From 9b6c91918e1b80290f434018f4096d83a40f1e2c Mon Sep 17 00:00:00 2001 From: Jason Sandlin Date: Tue, 22 Nov 2016 17:10:54 -0800 Subject: [PATCH] Init --- .gitattributes | 63 + .gitignore | 111 + .gitmodules | 3 + .../Build.Durango.Cpp.props | 29 + .../Microsoft.Xbox.Services.110.XDK.Cpp.sln | 30 + ...icrosoft.Xbox.Services.110.XDK.Cpp.vcxproj | 386 ++ ....Xbox.Services.110.XDK.Cpp.vcxproj.filters | 903 ++++ ...crosoft.Xbox.Services.110.XDK.Ship.Cpp.sln | 26 + ...oft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj | 174 + ....Services.110.XDK.Ship.Cpp.vcxproj.filters | 261 + .../build.cpp | 207 + .../Microsoft.Xbox.Services.140.UWP.Cpp.sln | 52 + ...icrosoft.Xbox.Services.140.UWP.Cpp.vcxproj | 409 ++ ....Xbox.Services.140.UWP.Cpp.vcxproj.filters | 915 ++++ ...crosoft.Xbox.Services.140.UWP.Ship.Cpp.sln | 34 + ...oft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj | 162 + ....Services.140.UWP.Ship.Cpp.vcxproj.filters | 92 + .../build.cpp | 206 + .../Microsoft.Xbox.Services.140.UWP.WinRT.sln | 59 + ...rosoft.Xbox.Services.140.UWP.WinRT.vcxproj | 779 +++ ...box.Services.140.UWP.WinRT.vcxproj.filters | 2063 ++++++++ .../Build.Durango.Cpp.props | 29 + .../Microsoft.Xbox.Services.140.XDK.Cpp.sln | 28 + ...icrosoft.Xbox.Services.140.XDK.Cpp.vcxproj | 398 ++ ....Xbox.Services.140.XDK.Cpp.vcxproj.filters | 919 ++++ ...oft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj | 165 + ....Services.140.XDK.Ship.Cpp.vcxproj.filters | 233 + .../build.cpp | 197 + .../Build.Durango.Cpp.props | 29 + .../Microsoft.Xbox.Services.140.XDK.WinRT.sln | 31 + ...rosoft.Xbox.Services.140.XDK.WinRT.vcxproj | 782 +++ ...box.Services.140.XDK.WinRT.vcxproj.filters | 2106 ++++++++ .../Microsoft.Xbox.Services.Android/.project | 17 + .../.settings/org.eclipse.jdt.core.prefs | 6 + .../Microsoft.Xbox.Services.Android.sln | 42 + .../Microsoft.Xbox.Services.Android.vcxproj | 501 ++ ...soft.Xbox.Services.Android.vcxproj.filters | 1125 +++++ ...Xbox.Services.UnitTest.140.Shared.vcxitems | 706 +++ ...vices.UnitTest.140.Shared.vcxitems.filters | 2193 +++++++++ ...rosoft.Xbox.Services.UnitTest.140.TAEF.sln | 54 + ...ft.Xbox.Services.UnitTest.140.TAEF.vcxproj | 256 + ...Services.UnitTest.140.TAEF.vcxproj.filters | 204 + ...icrosoft.Xbox.Services.UnitTest.140.TE.sln | 54 + ...soft.Xbox.Services.UnitTest.140.TE.vcxproj | 343 ++ ...x.Services.UnitTest.140.TE.vcxproj.filters | 205 + .../TestAll.runsettings | 38 + .../TestMultiplayerManager.runsettings | 38 + .../TestSocialManager.runsettings | 38 + .../project.pbxproj | 2046 ++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/XboxLiveServices.xccheckout | 41 + .../xcschemes/XboxLiveServices.xcscheme | 80 + .../XboxLiveServicesResources.xcscheme | 80 + .../XboxLiveServicesResources/Info.plist | 28 + CONTRIBUTING.md | 31 + External/cpprestsdk/.gitignore | 68 + .../cpprestsdk/Build/Build.Durango.Cpp.props | 29 + .../Build/Common.Build.Traversal.targets | 28 + .../cpprestsdk/Build/Common.Build.settings | 244 + .../Build/Config.Definitions.Durango.props | 13 + .../cpprestsdk/Build/Config.Definitions.props | 29 + .../cpprestsdk/Build/Release.Product.settings | 64 + .../cpprestsdk/Build/Release.Tests.settings | 27 + External/cpprestsdk/Build/version.props | 11 + .../Build_android/boost-for-android-x86.patch | 173 + .../Build_android/boost-for-android.patch | 175 + .../Boost-for-Android-x86/.gitattributes | 2 + .../build/Boost-for-Android-x86/.gitignore | 7 + .../build/Boost-for-Android-x86/README.md | 96 + .../Boost-for-Android-x86/build-android.bat | 10 + .../Boost-for-Android-x86/build-android.sh | 435 ++ .../Boost-for-Android-x86/build-common.sh | 671 +++ .../configs/user-config-boost-1_45_0.jam | 269 ++ .../configs/user-config-boost-1_48_0.jam | 231 + .../configs/user-config-boost-1_49_0.jam | 273 ++ .../configs/user-config-boost-1_53_0.jam | 130 + .../configs/user-config-boost-1_54_0.jam | 186 + .../configs/user-config-boost-1_55_0.jam | 139 + .../configs/user-config-boost-1_59_0.jam | 139 + .../cpprestsdk.patched.stamp | 0 .../patches/boost-1_45_0/address_v6.ipp.patch | 26 + .../patches/boost-1_45_0/android.jam.patch | 1067 +++++ .../patches/boost-1_45_0/android.py.patch | 801 ++++ .../patches/boost-1_45_0/endian.hpp.patch | 12 + .../boost-1_45_0/fenced_block.hpp.patch | 38 + .../patches/boost-1_45_0/operations.cpp.patch | 39 + .../boost-1_45_0/socket_types.hpp.patch | 15 + .../patches/boost-1_45_0/user.hpp.patch | 18 + .../boost-1_45_0/v2_operations.cpp.patch | 31 + .../patches/boost-1_45_0/workaround.hpp.patch | 11 + .../patches/boost-1_48_0/boost-1_48_0.patch | 2069 ++++++++ .../patches/boost-1_49_0/boost-1_49_0.patch | 2099 ++++++++ .../patches/boost-1_53_0/boost-1_53_0.patch | 138 + .../patches/boost-1_54_0/boost-1_54_0.patch | 2008 ++++++++ .../patches/boost-1_55_0/boost-1_55_0.patch | 125 + .../build/Boost-for-Android/.gitattributes | 2 + .../build/Boost-for-Android/.gitignore | 7 + .../build/Boost-for-Android/README.md | 96 + .../build/Boost-for-Android/build-android.bat | 10 + .../build/Boost-for-Android/build-android.sh | 435 ++ .../build/Boost-for-Android/build-common.sh | 671 +++ .../configs/user-config-boost-1_45_0.jam | 269 ++ .../configs/user-config-boost-1_48_0.jam | 231 + .../configs/user-config-boost-1_49_0.jam | 273 ++ .../configs/user-config-boost-1_53_0.jam | 130 + .../configs/user-config-boost-1_54_0.jam | 186 + .../configs/user-config-boost-1_55_0.jam | 147 + .../configs/user-config-boost-1_59_0.jam | 147 + .../cpprestsdk.patched.stamp | 0 .../patches/boost-1_45_0/address_v6.ipp.patch | 26 + .../patches/boost-1_45_0/android.jam.patch | 1067 +++++ .../patches/boost-1_45_0/android.py.patch | 801 ++++ .../patches/boost-1_45_0/endian.hpp.patch | 12 + .../boost-1_45_0/fenced_block.hpp.patch | 38 + .../patches/boost-1_45_0/operations.cpp.patch | 39 + .../boost-1_45_0/socket_types.hpp.patch | 15 + .../patches/boost-1_45_0/user.hpp.patch | 18 + .../boost-1_45_0/v2_operations.cpp.patch | 31 + .../patches/boost-1_45_0/workaround.hpp.patch | 11 + .../patches/boost-1_48_0/boost-1_48_0.patch | 2069 ++++++++ .../patches/boost-1_49_0/boost-1_49_0.patch | 2099 ++++++++ .../patches/boost-1_53_0/boost-1_53_0.patch | 138 + .../patches/boost-1_54_0/boost-1_54_0.patch | 2008 ++++++++ .../patches/boost-1_55_0/boost-1_55_0.patch | 125 + .../cpprestsdk/Build_android/configure.sh | 283 ++ .../Build_android/libiconv/jni/Android.mk | 23 + .../Build_android/libiconv/jni/Application.mk | 3 + .../Build_android/libiconv/libiconv.patch | 22 + .../cpprestsdk/Build_android/openssl/Makefile | 61 + External/cpprestsdk/Build_iOS/.gitignore | 6 + External/cpprestsdk/Build_iOS/CMakeLists.txt | 179 + .../Casablanca.xcodeproj/project.pbxproj | 636 +++ .../contents.xcworkspacedata | 7 + External/cpprestsdk/Build_iOS/README.md | 1 + External/cpprestsdk/Build_iOS/configure.sh | 31 + .../Build_iOS/fix_boost_building_script.patch | 13 + .../Build_iOS/fix_boost_version.patch | 186 + .../Build_iOS/fix_ios_cmake_compiler.patch | 15 + External/cpprestsdk/CONTRIBUTORS.txt | 47 + External/cpprestsdk/README.md | 34 + External/cpprestsdk/ThirdPartyNotices.txt | 159 + External/cpprestsdk/build.root | 1 + External/cpprestsdk/casablanca110.Xbox.sln | 22 + External/cpprestsdk/cpprestsdk120.nonuget | 0 External/cpprestsdk/cpprestsdk120.sln | 321 ++ External/cpprestsdk/cpprestsdk140.nonuget | 0 External/cpprestsdk/cpprestsdk140.sln | 292 ++ External/cpprestsdk/license.txt | 25 + External/cpprestsdk/setup_ps_env_VS2013.ps1 | 22 + External/cpprestsdk/setup_ps_env_VS2015.ps1 | 17 + Include/xsapi/achievements.h | 810 ++++ Include/xsapi/contextual_search_service.h | 800 ++++ Include/xsapi/entertainment_profile.h | 147 + Include/xsapi/errors.h | 1523 ++++++ Include/xsapi/events.h | 100 + Include/xsapi/game_server_platform.h | 920 ++++ Include/xsapi/http_call.h | 362 ++ Include/xsapi/http_call_request_message.h | 77 + Include/xsapi/leaderboard.h | 584 +++ Include/xsapi/marketplace.h | 1487 ++++++ Include/xsapi/matchmaking.h | 324 ++ Include/xsapi/mem.h | 145 + Include/xsapi/multiplayer.h | 4243 ++++++++++++++++ Include/xsapi/multiplayer_manager.h | 1638 +++++++ Include/xsapi/notification_helper.h | 35 + Include/xsapi/presence.h | 876 ++++ Include/xsapi/privacy.h | 309 ++ Include/xsapi/profile.h | 191 + Include/xsapi/real_time_activity.h | 386 ++ Include/xsapi/service_call_logging_config.h | 55 + Include/xsapi/services.h | 45 + Include/xsapi/social.h | 653 +++ Include/xsapi/social_manager.h | 928 ++++ Include/xsapi/system.h | 718 +++ Include/xsapi/title_callable_ui.h | 407 ++ Include/xsapi/title_storage.h | 753 +++ Include/xsapi/types.h | 180 + Include/xsapi/user_statistics.h | 449 ++ Include/xsapi/xbox_cll.h | 32 + Include/xsapi/xbox_live_app_config.h | 321 ++ Include/xsapi/xbox_live_context.h | 258 + Include/xsapi/xbox_live_context_settings.h | 328 ++ .../xbox_service_call_routed_event_args.h | 141 + LICENSE.md | 11 + README.md | 29 +- .../WinRT/AchievementMediaAssetType_WinRT.h | 30 + .../WinRT/AchievementOrderBy_WinRT.h | 27 + .../WinRT/AchievementProgression_WinRT.cpp | 43 + .../WinRT/AchievementProgression_WinRT.h | 43 + .../WinRT/AchievementRequirement_WinRT.h | 49 + .../WinRT/AchievementRewardType_WinRT.h | 30 + .../WinRT/AchievementService_WinRT.cpp | 121 + .../WinRT/AchievementService_WinRT.h | 135 + .../WinRT/AchievementType_WinRT.h | 33 + .../Achievements/WinRT/Achievement_WinRT.cpp | 79 + .../Achievements/WinRT/Achievement_WinRT.h | 148 + .../WinRT/AchievementsResult_WinRT.cpp | 55 + .../WinRT/AchievementsResult_WinRT.h | 61 + .../Achievements/WinRT/MediaAsset_WinRT.cpp | 31 + .../Achievements/WinRT/MediaAsset_WinRT.h | 46 + .../WinRT/ParticipationType_WinRT.h | 27 + .../Achievements/WinRT/ProgressState_WinRT.h | 30 + .../Achievements/WinRT/Reward_WinRT.cpp | 58 + .../Achievements/WinRT/Reward_WinRT.h | 75 + .../Achievements/WinRT/TimeWindow_WinRT.cpp | 27 + .../Achievements/WinRT/TimeWindow_WinRT.h | 41 + .../WinRT/TitleAssociation_WinRT.h | 41 + Source/Services/Achievements/achievement.cpp | 263 + .../Achievements/achievement_media_asset.cpp | 87 + .../Achievements/achievement_progression.cpp | 59 + .../Achievements/achievement_requirement.cpp | 71 + .../Achievements/achievement_reward.cpp | 115 + .../Achievements/achievement_service.cpp | 586 +++ .../Achievements/achievement_time_window.cpp | 59 + .../achievement_title_association.cpp | 59 + .../Achievements/achievements_result.cpp | 109 + .../Desktop/XboxLiveContext_Desktop.cpp | 206 + Source/Services/Common/Desktop/dllmain.cpp | 19 + Source/Services/Common/Desktop/pch.cpp | 1 + Source/Services/Common/Desktop/pch.h | 8 + .../Server/xbox_live_context_server.cpp | 47 + .../Server/xbox_live_context_server_impl.cpp | 60 + .../Server/xbox_live_context_server_impl.h | 56 + Source/Services/Common/Unix/pch.cpp | 1 + Source/Services/Common/Unix/pch.h | 11 + Source/Services/Common/Unix/pch_unix.cpp | 1 + Source/Services/Common/Unix/pch_unix.h | 11 + .../Common/WinRT/XboxLiveContext_WinRT.cpp | 291 ++ .../Common/WinRT/XboxLiveContext_WinRT.h | 216 + Source/Services/Common/WinRT/pch.cpp | 10 + Source/Services/Common/WinRT/pch.h | 22 + Source/Services/Common/iOS/pch.cpp | 1 + Source/Services/Common/iOS/pch.h | 5 + Source/Services/Common/pch_common.h | 75 + .../Common/xbox_live_context_impl.cpp | 386 ++ .../Services/Common/xbox_live_context_impl.h | 222 + ...entProfileListContainsItemResult_WinRT.cpp | 24 + ...nmentProfileListContainsItemResult_WinRT.h | 42 + .../EntertainmentProfileListService_WinRT.cpp | 29 + .../EntertainmentProfileListService_WinRT.h | 36 + ...tertainmentProfileListVideoQueue_WinRT.cpp | 93 + ...EntertainmentProfileListVideoQueue_WinRT.h | 76 + .../entertainment_profile.cpp | 35 + ...ment_profile_list_contains_item_result.cpp | 56 + ...tertainment_profile_list_xbox_one_pins.cpp | 230 + .../Events/WinRT/EventsService_WinRT.cpp | 54 + .../Events/WinRT/EventsService_WinRT.h | 75 + Source/Services/Events/events_service.cpp | 346 ++ .../WinRT/AllocationResult_WinRT.cpp | 36 + .../WinRT/AllocationResult_WinRT.h | 64 + .../WinRT/ClusterResult_WinRT.cpp | 38 + .../WinRT/ClusterResult_WinRT.h | 65 + .../WinRT/GameServerFulfillmentState_WinRT.h | 31 + .../WinRT/GameServerHostStatus_WinRT.h | 34 + .../WinRT/GameServerImageSet_WinRT.cpp | 35 + .../WinRT/GameServerImageSet_WinRT.h | 89 + .../WinRT/GameServerMetadataResult_WinRT.cpp | 49 + .../WinRT/GameServerMetadataResult_WinRT.h | 85 + .../WinRT/GameServerPlatformService_WinRT.cpp | 205 + .../WinRT/GameServerPlatformService_WinRT.h | 170 + .../WinRT/GameServerPortMapping_WinRT.cpp | 24 + .../WinRT/GameServerPortMapping_WinRT.h | 63 + .../WinRT/GameServerTicketStatus_WinRT.cpp | 37 + .../WinRT/GameServerTicketStatus_WinRT.h | 98 + .../WinRT/GameVariantSchema_WinRT.cpp | 24 + .../WinRT/GameVariantSchema_WinRT.h | 52 + .../WinRT/GameVariant_WinRT.cpp | 24 + .../WinRT/GameVariant_WinRT.h | 75 + .../WinRT/QualityOfServiceServer_WinRT.cpp | 30 + .../WinRT/QualityOfServiceServer_WinRT.h | 65 + .../GameServerPlatform/allocation_result.cpp | 143 + .../GameServerPlatform/cluster_result.cpp | 125 + .../game_server_image_set.cpp | 131 + .../game_server_metadata_result.cpp | 92 + .../game_server_platform_service.cpp | 501 ++ .../game_server_port_mapping.cpp | 80 + .../game_server_ticket_status.cpp | 161 + .../GameServerPlatform/game_variant.cpp | 107 + .../game_variant_schema.cpp | 68 + .../quality_of_service_server.cpp | 69 + .../Leaderboard/WinRT/LeaderboardColumn.cpp | 48 + .../Leaderboard/WinRT/LeaderboardColumn.h | 53 + .../Leaderboard/WinRT/LeaderboardResult.cpp | 67 + .../Leaderboard/WinRT/LeaderboardResult.h | 88 + .../Leaderboard/WinRT/LeaderboardRow.cpp | 40 + .../Leaderboard/WinRT/LeaderboardRow.h | 62 + .../Leaderboard/WinRT/LeaderboardService.cpp | 364 ++ .../Leaderboard/WinRT/LeaderboardService.h | 533 +++ .../Leaderboard/leaderboard_column.cpp | 42 + .../Services/Leaderboard/leaderboard_query.h | 36 + .../Leaderboard/leaderboard_result.cpp | 179 + .../Services/Leaderboard/leaderboard_row.cpp | 60 + .../Leaderboard/leaderboard_serializers.cpp | 134 + .../Leaderboard/leaderboard_serializers.h | 31 + .../Leaderboard/leaderboard_service.cpp | 534 +++ .../WinRT/BrowseCatalogResult_WinRT.cpp | 48 + .../WinRT/BrowseCatalogResult_WinRT.h | 80 + .../WinRT/BundleRelationshipType_WinRT.h | 27 + .../WinRT/CatalogItemAvailability_WinRT.cpp | 30 + .../WinRT/CatalogItemAvailability_WinRT.h | 130 + .../WinRT/CatalogItemDetails_WinRT.cpp | 40 + .../WinRT/CatalogItemDetails_WinRT.h | 178 + .../WinRT/CatalogItemImage_WinRT.cpp | 32 + .../WinRT/CatalogItemImage_WinRT.h | 73 + .../Marketplace/WinRT/CatalogItem_WinRT.cpp | 40 + .../Marketplace/WinRT/CatalogItem_WinRT.h | 150 + .../WinRT/CatalogService_WinRT.cpp | 109 + .../Marketplace/WinRT/CatalogService_WinRT.h | 86 + .../WinRT/CatalogSortOrder_WinRT.h | 47 + .../Marketplace/WinRT/CatalogTotal_WinRT.cpp | 23 + .../Marketplace/WinRT/CatalogTotal_WinRT.h | 31 + .../ConsumeInventoryItemResult_WinRT.cpp | 22 + .../WinRT/ConsumeInventoryItemResult_WinRT.h | 42 + .../WinRT/InventoryItemAvailability_WinRT.h | 33 + .../WinRT/InventoryItemState_WinRT.h | 36 + .../Marketplace/WinRT/InventoryItem_WinRT.cpp | 42 + .../Marketplace/WinRT/InventoryItem_WinRT.h | 100 + .../WinRT/InventoryItemsResult_WinRT.cpp | 51 + .../WinRT/InventoryItemsResult_WinRT.h | 59 + .../WinRT/InventoryService_WinRT.cpp | 294 ++ .../WinRT/InventoryService_WinRT.h | 220 + .../Marketplace/WinRT/MediaItemType_WinRT.h | 63 + .../Marketplace/browse_catalog_result.cpp | 164 + Source/Services/Marketplace/catalog_item.cpp | 156 + .../Marketplace/catalog_item_availability.cpp | 195 + .../Marketplace/catalog_item_details.cpp | 144 + .../Marketplace/catalog_item_image.cpp | 86 + .../Services/Marketplace/catalog_service.cpp | 632 +++ Source/Services/Marketplace/catalog_total.cpp | 46 + .../consume_inventory_item_request.cpp | 53 + .../consume_inventory_item_result.cpp | 62 + .../Services/Marketplace/inventory_item.cpp | 209 + .../Marketplace/inventory_items_result.cpp | 137 + .../Marketplace/inventory_service.cpp | 462 ++ .../WinRT/CreateMatchTicketResponse_WinRT.h | 44 + .../WinRT/HopperStatisticsResponse_WinRT.h | 49 + .../MatchTicketDetailsResponse_WinRT.cpp | 61 + .../WinRT/MatchTicketDetailsResponse_WinRT.h | 74 + .../WinRT/MatchmakingService_WinRT.cpp | 129 + .../WinRT/MatchmakingService_WinRT.h | 101 + .../WinRT/PreserveSessionMode_WinRT.h | 38 + .../Matchmaking/WinRT/TicketStatus_WinRT.h | 50 + .../create_match_ticket_response.cpp | 60 + .../hopper_statistics_response.cpp | 74 + .../match_ticket_details_response.cpp | 149 + .../Matchmaking/matchmaking_service.cpp | 257 + .../Misc/Android/title_callable_static_glue.h | 2 + .../Android/title_callable_ui_android.cpp | 406 ++ .../Misc/Android/title_callable_ui_jni.h | 11 + .../Android/title_callable_ui_static_glue.cpp | 38 + .../Services/Misc/UWP/title_callable_ui.cpp | 719 +++ .../Unix/notification_service_android.cpp | 161 + .../Misc/Unix/notification_service_i.mm | 62 + .../WinRT/ContextualSearchBroadcast_WinRT.cpp | 41 + .../WinRT/ContextualSearchBroadcast_WinRT.h | 65 + .../ContextualSearchConfiguredStat_WinRT.cpp | 42 + .../ContextualSearchConfiguredStat_WinRT.h | 84 + .../ContextualSearchFilterOperator_WinRT.h | 37 + .../ContextualSearchGameClipStat_WinRT.cpp | 30 + .../ContextualSearchGameClipStat_WinRT.h | 57 + ...ontextualSearchGameClipThumbnail_WinRT.cpp | 30 + .../ContextualSearchGameClipThumbnail_WinRT.h | 56 + .../ContextualSearchGameClipUriInfo_WinRT.cpp | 30 + .../ContextualSearchGameClipUriInfo_WinRT.h | 68 + .../WinRT/ContextualSearchGameClip_WinRT.cpp | 52 + .../WinRT/ContextualSearchGameClip_WinRT.h | 102 + .../ContextualSearchGameClipsResult_WinRT.cpp | 53 + .../ContextualSearchGameClipsResult_WinRT.h | 43 + .../WinRT/ContextualSearchService_WinRT.cpp | 186 + .../WinRT/ContextualSearchService_WinRT.h | 187 + .../ContextualSearchStatDisplayType_WinRT.h | 32 + .../ContextualSearchStatVisibility_WinRT.h | 29 + .../Misc/WinRT/StringService_WinRT.cpp | 73 + .../Services/Misc/WinRT/StringService_WinRT.h | 58 + .../Misc/WinRT/TitleCallableUI_WinRT.cpp | 302 ++ .../Misc/WinRT/TitleCallableUI_WinRT.h | 328 ++ .../Misc/WinRT/VerifyStringResultCode_WinRT.h | 33 + .../Misc/WinRT/VerifyStringResult_WinRT.h | 45 + .../Misc/WinRT/XboxLiveHttpCall_WinRT.cpp | 202 + .../Misc/WinRT/XboxLiveHttpCall_WinRT.h | 181 + .../Windows/notification_service_windows.cpp | 157 + .../Misc/contextual_config_result.cpp | 375 ++ .../Services/Misc/contextual_config_result.h | 143 + .../Misc/contextual_search_broadcast.cpp | 97 + .../contextual_search_configured_stat.cpp | 100 + .../Misc/contextual_search_game_clip.cpp | 151 + .../Misc/contextual_search_game_clip_stat.cpp | 78 + .../contextual_search_game_clip_thumbnail.cpp | 76 + .../contextual_search_game_clip_uri_info.cpp | 95 + .../contextual_search_game_clips_result.cpp | 79 + .../Misc/contextual_search_service.cpp | 393 ++ .../Services/Misc/iOS/notification_helper.mm | 105 + Source/Services/Misc/iOS/title_callable_ui.mm | 191 + Source/Services/Misc/notification_service.cpp | 249 + Source/Services/Misc/notification_service.h | 134 + Source/Services/Misc/string_service.cpp | 103 + Source/Services/Misc/verify_string_result.cpp | 56 + .../FindMatchCompletedEventArgs_WinRT.cpp | 32 + .../WinRT/FindMatchCompletedEventArgs_WinRT.h | 47 + .../WinRT/HostChangedEventArgs_WinRT.cpp | 38 + .../WinRT/HostChangedEventArgs_WinRT.h | 43 + .../Manager/WinRT/JoinInProgressState_WinRT.h | 48 + .../JoinLobbyCompletedEventArgs_WinRT.cpp | 32 + .../WinRT/JoinLobbyCompletedEventArgs_WinRT.h | 45 + .../Manager/WinRT/MatchStatus_WinRT.h | 110 + .../WinRT/MemberJoinedEventArgs_WinRT.cpp | 41 + .../WinRT/MemberJoinedEventArgs_WinRT.h | 43 + .../WinRT/MemberLeftEventArgs_WinRT.cpp | 41 + .../Manager/WinRT/MemberLeftEventArgs_WinRT.h | 43 + .../MemberPropertyChangedEventArgs_WinRT.cpp | 38 + .../MemberPropertyChangedEventArgs_WinRT.h | 48 + .../WinRT/MultiplayerEventArgs_WinRT.h | 18 + .../WinRT/MultiplayerEventType_WinRT.h | 161 + .../Manager/WinRT/MultiplayerEvent_WinRT.cpp | 170 + .../Manager/WinRT/MultiplayerEvent_WinRT.h | 82 + .../WinRT/MultiplayerGameSession_WinRT.cpp | 150 + .../WinRT/MultiplayerGameSession_WinRT.h | 157 + .../WinRT/MultiplayerLobbySession_WinRT.cpp | 288 ++ .../WinRT/MultiplayerLobbySession_WinRT.h | 268 ++ .../WinRT/MultiplayerManager_WinRT.cpp | 323 ++ .../Manager/WinRT/MultiplayerManager_WinRT.h | 279 ++ .../Manager/WinRT/MultiplayerMember_WinRT.cpp | 38 + .../Manager/WinRT/MultiplayerMember_WinRT.h | 93 + .../WinRT/MultiplayerSessionType_WinRT.h | 35 + .../PerformQosMeasurementsEventArgs_WinRT.cpp | 47 + .../PerformQosMeasurementsEventArgs_WinRT.h | 44 + .../SessionPropertyChangedEventArgs_WinRT.cpp | 32 + .../SessionPropertyChangedEventArgs_WinRT.h | 39 + ...rnamentGameSessionReadyEventArgs_WinRT.cpp | 32 + ...ournamentGameSessionReadyEventArgs_WinRT.h | 39 + ...egistrationStateChangedEventArgs_WinRT.cpp | 32 + ...tRegistrationStateChangedEventArgs_WinRT.h | 47 + .../WinRT/UserAddedEventArgs_WinRT.cpp | 32 + .../Manager/WinRT/UserAddedEventArgs_WinRT.h | 39 + .../WinRT/UserRemovedEventArgs_WinRT.cpp | 32 + .../WinRT/UserRemovedEventArgs_WinRT.h | 39 + .../find_match_completed_event_args.cpp | 39 + .../Manager/host_changed_event_args.cpp | 30 + .../join_lobby_completed_event_args.cpp | 28 + .../Manager/member_joined_event_args.cpp | 30 + .../Manager/member_left_event_args.cpp | 30 + .../member_property_changed_event_args.cpp | 38 + .../Manager/multiplayer_client_manager.cpp | 1220 +++++ .../multiplayer_client_pending_reader.cpp | 460 ++ .../multiplayer_client_pending_request.cpp | 270 ++ .../Multiplayer/Manager/multiplayer_event.cpp | 70 + .../Manager/multiplayer_game_client.cpp | 784 +++ .../Manager/multiplayer_game_session.cpp | 180 + .../Manager/multiplayer_lobby_client.cpp | 1418 ++++++ .../Manager/multiplayer_lobby_session.cpp | 276 ++ .../Manager/multiplayer_local_user.cpp | 199 + .../multiplayer_local_user_manager.cpp | 521 ++ .../Manager/multiplayer_manager.cpp | 388 ++ .../Manager/multiplayer_manager_internal.h | 1227 +++++ .../Manager/multiplayer_manager_utils.cpp | 324 ++ .../Manager/multiplayer_match_client.cpp | 725 +++ .../Manager/multiplayer_member.cpp | 133 + .../Manager/multiplayer_session_writer.cpp | 565 +++ .../perform_qos_measurements_event_args.cpp | 30 + .../session_property_changed_event_args.cpp | 30 + ...urnament_game_session_ready_event_args.cpp | 32 + ..._registration_state_changed_event_args.cpp | 40 + .../Manager/user_added_event_args.cpp | 30 + .../Manager/user_removed_event_args.cpp | 30 + .../WinRT/MatchmakingStatus_WinRT.h | 49 + .../WinRT/MultiplayMetrics_WinRT.h | 45 + .../MultiplayerActivityDetails_WinRT.cpp | 30 + .../WinRT/MultiplayerActivityDetails_WinRT.h | 79 + .../MultiplayerGetSessionsRequest_WinRT.cpp | 62 + .../MultiplayerGetSessionsRequest_WinRT.h | 105 + .../MultiplayerInitializationStage_WinRT.h | 54 + ...MultiplayerManagedInitialization_WinRT.cpp | 28 + .../MultiplayerManagedInitialization_WinRT.h | 90 + .../MultiplayerMeasurementFailure_WinRT.h | 65 + .../MultiplayerMemberInitialization_WinRT.cpp | 28 + .../MultiplayerMemberInitialization_WinRT.h | 90 + ...ultiplayerPeerToHostRequirements_WinRT.cpp | 26 + .../MultiplayerPeerToHostRequirements_WinRT.h | 66 + ...ultiplayerPeerToPeerRequirements_WinRT.cpp | 26 + .../MultiplayerPeerToPeerRequirements_WinRT.h | 50 + ...ayerQualityOfServiceMeasurements_WinRT.cpp | 50 + ...playerQualityOfServiceMeasurements_WinRT.h | 87 + ...tiplayerQuerySearchHandleRequest_WinRT.cpp | 46 + ...ultiplayerQuerySearchHandleRequest_WinRT.h | 73 + .../WinRT/MultiplayerRoleInfo_WinRT.cpp | 44 + .../WinRT/MultiplayerRoleInfo_WinRT.h | 67 + .../WinRT/MultiplayerRoleType_WinRT.cpp | 63 + .../WinRT/MultiplayerRoleType_WinRT.h | 63 + .../MultiplayerSearchHandleDetails_WinRT.cpp | 81 + .../MultiplayerSearchHandleDetails_WinRT.h | 120 + .../MultiplayerSearchHandleRequest_WinRT.cpp | 102 + .../MultiplayerSearchHandleRequest_WinRT.h | 78 + ...tiplayerServiceMatchmakingServer_WinRT.cpp | 32 + ...ultiplayerServiceMatchmakingServer_WinRT.h | 52 + .../WinRT/MultiplayerService_WinRT.cpp | 756 +++ .../WinRT/MultiplayerService_WinRT.h | 613 +++ ...tiplayerSessionArbitrationServer_WinRT.cpp | 38 + ...ultiplayerSessionArbitrationServer_WinRT.h | 54 + .../MultiplayerSessionCapabilities_WinRT.cpp | 38 + .../MultiplayerSessionCapabilities_WinRT.h | 117 + ...ultiplayerSessionChangeEventArgs_WinRT.cpp | 29 + .../MultiplayerSessionChangeEventArgs_WinRT.h | 46 + .../WinRT/MultiplayerSessionChangeTypes.h | 79 + .../MultiplayerSessionConstants_WinRT.cpp | 59 + .../WinRT/MultiplayerSessionConstants_WinRT.h | 293 ++ .../MultiplayerSessionMemberStatus_WinRT.h | 45 + .../WinRT/MultiplayerSessionMember_WinRT.cpp | 109 + .../WinRT/MultiplayerSessionMember_WinRT.h | 342 ++ .../MultiplayerSessionProperties_WinRT.cpp | 77 + .../MultiplayerSessionProperties_WinRT.h | 178 + .../MultiplayerSessionReference_WinRT.cpp | 70 + .../WinRT/MultiplayerSessionReference_WinRT.h | 91 + .../MultiplayerSessionRestriction_WinRT.h | 47 + .../MultiplayerSessionRoleTypes_WinRT.cpp | 34 + .../WinRT/MultiplayerSessionRoleTypes_WinRT.h | 40 + .../WinRT/MultiplayerSessionStates_WinRT.cpp | 43 + .../WinRT/MultiplayerSessionStates_WinRT.h | 115 + .../WinRT/MultiplayerSessionStatus_WinRT.h | 40 + ...tiplayerSessionTournamentsServer_WinRT.cpp | 63 + ...ultiplayerSessionTournamentsServer_WinRT.h | 94 + .../MultiplayerSessionVisibility_WinRT.h | 52 + .../WinRT/MultiplayerSessionWriteMode_WinRT.h | 41 + .../WinRT/MultiplayerSession_WinRT.cpp | 767 +++ .../WinRT/MultiplayerSession_WinRT.h | 1300 +++++ ...iplayerSubscriptionLostEventArgs_WinRT.cpp | 19 + ...ltiplayerSubscriptionLostEventArgs_WinRT.h | 24 + .../WinRT/MutableRoleSetting_WinRT.h | 30 + .../NetworkAddressTranslationSetting_WinRT.h | 40 + .../WinRT/WriteSessionResult_WinRT.cpp | 45 + .../WinRT/WriteSessionResult_WinRT.h | 58 + .../WinRT/WriteSessionStatus_WinRT.h | 61 + .../multiplayer_activity_details.cpp | 127 + ...ltiplayer_activity_handle_post_request.cpp | 55 + ...ultiplayer_activity_query_post_request.cpp | 91 + .../multiplayer_get_sessions_request.cpp | 165 + .../Multiplayer/multiplayer_internal.h | 477 ++ .../Multiplayer/multiplayer_invite.cpp | 40 + ...multiplayer_invite_handle_post_request.cpp | 105 + .../multiplayer_managed_initialization.cpp | 122 + .../multiplayer_member_initialization.cpp | 122 + .../multiplayer_peer_to_host_requirements.cpp | 98 + .../multiplayer_peer_to_peer_requirements.cpp | 64 + ...iplayer_quality_of_service_measurement.cpp | 95 + ...ultiplayer_query_search_handle_request.cpp | 141 + .../Multiplayer/multiplayer_role_info.cpp | 84 + .../Multiplayer/multiplayer_role_type.cpp | 102 + .../multiplayer_search_handle_details.cpp | 190 + .../multiplayer_search_handle_request.cpp | 123 + .../Multiplayer/multiplayer_service.cpp | 1206 +++++ .../Multiplayer/multiplayer_service_impl.cpp | 269 ++ .../Multiplayer/multiplayer_session.cpp | 1638 +++++++ ...multiplayer_session_arbitration_server.cpp | 135 + .../multiplayer_session_capabilities.cpp | 185 + .../multiplayer_session_change_event_args.cpp | 44 + .../multiplayer_session_constants.cpp | 739 +++ ...multiplayer_session_matchmaking_server.cpp | 104 + .../multiplayer_session_member.cpp | 826 ++++ .../multiplayer_session_member_request.cpp | 576 +++ .../multiplayer_session_properties.cpp | 325 ++ .../multiplayer_session_reference.cpp | 146 + .../multiplayer_session_request.cpp | 688 +++ .../multiplayer_session_role_types.cpp | 51 + .../multiplayer_session_states.cpp | 224 + ...multiplayer_session_tournaments_server.cpp | 253 + .../Multiplayer/multiplayer_subscription.cpp | 178 + ...ltiplayer_transfer_handle_post_request.cpp | 65 + .../DevicePresenceChangeEventArgs_WinRT.cpp | 22 + .../DevicePresenceChangeEventArgs_WinRT.h | 45 + ...DevicePresenceChangeSubscription_WinRT.cpp | 35 + .../DevicePresenceChangeSubscription_WinRT.h | 51 + .../WinRT/PresenceBroadcastRecord_WinRT.cpp | 22 + .../WinRT/PresenceBroadcastRecord_WinRT.h | 56 + .../Presence/WinRT/PresenceData_WinRT.cpp | 75 + .../Presence/WinRT/PresenceData_WinRT.h | 73 + .../WinRT/PresenceDetailLevel_WinRT.h | 33 + .../WinRT/PresenceDeviceRecord_WinRT.cpp | 32 + .../WinRT/PresenceDeviceRecord_WinRT.h | 37 + .../Presence/WinRT/PresenceDeviceType_WinRT.h | 48 + .../WinRT/PresenceMediaIdType_WinRT.h | 27 + .../WinRT/PresenceMediaRecord_WinRT.cpp | 22 + .../WinRT/PresenceMediaRecord_WinRT.h | 44 + .../Presence/WinRT/PresenceRecord_WinRT.cpp | 38 + .../Presence/WinRT/PresenceRecord_WinRT.h | 52 + .../Presence/WinRT/PresenceService_WinRT.cpp | 418 ++ .../Presence/WinRT/PresenceService_WinRT.h | 226 + .../WinRT/PresenceTitleRecord_WinRT.cpp | 29 + .../WinRT/PresenceTitleRecord_WinRT.h | 67 + .../WinRT/PresenceTitleViewState_WinRT.h | 33 + .../TitlePresenceChangeEventArgs_WinRT.cpp | 22 + .../TitlePresenceChangeEventArgs_WinRT.h | 45 + .../TitlePresenceChangeSubscription_WinRT.cpp | 35 + .../TitlePresenceChangeSubscription_WinRT.h | 56 + .../Presence/WinRT/TitlePresenceState_WinRT.h | 33 + .../Presence/WinRT/UserPresenceState_WinRT.h | 31 + .../device_presence_change_event_args.cpp | 50 + .../device_presence_change_subscription.cpp | 154 + .../Services/Presence/media_presence_data.cpp | 72 + .../Presence/presence_activity_data.cpp | 55 + .../Presence/presence_broadcast_record.cpp | 88 + Source/Services/Presence/presence_data.cpp | 92 + .../Presence/presence_device_record.cpp | 203 + Source/Services/Presence/presence_internal.h | 307 ++ .../Presence/presence_media_record.cpp | 73 + Source/Services/Presence/presence_record.cpp | 115 + Source/Services/Presence/presence_service.cpp | 208 + .../Presence/presence_service_impl.cpp | 638 +++ .../Presence/presence_title_record.cpp | 160 + .../Presence/presence_title_request.cpp | 45 + .../Presence/presence_user_batch_request.cpp | 127 + Source/Services/Presence/presence_writer.cpp | 250 + .../title_presence_change_event_args.cpp | 51 + .../title_presence_change_subscription.cpp | 177 + .../MultiplePermissionsCheckResult_WinRT.cpp | 35 + .../MultiplePermissionsCheckResult_WinRT.h | 43 + .../WinRT/PermissionCheckResult_WinRT.cpp | 33 + .../WinRT/PermissionCheckResult_WinRT.h | 50 + .../WinRT/PermissionDenyReason_WinRT.cpp | 24 + .../WinRT/PermissionDenyReason_WinRT.h | 41 + .../WinRT/PermissionIdConstants_WinRT.cpp | 101 + .../WinRT/PermissionIdConstants_WinRT.h | 94 + .../Privacy/WinRT/PrivacyService_WinRT.cpp | 95 + .../Privacy/WinRT/PrivacyService_WinRT.h | 90 + .../multiple_permissions_check_result.cpp | 65 + .../Privacy/permission_check_result.cpp | 61 + .../Privacy/permission_deny_reason.cpp | 47 + Source/Services/Privacy/privacy_service.cpp | 320 ++ .../RealTimeActivityConnectionState_WinRT.h | 36 + .../RealTimeActivityResyncEventArgs_WinRT.cpp | 19 + .../RealTimeActivityResyncEventArgs_WinRT.h | 20 + .../WinRT/RealTimeActivityService_WinRT.cpp | 273 ++ .../WinRT/RealTimeActivityService_WinRT.h | 141 + ...tivitySubscriptionErrorEventArgs_WinRT.cpp | 57 + ...ActivitySubscriptionErrorEventArgs_WinRT.h | 57 + .../RealTimeActivitySubscriptionError_WinRT.h | 27 + .../RealTimeActivitySubscriptionState_WinRT.h | 46 + .../real_time_activity_internal.h | 43 + .../real_time_activity_service.cpp | 806 ++++ .../real_time_activity_service_factory.cpp | 93 + .../real_time_activity_subscription.cpp | 104 + ...activity_subscription_error_event_args.cpp | 45 + .../Manager/WinRT/PreferredColor_WinRT.cpp | 22 + .../Manager/WinRT/PreferredColor_WinRT.h | 45 + .../Manager/WinRT/SocialEventArgs_WinRT.h | 19 + .../Manager/WinRT/SocialEventType_WinRT.h | 45 + .../Manager/WinRT/SocialEvent_WinRT.cpp | 85 + .../Social/Manager/WinRT/SocialEvent_WinRT.h | 76 + .../SocialManagerExtraDetailLevel_WinRT.h | 32 + .../SocialManagerPresenceRecord_WinRT.cpp | 44 + .../WinRT/SocialManagerPresenceRecord_WinRT.h | 47 + ...SocialManagerPresenceTitleRecord_WinRT.cpp | 22 + .../SocialManagerPresenceTitleRecord_WinRT.h | 50 + .../Manager/WinRT/SocialManager_WinRT.cpp | 175 + .../Manager/WinRT/SocialManager_WinRT.h | 122 + .../SocialUserGroupLoadedEventArgs_WinRT.cpp | 33 + .../SocialUserGroupLoadedEventArgs_WinRT.h | 38 + .../Manager/WinRT/SocialUserGroupType_WinRT.h | 24 + .../Manager/WinRT/TitleHistory_WinRT.cpp | 22 + .../Social/Manager/WinRT/TitleHistory_WinRT.h | 38 + .../WinRT/XboxSocialUserGroup_WinRT.cpp | 77 + .../Manager/WinRT/XboxSocialUserGroup_WinRT.h | 86 + .../Manager/WinRT/XboxSocialUser_WinRT.cpp | 48 + .../Manager/WinRT/XboxSocialUser_WinRT.h | 101 + .../Social/Manager/internal_social_event.cpp | 185 + .../Social/Manager/peoplehub_service.cpp | 201 + .../Social/Manager/preferred_color.cpp | 76 + .../Services/Social/Manager/social_event.cpp | 76 + .../Services/Social/Manager/social_graph.cpp | 1803 +++++++ .../Social/Manager/social_manager.cpp | 509 ++ .../Social/Manager/social_manager_internal.h | 566 +++ .../social_manager_presence_record.cpp | 216 + .../social_manager_presence_title_record.cpp | 97 + .../social_user_group_loaded_event_args.cpp | 28 + .../Services/Social/Manager/title_history.cpp | 84 + .../Social/Manager/xbox_social_user.cpp | 216 + .../Social/Manager/xbox_social_user_group.cpp | 531 ++ .../Social/Manager/xbox_user_id_container.cpp | 33 + .../Social/WinRT/PresenceFilter_WinRT.h | 43 + .../Social/WinRT/ProfileService_WinRT.cpp | 94 + .../Social/WinRT/ProfileService_WinRT.h | 71 + .../Social/WinRT/RelationshipFilter_WinRT.h | 27 + .../WinRT/ReputationFeedbackType_WinRT.h | 144 + .../Social/WinRT/ReputationService_WinRT.cpp | 108 + .../Social/WinRT/ReputationService_WinRT.h | 119 + .../Social/WinRT/SocialGroupConstants_WinRT.h | 47 + .../WinRT/SocialNotificationType_WinRT.h | 37 + ...ocialRelationshipChangeEventArgs_WinRT.cpp | 33 + .../SocialRelationshipChangeEventArgs_WinRT.h | 39 + ...alRelationshipChangeSubscription_WinRT.cpp | 35 + ...cialRelationshipChangeSubscription_WinRT.h | 47 + .../Social/WinRT/SocialRelationship_WinRT.h | 29 + .../Social/WinRT/SocialService_WinRT.cpp | 177 + .../Social/WinRT/SocialService_WinRT.h | 121 + .../XboxSocialRelationshipResult_WinRT.cpp | 58 + .../XboxSocialRelationshipResult_WinRT.h | 58 + .../WinRT/XboxSocialRelationship_WinRT.cpp | 40 + .../WinRT/XboxSocialRelationship_WinRT.h | 58 + .../Social/WinRT/XboxUserProfile_WinRT.cpp | 28 + .../Social/WinRT/XboxUserProfile_WinRT.h | 81 + Source/Services/Social/profile_service.cpp | 219 + .../Social/reputation_feedback_request.cpp | 207 + Source/Services/Social/reputation_service.cpp | 140 + Source/Services/Social/social_internal.h | 116 + .../social_relationship_change_event_args.cpp | 48 + ...ocial_relationship_change_subscription.cpp | 108 + Source/Services/Social/social_service.cpp | 125 + .../Services/Social/social_service_impl.cpp | 268 ++ .../Social/xbox_social_relationship.cpp | 77 + .../xbox_social_relationship_result.cpp | 92 + Source/Services/Social/xbox_user_profile.cpp | 144 + .../Stats/WinRT/RequestedStatistics_WinRT.cpp | 45 + .../Stats/WinRT/RequestedStatistics_WinRT.h | 51 + .../ServiceConfigurationStatistic_WinRT.cpp | 34 + .../ServiceConfigurationStatistic_WinRT.h | 45 + .../WinRT/StatisticChangeEventArgs_WinRT.cpp | 29 + .../WinRT/StatisticChangeEventArgs_WinRT.h | 45 + .../StatisticChangeSubscription_WinRT.cpp | 42 + .../WinRT/StatisticChangeSubscription_WinRT.h | 65 + .../Services/Stats/WinRT/Statistic_WinRT.cpp | 33 + Source/Services/Stats/WinRT/Statistic_WinRT.h | 51 + .../WinRT/UserStatisticsResult_WinRT.cpp | 39 + .../Stats/WinRT/UserStatisticsResult_WinRT.h | 46 + .../WinRT/UserStatisticsService_WinRT.cpp | 236 + .../Stats/WinRT/UserStatisticsService_WinRT.h | 154 + .../Services/Stats/requested_statistics.cpp | 34 + .../Stats/service_configuration_statistic.cpp | 68 + Source/Services/Stats/statistic.cpp | 94 + .../Stats/statistic_change_event_args.cpp | 48 + .../Stats/statistic_change_subscription.cpp | 157 + .../Services/Stats/user_statistics_internal.h | 46 + .../Services/Stats/user_statistics_result.cpp | 77 + .../Stats/user_statistics_service.cpp | 268 ++ .../Stats/user_statistics_service_impl.cpp | 138 + .../TitleStorageBlobMetadataResult_WinRT.cpp | 48 + .../TitleStorageBlobMetadataResult_WinRT.h | 49 + .../WinRT/TitleStorageBlobMetadata_WinRT.cpp | 124 + .../WinRT/TitleStorageBlobMetadata_WinRT.h | 186 + .../WinRT/TitleStorageBlobResult_WinRT.cpp | 49 + .../WinRT/TitleStorageBlobResult_WinRT.h | 41 + .../WinRT/TitleStorageBlobType_WinRT.h | 30 + .../TitleStorageETagMatchCondition_WinRT.h | 27 + .../WinRT/TitleStorageQuota_WinRT.cpp | 23 + .../WinRT/TitleStorageQuota_WinRT.h | 65 + .../WinRT/TitleStorageService_WinRT.cpp | 232 + .../WinRT/TitleStorageService_WinRT.h | 229 + .../WinRT/TitleStorageType_WinRT.h | 54 + .../title_storage_blob_metadata.cpp | 302 ++ .../title_storage_blob_metadata_result.cpp | 129 + .../title_storage_blob_result.cpp | 40 + .../TitleStorage/title_storage_quota.cpp | 100 + .../TitleStorage/title_storage_service.cpp | 989 ++++ .../WinRT/TournamentArbitrationState_WinRT.h | 41 + .../WinRT/TournamentArbitrationStatus_WinRT.h | 46 + .../WinRT/TournamentGameResultSource_WinRT.h | 41 + .../WinRT/TournamentGameResultState_WinRT.h | 51 + .../WinRT/TournamentReference_WinRT.cpp | 33 + .../WinRT/TournamentReference_WinRT.h | 53 + .../TournamentRegistrationReason_WinRT.h | 50 + .../WinRT/TournamentRegistrationState_WinRT.h | 50 + .../WinRT/TournamentTeamResult_WinRT.cpp | 40 + .../WinRT/TournamentTeamResult_WinRT.h | 45 + .../Tournaments/tournament_reference.cpp | 81 + .../Tournaments/tournament_team_result.cpp | 78 + .../Shared/Desktop/local_config_desktop.cpp | 177 + Source/Shared/Logger/ERA_ETW.h | 466 ++ Source/Shared/Logger/ERA_ETW.man | 61 + .../Shared/Logger/android/logcat_output.cpp | 43 + Source/Shared/Logger/android/logcat_output.h | 22 + Source/Shared/Logger/console_output.cpp | 22 + Source/Shared/Logger/console_output.h | 23 + Source/Shared/Logger/custom_output.cpp | 33 + Source/Shared/Logger/custom_output.h | 23 + Source/Shared/Logger/debug_output.cpp | 21 + Source/Shared/Logger/debug_output.h | 23 + Source/Shared/Logger/era_etw.rc | 3 + Source/Shared/Logger/era_etwTEMP.BIN | Bin 0 -> 866 bytes Source/Shared/Logger/era_etw_MSG00001.bin | Bin 0 -> 116 bytes .../Logger/era_etw_headergen_readme.txt | 21 + Source/Shared/Logger/etw_output.cpp | 70 + Source/Shared/Logger/etw_output.h | 41 + Source/Shared/Logger/iOS/debug_output_ios.cpp | 21 + Source/Shared/Logger/log.cpp | 56 + Source/Shared/Logger/log.h | 164 + Source/Shared/Logger/log_entry.cpp | 47 + Source/Shared/Logger/log_output.cpp | 59 + .../Shared/WinRT/AppConfiguration_WinRT.cpp | 42 + Source/Shared/WinRT/AppConfiguration_WinRT.h | 75 + Source/Shared/WinRT/Event_WinRT.cpp | 64 + Source/Shared/WinRT/Event_WinRT.h | 26 + .../WinRT/HttpCallRequestMessage_WinRT.cpp | 33 + .../WinRT/HttpCallRequestMessage_WinRT.h | 45 + .../WinRT/HttpRequestMessageType_WinRT.h | 35 + Source/Shared/WinRT/Macros_WinRT.h | 399 ++ .../WinRT/ServiceCallLoggingConfig_WinRT.cpp | 43 + .../WinRT/ServiceCallLoggingConfig_WinRT.h | 40 + .../WinRT/SignInUIEmphasisFeature_WinRT.h | 75 + .../Shared/WinRT/SignInUIGameCategory_WinRT.h | 31 + .../Shared/WinRT/SignInUISettings_WinRT.cpp | 73 + Source/Shared/WinRT/SignInUISettings_WinRT.h | 74 + Source/Shared/WinRT/Utils_WinRT.cpp | 308 ++ Source/Shared/WinRT/Utils_WinRT.h | 236 + .../WinRT/XboxLiveContextSettings_WinRT.cpp | 133 + .../WinRT/XboxLiveContextSettings_WinRT.h | 192 + .../WinRT/XboxLiveLogCallEventArgs_WinRT.cpp | 49 + .../WinRT/XboxLiveLogCallEventArgs_WinRT.h | 54 + .../WinRT/XboxLiveServicesSettings_WinRT.cpp | 92 + .../WinRT/XboxLiveServicesSettings_WinRT.h | 79 + .../XboxServiceCallRoutedEventArgs_WinRT.cpp | 71 + .../XboxServiceCallRoutedEventArgs_WinRT.h | 120 + .../XboxServicesDiagnosticsTraceLevel_WinRT.h | 48 + Source/Shared/WinRT/local_config_winrt.cpp | 136 + Source/Shared/a/http_call_jni.cpp | 312 ++ Source/Shared/a/http_call_jni.h | 87 + Source/Shared/a/http_call_static_glue.cpp | 73 + Source/Shared/a/http_call_static_glue.h | 4 + Source/Shared/a/interop_jni.cpp | 21 + Source/Shared/a/interop_jni.h | 16 + Source/Shared/a/jni_utils.h | 72 + Source/Shared/a/local_config_a.cpp | 68 + Source/Shared/a/local_config_jni.cpp | 51 + Source/Shared/a/local_config_jni.h | 34 + Source/Shared/a/local_config_static_glue.cpp | 45 + Source/Shared/a/local_config_static_glue.h | 4 + Source/Shared/a/title_callable_ui_jni.h | 0 Source/Shared/a/utils_a.cpp | 44 + Source/Shared/a/utils_a.h | 21 + .../Shared/a/xbox_live_app_config_android.cpp | 47 + Source/Shared/a/xbox_live_app_config_jni.cpp | 216 + .../a/xbox_live_app_config_static_glue.h | 4 + Source/Shared/build_version.h | 12 + Source/Shared/errors.cpp | 398 ++ Source/Shared/http_call_impl.cpp | 977 ++++ Source/Shared/http_call_impl.h | 380 ++ Source/Shared/http_call_request_message.cpp | 55 + Source/Shared/http_call_response.cpp | 336 ++ Source/Shared/http_call_response.h | 31 + Source/Shared/http_client.cpp | 37 + Source/Shared/http_client.h | 41 + Source/Shared/i/local_config_i.mm | 76 + Source/Shared/i/utils_locales_ios.mm | 22 + Source/Shared/initiator.cpp | 64 + Source/Shared/initiator.h | 24 + Source/Shared/local_config.cpp | 173 + Source/Shared/local_config.h | 86 + Source/Shared/mem.cpp | 71 + Source/Shared/perf_tester.h | 96 + Source/Shared/service_call_logger.cpp | 148 + Source/Shared/service_call_logger.h | 63 + Source/Shared/service_call_logger_data.cpp | 270 ++ Source/Shared/service_call_logger_data.h | 93 + .../Shared/service_call_logger_protocol.cpp | 155 + Source/Shared/service_call_logger_protocol.h | 40 + Source/Shared/service_call_logging_config.cpp | 66 + Source/Shared/shared_macros.h | 179 + Source/Shared/telemetry.cpp | 31 + Source/Shared/telemetry.h | 25 + Source/Shared/u/local_config_u.cpp | 146 + Source/Shared/user_context.cpp | 529 ++ Source/Shared/user_context.h | 163 + Source/Shared/utils.cpp | 1556 ++++++ Source/Shared/utils.h | 728 +++ Source/Shared/utils_locales.cpp | 271 ++ Source/Shared/web_socket_client.cpp | 163 + Source/Shared/web_socket_client.h | 46 + Source/Shared/web_socket_connection.cpp | 265 + Source/Shared/web_socket_connection.h | 76 + Source/Shared/web_socket_connection_state.h | 22 + Source/Shared/xbox_live_app_config.cpp | 206 + Source/Shared/xbox_live_context_settings.cpp | 245 + Source/Shared/xbox_live_services_settings.cpp | 141 + .../xbox_service_call_routed_event_args.cpp | 132 + Source/Shared/xbox_system_factory.cpp | 174 + Source/Shared/xbox_system_factory.h | 109 + Source/Shared/xbox_system_factory_ios.mm | 24 + .../GetTokenAndSignatureResult_WinRT.cpp | 26 + .../WinRT/GetTokenAndSignatureResult_WinRT.h | 79 + Source/System/WinRT/SignInResult_WinRT.h | 43 + Source/System/WinRT/SignInStatus_WinRT.h | 37 + Source/System/WinRT/User_WinRT.cpp | 230 + Source/System/WinRT/User_WinRT.h | 248 + Source/System/a/auth_flow_result_jni.cpp | 83 + Source/System/a/auth_flow_result_jni.h | 65 + .../System/a/auth_flow_result_static_glue.cpp | 58 + .../System/a/auth_flow_result_static_glue.h | 4 + Source/System/a/java_interop.cpp | 505 ++ Source/System/a/java_interop.h | 71 + Source/System/a/user_android.cpp | 50 + Source/System/a/user_auth_android.cpp | 1141 +++++ Source/System/a/user_auth_android.h | 197 + Source/System/a/user_impl_a.h | 62 + Source/System/a/user_impl_android.cpp | 154 + .../System/a/user_impl_delegated_android.cpp | 61 + Source/System/auth/Desktop/Ecdsa.cpp | 207 + .../auth/Desktop/algorithm_provider.cpp | 45 + .../System/auth/Desktop/algorithm_provider.h | 30 + .../auth/Desktop/ip_address_desktop.cpp | 60 + Source/System/auth/Desktop/request_signer.cpp | 111 + Source/System/auth/Desktop/sha256.cpp | 121 + Source/System/auth/Desktop/sha256.h | 31 + Source/System/auth/Unix/big_num.cpp | 52 + Source/System/auth/Unix/big_num.h | 34 + Source/System/auth/Unix/ecdsa_unix.cpp | 84 + Source/System/auth/Unix/ip_address_unix.cpp | 107 + Source/System/auth/Unix/request_signer.cpp | 112 + Source/System/auth/Unix/sha256.cpp | 43 + Source/System/auth/Unix/sha256.h | 35 + Source/System/auth/auth_manager.cpp | 230 + Source/System/auth/auth_manager.h | 65 + Source/System/auth/cidr.cpp | 118 + Source/System/auth/cidr.h | 53 + Source/System/auth/device_token_service.cpp | 54 + Source/System/auth/device_token_service.h | 42 + Source/System/auth/ecdsa.h | 100 + Source/System/auth/ip_address.cpp | 157 + Source/System/auth/ip_address.h | 47 + Source/System/auth/json_web_key.cpp | 55 + Source/System/auth/json_web_key.h | 27 + Source/System/auth/nsal.cpp | 362 ++ Source/System/auth/nsal.h | 107 + Source/System/auth/nsal_endpoint.cpp | 253 + Source/System/auth/nsal_endpoint.h | 166 + Source/System/auth/request_signer.h | 53 + Source/System/auth/request_signer_helpers.cpp | 47 + Source/System/auth/request_signer_helpers.h | 37 + Source/System/auth/service_token_service.cpp | 54 + Source/System/auth/service_token_service.h | 39 + Source/System/auth/signature_policy.cpp | 63 + Source/System/auth/signature_policy.h | 39 + Source/System/auth/title_token_service.cpp | 52 + Source/System/auth/title_token_service.h | 44 + Source/System/auth/token_error.cpp | 85 + Source/System/auth/token_error.h | 64 + Source/System/auth/token_manager.cpp | 525 ++ Source/System/auth/token_manager.h | 161 + Source/System/auth/token_request.cpp | 169 + Source/System/auth/token_request.h | 71 + Source/System/auth/token_result.cpp | 195 + Source/System/auth/token_result.h | 132 + Source/System/auth/trie.cpp | 34 + Source/System/auth/trie.h | 229 + Source/System/auth/user_token_service.cpp | 49 + Source/System/auth/user_token_service.h | 47 + Source/System/auth/xbox_live_server.cpp | 67 + Source/System/auth/xbox_live_server_impl.cpp | 173 + Source/System/auth/xbox_live_server_impl.h | 69 + Source/System/auth/xsts_token_service.cpp | 75 + Source/System/auth/xsts_token_service.h | 58 + Source/System/auth/xtitle_service.cpp | 102 + Source/System/auth/xtitle_service.h | 57 + Source/System/auth_config.cpp | 294 ++ Source/System/auth_config.h | 123 + Source/System/iOS/XBLDictionaryToJSON.h | 16 + Source/System/iOS/XBLDictionaryToJSON.mm | 117 + Source/System/iOS/XBLServiceManager.h | 14 + Source/System/iOS/XBLServiceManager.mm | 297 ++ Source/System/iOS/XBLiOSGlobalState.h | 44 + Source/System/iOS/XBLiOSGlobalState.mm | 32 + Source/System/iOS/XboxTelemetry/UTCIdpNames.h | 112 + .../System/iOS/XboxTelemetry/UTCIdpNames.mm | 112 + Source/System/iOS/XboxTelemetry/XLSCll.h | 16 + Source/System/iOS/XboxTelemetry/XLSCll.mm | 417 ++ .../iOS/XboxUIDelegates/XBLSignInHandler.h | 53 + .../iOS/XboxUIDelegates/XBLSignInHandler.mm | 154 + .../iOS/XboxUIDelegates/XboxSignInHandler.h | 37 + .../iOS/XboxUIDelegates/XboxSignInHandler.mm | 141 + .../XboxUIDelegates/sign_in_delegate_ios.h | 53 + .../XboxUIDelegates/sign_in_delegate_ios.mm | 641 +++ Source/System/iOS/auth/user_auth_ios.h | 141 + Source/System/iOS/auth/user_auth_ios.mm | 704 +++ Source/System/iOS/xbox_cll.mm | 137 + Source/System/iOS/xbox_live_app_config_ios.mm | 83 + Source/System/ppltasks_extra.h | 107 + Source/System/ppltasks_extra_unix.h | 25 + Source/System/system_internal.h | 24 + Source/System/token_and_signature_result.cpp | 130 + Source/System/user.cpp | 199 + Source/System/user_impl.cpp | 278 ++ Source/System/user_impl.h | 275 ++ Source/System/user_impl_idp.cpp | 654 +++ Source/System/user_impl_ios.h | 58 + Source/System/user_impl_ios.mm | 138 + Source/System/user_impl_server.cpp | 119 + Source/System/user_ios.mm | 52 + Source/System/xbox_live_mutex.cpp | 37 + Tests/UnitTests/Mocks/MockHttpCall.cpp | 248 + Tests/UnitTests/Mocks/MockHttpCall.h | 109 + Tests/UnitTests/Mocks/MockHttpClient.cpp | 50 + Tests/UnitTests/Mocks/MockHttpClient.h | 32 + Tests/UnitTests/Mocks/MockLocalConfig.cpp | 124 + Tests/UnitTests/Mocks/MockLocalConfig.h | 56 + Tests/UnitTests/Mocks/MockMultiplayer.cpp | 26 + Tests/UnitTests/Mocks/MockMultiplayer.h | 42 + Tests/UnitTests/Mocks/MockSocialManager.cpp | 92 + Tests/UnitTests/Mocks/MockSocialManager.h | 43 + Tests/UnitTests/Mocks/MockUser.cpp | 99 + Tests/UnitTests/Mocks/MockUser.h | 58 + .../UnitTests/Mocks/MockUserTokenService.cpp | 78 + Tests/UnitTests/Mocks/MockUserTokenService.h | 72 + Tests/UnitTests/Mocks/MockWebSocketClient.h | 207 + Tests/UnitTests/Mocks/MockXTitleService.cpp | 42 + Tests/UnitTests/Mocks/MockXTitleService.h | 39 + .../UnitTests/Mocks/MockXboxSystemFactory.cpp | 271 ++ Tests/UnitTests/Mocks/MockXboxSystemFactory.h | 156 + .../UnitTests/Mocks/MockXstsTokenService.cpp | 54 + Tests/UnitTests/Mocks/MockXstsTokenService.h | 42 + Tests/UnitTests/Mocks/StockMocks.cpp | 234 + Tests/UnitTests/Mocks/StockMocks.h | 55 + Tests/UnitTests/Support/DefineTestMacros.h | 108 + Tests/UnitTests/Support/TAEF/UnitTestBase.cpp | 141 + Tests/UnitTests/Support/TAEF/UnitTestBase.h | 216 + .../Support/TAEF/UnitTestBase_winrt.cpp | 252 + .../Support/TAEF/UnitTestBase_winrt.h | 140 + .../Support/TAEF/UnitTestIncludes_TAEF.h | 15 + .../UnitTests/Support/TE/UnitTestHelpers.cpp | 107 + Tests/UnitTests/Support/TE/UnitTestHelpers.h | 54 + .../Support/TE/UnitTestIncludes_TE.h | 254 + Tests/UnitTests/Support/UnitTestIncludes.h | 16 + Tests/UnitTests/Support/iso8601.cpp | 741 +++ Tests/UnitTests/Support/iso8601.h | 84 + Tests/UnitTests/Support/unittest_output.cpp | 43 + Tests/UnitTests/Support/unittest_output.h | 24 + .../Tests/Services/AchievementsTests.cpp | 565 +++ .../Tests/Services/ContextualSearchTests.cpp | 673 +++ .../Services/EntertainmentProfileTests.cpp | 149 + Tests/UnitTests/Tests/Services/ErrorTests.cpp | 424 ++ .../Services/GameServerPlatformTests.cpp | 384 ++ .../Tests/Services/LeaderboardTests.cpp | 631 +++ .../Tests/Services/MarketplaceTests.cpp | 1379 ++++++ .../Tests/Services/MatchmakingTests.cpp | 272 ++ .../Services/MultiplayerManagerTests.cpp | 4260 +++++++++++++++++ .../Tests/Services/MultiplayerTests.cpp | 3567 ++++++++++++++ .../Tests/Services/PeoplehubTests.cpp | 148 + .../Tests/Services/PresenceTests.cpp | 920 ++++ .../UnitTests/Tests/Services/PrivacyTests.cpp | 366 ++ .../UnitTests/Tests/Services/ProfileTests.cpp | 354 ++ .../Tests/Services/RealTimeActivityTests.cpp | 969 ++++ .../Tests/Services/ReputationTests.cpp | 202 + .../Tests/Services/RtaTestHelper.cpp | 93 + .../UnitTests/Tests/Services/RtaTestHelper.h | 40 + .../Tests/Services/SocialManagerHelper.h | 252 + .../Tests/Services/SocialManagerTests.cpp | 2507 ++++++++++ .../UnitTests/Tests/Services/SocialTests.cpp | 393 ++ Tests/UnitTests/Tests/Services/StatsTests.cpp | 390 ++ .../Tests/Services/StringVerifyTests.cpp | 120 + .../Services/TestResponses/Matchmaking.json | 41 + .../Services/TestResponses/Multiplayer.json | 1393 ++++++ .../TestResponses/MultiplayerManager.json | 2040 ++++++++ .../Tests/Services/TitleStorageTests.cpp | 788 +++ .../Tests/Services/TournamentsTests.cpp | 216 + .../Tests/Shared/EventTests_WinRT.cpp | 40 + .../Tests/Shared/HttpCallResponseTests.cpp | 104 + .../Tests/Shared/HttpCallSettingsTests.cpp | 249 + .../Shared/HttpCallSettingsTests_WinRT.cpp | 54 + Tests/UnitTests/Tests/Shared/LogTests.cpp | 364 ++ .../Tests/Shared/ServiceCallLoggerTests.cpp | 130 + Tests/UnitTests/Tests/Shared/UtilTests.cpp | 206 + .../UnitTests/Tests/Shared/WebsocketTests.cpp | 407 ++ .../Tests/Shared/XboxLiveContextTests.cpp | 324 ++ Tests/UnitTests/Tests/System/CidrTests.cpp | 144 + Tests/UnitTests/Tests/System/EcdsaTests.cpp | 76 + .../UnitTests/Tests/System/IpAddressTests.cpp | 75 + Tests/UnitTests/Tests/System/NsalTests.cpp | 342 ++ .../Tests/System/RequestSignerTests.cpp | 118 + .../Tests/System/TokenErrorResponseTests.cpp | 39 + .../Tests/System/TokenResultTests.cpp | 60 + Tests/UnitTests/Tests/System/UserTests.cpp | 275 ++ .../Tests/System/UserTests_WinRT.cpp | 114 + .../Tests/System/UserTokenResultTests.cpp | 70 + .../Tests/System/UserTokenServiceTests.cpp | 101 + .../Tests/System/XTitleServiceTests.cpp | 193 + .../Tests/System/XboxSystemFactoryTests.cpp | 40 + .../Tests/System/XstsTokenServiceTests.cpp | 107 + ...soft.Xbox.Live.Services.API.Cpp.UWP.nuspec | 53 + ...oft.Xbox.Live.Services.API.Cpp.UWP.targets | 19 + ...ox.Live.Services.API.Cpp.XboxOneXDK.nuspec | 42 + ...x.Live.Services.API.Cpp.XboxOneXDK.targets | 28 + ...ft.Xbox.Live.Services.API.WinRT.UWP.nuspec | 99 + ...t.Xbox.Live.Services.API.WinRT.UWP.targets | 51 + ....Live.Services.API.WinRT.XboxOneXDK.nuspec | 29 + ...Live.Services.API.WinRT.XboxOneXDK.targets | 21 + .../ABIHeaderGen/DurangoVars.cmd | 307 ++ .../ABIHeaderGen/GenerateABIOnBuildServer.cmd | 56 + .../CppWinRTCompiler/CompileCppWinRT.cmd | 74 + .../VSOBuildScripts/CppWinRTCompiler/ERA.rsp | 10 + .../CppWinRTCompiler/WinSDK.rsp | 10 + Utilities/VSOBuildScripts/FindAndReplace.exe | Bin 0 -> 9728 bytes .../VSOBuildScripts/GenSDKBuildCppFile.exe | Bin 0 -> 7168 bytes .../GenSDKBuildCppFile/App.config | 6 + .../GenSDKBuildCppFile.csproj | 60 + .../GenSDKBuildCppFile/GenSDKBuildCppFile.sln | 22 + .../GenSDKBuildCppFile/Program.cs | 106 + .../Properties/AssemblyInfo.cs | 36 + Utilities/VSOBuildScripts/postBuildScript.cmd | 120 + .../VSOBuildScripts/preCompileScript.cmd | 47 + Utilities/VSOBuildScripts/setBuildVersion.cmd | 3 + Utilities/VSOBuildScripts/skipBuild.cmd | 29 + nuget.config | 6 + signConfig.xml | 38 + xdk.extcomp | 8 + xsapi.staticlib.props | 18 + 1099 files changed, 201251 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Build.Durango.Cpp.props create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.sln create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.sln create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.110.XDK.Cpp/build.cpp create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.sln create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.sln create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.Cpp/build.cpp create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.sln create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/Build.Durango.Cpp.props create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.sln create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.Cpp/build.cpp create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.WinRT/Build.Durango.Cpp.props create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.sln create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.Android/.project create mode 100644 Build/Microsoft.Xbox.Services.Android/.settings/org.eclipse.jdt.core.prefs create mode 100644 Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.sln create mode 100644 Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems.filters create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.sln create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.sln create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj.filters create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestAll.runsettings create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestMultiplayerManager.runsettings create mode 100644 Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestSocialManager.runsettings create mode 100644 Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.pbxproj create mode 100644 Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/xcshareddata/XboxLiveServices.xccheckout create mode 100644 Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServices.xcscheme create mode 100644 Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServicesResources.xcscheme create mode 100644 Build/Microsoft.Xbox.Services.iOS/XboxLiveServicesResources/Info.plist create mode 100644 CONTRIBUTING.md create mode 100644 External/cpprestsdk/.gitignore create mode 100644 External/cpprestsdk/Build/Build.Durango.Cpp.props create mode 100644 External/cpprestsdk/Build/Common.Build.Traversal.targets create mode 100644 External/cpprestsdk/Build/Common.Build.settings create mode 100644 External/cpprestsdk/Build/Config.Definitions.Durango.props create mode 100644 External/cpprestsdk/Build/Config.Definitions.props create mode 100644 External/cpprestsdk/Build/Release.Product.settings create mode 100644 External/cpprestsdk/Build/Release.Tests.settings create mode 100644 External/cpprestsdk/Build/version.props create mode 100644 External/cpprestsdk/Build_android/boost-for-android-x86.patch create mode 100644 External/cpprestsdk/Build_android/boost-for-android.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitattributes create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitignore create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/README.md create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.bat create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.sh create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-common.sh create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_45_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_48_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_49_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_53_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_54_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_55_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_59_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/cpprestsdk.patched.stamp create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/address_v6.ipp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.jam.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.py.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/endian.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/fenced_block.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/operations.cpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/socket_types.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/user.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/v2_operations.cpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/workaround.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_48_0/boost-1_48_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_49_0/boost-1_49_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_53_0/boost-1_53_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_54_0/boost-1_54_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_55_0/boost-1_55_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/.gitattributes create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/.gitignore create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/README.md create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.bat create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.sh create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/build-common.sh create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_45_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_48_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_49_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_53_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_54_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_55_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_59_0.jam create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/cpprestsdk.patched.stamp create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/address_v6.ipp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.jam.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.py.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/endian.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/fenced_block.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/operations.cpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/socket_types.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/user.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/v2_operations.cpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/workaround.hpp.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_48_0/boost-1_48_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_49_0/boost-1_49_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_53_0/boost-1_53_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_54_0/boost-1_54_0.patch create mode 100644 External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_55_0/boost-1_55_0.patch create mode 100644 External/cpprestsdk/Build_android/configure.sh create mode 100644 External/cpprestsdk/Build_android/libiconv/jni/Android.mk create mode 100644 External/cpprestsdk/Build_android/libiconv/jni/Application.mk create mode 100644 External/cpprestsdk/Build_android/libiconv/libiconv.patch create mode 100644 External/cpprestsdk/Build_android/openssl/Makefile create mode 100644 External/cpprestsdk/Build_iOS/.gitignore create mode 100644 External/cpprestsdk/Build_iOS/CMakeLists.txt create mode 100644 External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.pbxproj create mode 100644 External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 External/cpprestsdk/Build_iOS/README.md create mode 100644 External/cpprestsdk/Build_iOS/configure.sh create mode 100644 External/cpprestsdk/Build_iOS/fix_boost_building_script.patch create mode 100644 External/cpprestsdk/Build_iOS/fix_boost_version.patch create mode 100644 External/cpprestsdk/Build_iOS/fix_ios_cmake_compiler.patch create mode 100644 External/cpprestsdk/CONTRIBUTORS.txt create mode 100644 External/cpprestsdk/README.md create mode 100644 External/cpprestsdk/ThirdPartyNotices.txt create mode 100644 External/cpprestsdk/build.root create mode 100644 External/cpprestsdk/casablanca110.Xbox.sln create mode 100644 External/cpprestsdk/cpprestsdk120.nonuget create mode 100644 External/cpprestsdk/cpprestsdk120.sln create mode 100644 External/cpprestsdk/cpprestsdk140.nonuget create mode 100644 External/cpprestsdk/cpprestsdk140.sln create mode 100644 External/cpprestsdk/license.txt create mode 100644 External/cpprestsdk/setup_ps_env_VS2013.ps1 create mode 100644 External/cpprestsdk/setup_ps_env_VS2015.ps1 create mode 100644 Include/xsapi/achievements.h create mode 100644 Include/xsapi/contextual_search_service.h create mode 100644 Include/xsapi/entertainment_profile.h create mode 100644 Include/xsapi/errors.h create mode 100644 Include/xsapi/events.h create mode 100644 Include/xsapi/game_server_platform.h create mode 100644 Include/xsapi/http_call.h create mode 100644 Include/xsapi/http_call_request_message.h create mode 100644 Include/xsapi/leaderboard.h create mode 100644 Include/xsapi/marketplace.h create mode 100644 Include/xsapi/matchmaking.h create mode 100644 Include/xsapi/mem.h create mode 100644 Include/xsapi/multiplayer.h create mode 100644 Include/xsapi/multiplayer_manager.h create mode 100644 Include/xsapi/notification_helper.h create mode 100644 Include/xsapi/presence.h create mode 100644 Include/xsapi/privacy.h create mode 100644 Include/xsapi/profile.h create mode 100644 Include/xsapi/real_time_activity.h create mode 100644 Include/xsapi/service_call_logging_config.h create mode 100644 Include/xsapi/services.h create mode 100644 Include/xsapi/social.h create mode 100644 Include/xsapi/social_manager.h create mode 100644 Include/xsapi/system.h create mode 100644 Include/xsapi/title_callable_ui.h create mode 100644 Include/xsapi/title_storage.h create mode 100644 Include/xsapi/types.h create mode 100644 Include/xsapi/user_statistics.h create mode 100644 Include/xsapi/xbox_cll.h create mode 100644 Include/xsapi/xbox_live_app_config.h create mode 100644 Include/xsapi/xbox_live_context.h create mode 100644 Include/xsapi/xbox_live_context_settings.h create mode 100644 Include/xsapi/xbox_service_call_routed_event_args.h create mode 100644 LICENSE.md create mode 100644 Source/Services/Achievements/WinRT/AchievementMediaAssetType_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementOrderBy_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementProgression_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/AchievementProgression_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementRequirement_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementRewardType_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementService_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/AchievementService_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementType_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/Achievement_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/Achievement_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/AchievementsResult_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/AchievementsResult_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/MediaAsset_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/MediaAsset_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/ParticipationType_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/ProgressState_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/Reward_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/Reward_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/TimeWindow_WinRT.cpp create mode 100644 Source/Services/Achievements/WinRT/TimeWindow_WinRT.h create mode 100644 Source/Services/Achievements/WinRT/TitleAssociation_WinRT.h create mode 100644 Source/Services/Achievements/achievement.cpp create mode 100644 Source/Services/Achievements/achievement_media_asset.cpp create mode 100644 Source/Services/Achievements/achievement_progression.cpp create mode 100644 Source/Services/Achievements/achievement_requirement.cpp create mode 100644 Source/Services/Achievements/achievement_reward.cpp create mode 100644 Source/Services/Achievements/achievement_service.cpp create mode 100644 Source/Services/Achievements/achievement_time_window.cpp create mode 100644 Source/Services/Achievements/achievement_title_association.cpp create mode 100644 Source/Services/Achievements/achievements_result.cpp create mode 100644 Source/Services/Common/Desktop/XboxLiveContext_Desktop.cpp create mode 100644 Source/Services/Common/Desktop/dllmain.cpp create mode 100644 Source/Services/Common/Desktop/pch.cpp create mode 100644 Source/Services/Common/Desktop/pch.h create mode 100644 Source/Services/Common/Server/xbox_live_context_server.cpp create mode 100644 Source/Services/Common/Server/xbox_live_context_server_impl.cpp create mode 100644 Source/Services/Common/Server/xbox_live_context_server_impl.h create mode 100644 Source/Services/Common/Unix/pch.cpp create mode 100644 Source/Services/Common/Unix/pch.h create mode 100644 Source/Services/Common/Unix/pch_unix.cpp create mode 100644 Source/Services/Common/Unix/pch_unix.h create mode 100644 Source/Services/Common/WinRT/XboxLiveContext_WinRT.cpp create mode 100644 Source/Services/Common/WinRT/XboxLiveContext_WinRT.h create mode 100644 Source/Services/Common/WinRT/pch.cpp create mode 100644 Source/Services/Common/WinRT/pch.h create mode 100644 Source/Services/Common/iOS/pch.cpp create mode 100644 Source/Services/Common/iOS/pch.h create mode 100644 Source/Services/Common/pch_common.h create mode 100644 Source/Services/Common/xbox_live_context_impl.cpp create mode 100644 Source/Services/Common/xbox_live_context_impl.h create mode 100644 Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.cpp create mode 100644 Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.h create mode 100644 Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.cpp create mode 100644 Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.h create mode 100644 Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.cpp create mode 100644 Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.h create mode 100644 Source/Services/EntertainmentProfile/entertainment_profile.cpp create mode 100644 Source/Services/EntertainmentProfile/entertainment_profile_list_contains_item_result.cpp create mode 100644 Source/Services/EntertainmentProfile/entertainment_profile_list_xbox_one_pins.cpp create mode 100644 Source/Services/Events/WinRT/EventsService_WinRT.cpp create mode 100644 Source/Services/Events/WinRT/EventsService_WinRT.h create mode 100644 Source/Services/Events/events_service.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerFulfillmentState_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerHostStatus_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.h create mode 100644 Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.cpp create mode 100644 Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.h create mode 100644 Source/Services/GameServerPlatform/allocation_result.cpp create mode 100644 Source/Services/GameServerPlatform/cluster_result.cpp create mode 100644 Source/Services/GameServerPlatform/game_server_image_set.cpp create mode 100644 Source/Services/GameServerPlatform/game_server_metadata_result.cpp create mode 100644 Source/Services/GameServerPlatform/game_server_platform_service.cpp create mode 100644 Source/Services/GameServerPlatform/game_server_port_mapping.cpp create mode 100644 Source/Services/GameServerPlatform/game_server_ticket_status.cpp create mode 100644 Source/Services/GameServerPlatform/game_variant.cpp create mode 100644 Source/Services/GameServerPlatform/game_variant_schema.cpp create mode 100644 Source/Services/GameServerPlatform/quality_of_service_server.cpp create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardColumn.cpp create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardColumn.h create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardResult.cpp create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardResult.h create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardRow.cpp create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardRow.h create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardService.cpp create mode 100644 Source/Services/Leaderboard/WinRT/LeaderboardService.h create mode 100644 Source/Services/Leaderboard/leaderboard_column.cpp create mode 100644 Source/Services/Leaderboard/leaderboard_query.h create mode 100644 Source/Services/Leaderboard/leaderboard_result.cpp create mode 100644 Source/Services/Leaderboard/leaderboard_row.cpp create mode 100644 Source/Services/Leaderboard/leaderboard_serializers.cpp create mode 100644 Source/Services/Leaderboard/leaderboard_serializers.h create mode 100644 Source/Services/Leaderboard/leaderboard_service.cpp create mode 100644 Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/BundleRelationshipType_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogItem_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/CatalogItem_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogService_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/CatalogService_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogSortOrder_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/InventoryItemAvailability_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/InventoryItemState_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/InventoryItem_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/InventoryItem_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/InventoryService_WinRT.cpp create mode 100644 Source/Services/Marketplace/WinRT/InventoryService_WinRT.h create mode 100644 Source/Services/Marketplace/WinRT/MediaItemType_WinRT.h create mode 100644 Source/Services/Marketplace/browse_catalog_result.cpp create mode 100644 Source/Services/Marketplace/catalog_item.cpp create mode 100644 Source/Services/Marketplace/catalog_item_availability.cpp create mode 100644 Source/Services/Marketplace/catalog_item_details.cpp create mode 100644 Source/Services/Marketplace/catalog_item_image.cpp create mode 100644 Source/Services/Marketplace/catalog_service.cpp create mode 100644 Source/Services/Marketplace/catalog_total.cpp create mode 100644 Source/Services/Marketplace/consume_inventory_item_request.cpp create mode 100644 Source/Services/Marketplace/consume_inventory_item_result.cpp create mode 100644 Source/Services/Marketplace/inventory_item.cpp create mode 100644 Source/Services/Marketplace/inventory_items_result.cpp create mode 100644 Source/Services/Marketplace/inventory_service.cpp create mode 100644 Source/Services/Matchmaking/WinRT/CreateMatchTicketResponse_WinRT.h create mode 100644 Source/Services/Matchmaking/WinRT/HopperStatisticsResponse_WinRT.h create mode 100644 Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.cpp create mode 100644 Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.h create mode 100644 Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.cpp create mode 100644 Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.h create mode 100644 Source/Services/Matchmaking/WinRT/PreserveSessionMode_WinRT.h create mode 100644 Source/Services/Matchmaking/WinRT/TicketStatus_WinRT.h create mode 100644 Source/Services/Matchmaking/create_match_ticket_response.cpp create mode 100644 Source/Services/Matchmaking/hopper_statistics_response.cpp create mode 100644 Source/Services/Matchmaking/match_ticket_details_response.cpp create mode 100644 Source/Services/Matchmaking/matchmaking_service.cpp create mode 100644 Source/Services/Misc/Android/title_callable_static_glue.h create mode 100644 Source/Services/Misc/Android/title_callable_ui_android.cpp create mode 100644 Source/Services/Misc/Android/title_callable_ui_jni.h create mode 100644 Source/Services/Misc/Android/title_callable_ui_static_glue.cpp create mode 100644 Source/Services/Misc/UWP/title_callable_ui.cpp create mode 100644 Source/Services/Misc/Unix/notification_service_android.cpp create mode 100644 Source/Services/Misc/Unix/notification_service_i.mm create mode 100644 Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchFilterOperator_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchService_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/ContextualSearchService_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchStatDisplayType_WinRT.h create mode 100644 Source/Services/Misc/WinRT/ContextualSearchStatVisibility_WinRT.h create mode 100644 Source/Services/Misc/WinRT/StringService_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/StringService_WinRT.h create mode 100644 Source/Services/Misc/WinRT/TitleCallableUI_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/TitleCallableUI_WinRT.h create mode 100644 Source/Services/Misc/WinRT/VerifyStringResultCode_WinRT.h create mode 100644 Source/Services/Misc/WinRT/VerifyStringResult_WinRT.h create mode 100644 Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.cpp create mode 100644 Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.h create mode 100644 Source/Services/Misc/Windows/notification_service_windows.cpp create mode 100644 Source/Services/Misc/contextual_config_result.cpp create mode 100644 Source/Services/Misc/contextual_config_result.h create mode 100644 Source/Services/Misc/contextual_search_broadcast.cpp create mode 100644 Source/Services/Misc/contextual_search_configured_stat.cpp create mode 100644 Source/Services/Misc/contextual_search_game_clip.cpp create mode 100644 Source/Services/Misc/contextual_search_game_clip_stat.cpp create mode 100644 Source/Services/Misc/contextual_search_game_clip_thumbnail.cpp create mode 100644 Source/Services/Misc/contextual_search_game_clip_uri_info.cpp create mode 100644 Source/Services/Misc/contextual_search_game_clips_result.cpp create mode 100644 Source/Services/Misc/contextual_search_service.cpp create mode 100644 Source/Services/Misc/iOS/notification_helper.mm create mode 100644 Source/Services/Misc/iOS/title_callable_ui.mm create mode 100644 Source/Services/Misc/notification_service.cpp create mode 100644 Source/Services/Misc/notification_service.h create mode 100644 Source/Services/Misc/string_service.cpp create mode 100644 Source/Services/Misc/verify_string_result.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/JoinInProgressState_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MatchStatus_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventType_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/MultiplayerSessionType_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/Manager/find_match_completed_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/host_changed_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/join_lobby_completed_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/member_joined_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/member_left_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/member_property_changed_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_client_manager.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_client_pending_reader.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_client_pending_request.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_event.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_game_client.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_game_session.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_lobby_client.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_lobby_session.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_local_user.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_local_user_manager.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_manager.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_manager_internal.h create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_manager_utils.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_match_client.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_member.cpp create mode 100644 Source/Services/Multiplayer/Manager/multiplayer_session_writer.cpp create mode 100644 Source/Services/Multiplayer/Manager/perform_qos_measurements_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/session_property_changed_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/tournament_game_session_ready_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/tournament_registration_state_changed_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/user_added_event_args.cpp create mode 100644 Source/Services/Multiplayer/Manager/user_removed_event_args.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MatchmakingStatus_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayMetrics_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerInitializationStage_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerMeasurementFailure_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeTypes.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionMemberStatus_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionRestriction_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionStatus_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionVisibility_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSessionWriteMode_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/MutableRoleSetting_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/NetworkAddressTranslationSetting_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.cpp create mode 100644 Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.h create mode 100644 Source/Services/Multiplayer/WinRT/WriteSessionStatus_WinRT.h create mode 100644 Source/Services/Multiplayer/multiplayer_activity_details.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_activity_handle_post_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_activity_query_post_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_get_sessions_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_internal.h create mode 100644 Source/Services/Multiplayer/multiplayer_invite.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_invite_handle_post_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_managed_initialization.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_member_initialization.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_peer_to_host_requirements.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_peer_to_peer_requirements.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_quality_of_service_measurement.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_query_search_handle_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_role_info.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_role_type.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_search_handle_details.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_search_handle_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_service.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_service_impl.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_arbitration_server.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_capabilities.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_change_event_args.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_constants.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_matchmaking_server.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_member.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_member_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_properties.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_reference.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_request.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_role_types.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_states.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_session_tournaments_server.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_subscription.cpp create mode 100644 Source/Services/Multiplayer/multiplayer_transfer_handle_post_request.cpp create mode 100644 Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.h create mode 100644 Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceData_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceData_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceDetailLevel_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceDeviceType_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceMediaIdType_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceRecord_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceRecord_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceService_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceService_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.h create mode 100644 Source/Services/Presence/WinRT/PresenceTitleViewState_WinRT.h create mode 100644 Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.h create mode 100644 Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.cpp create mode 100644 Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.h create mode 100644 Source/Services/Presence/WinRT/TitlePresenceState_WinRT.h create mode 100644 Source/Services/Presence/WinRT/UserPresenceState_WinRT.h create mode 100644 Source/Services/Presence/device_presence_change_event_args.cpp create mode 100644 Source/Services/Presence/device_presence_change_subscription.cpp create mode 100644 Source/Services/Presence/media_presence_data.cpp create mode 100644 Source/Services/Presence/presence_activity_data.cpp create mode 100644 Source/Services/Presence/presence_broadcast_record.cpp create mode 100644 Source/Services/Presence/presence_data.cpp create mode 100644 Source/Services/Presence/presence_device_record.cpp create mode 100644 Source/Services/Presence/presence_internal.h create mode 100644 Source/Services/Presence/presence_media_record.cpp create mode 100644 Source/Services/Presence/presence_record.cpp create mode 100644 Source/Services/Presence/presence_service.cpp create mode 100644 Source/Services/Presence/presence_service_impl.cpp create mode 100644 Source/Services/Presence/presence_title_record.cpp create mode 100644 Source/Services/Presence/presence_title_request.cpp create mode 100644 Source/Services/Presence/presence_user_batch_request.cpp create mode 100644 Source/Services/Presence/presence_writer.cpp create mode 100644 Source/Services/Presence/title_presence_change_event_args.cpp create mode 100644 Source/Services/Presence/title_presence_change_subscription.cpp create mode 100644 Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.cpp create mode 100644 Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.h create mode 100644 Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.cpp create mode 100644 Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.h create mode 100644 Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.cpp create mode 100644 Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.h create mode 100644 Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.cpp create mode 100644 Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.h create mode 100644 Source/Services/Privacy/WinRT/PrivacyService_WinRT.cpp create mode 100644 Source/Services/Privacy/WinRT/PrivacyService_WinRT.h create mode 100644 Source/Services/Privacy/multiple_permissions_check_result.cpp create mode 100644 Source/Services/Privacy/permission_check_result.cpp create mode 100644 Source/Services/Privacy/permission_deny_reason.cpp create mode 100644 Source/Services/Privacy/privacy_service.cpp create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivityConnectionState_WinRT.h create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.cpp create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.h create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.cpp create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.h create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.cpp create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.h create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionError_WinRT.h create mode 100644 Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionState_WinRT.h create mode 100644 Source/Services/RealTimeActivity/real_time_activity_internal.h create mode 100644 Source/Services/RealTimeActivity/real_time_activity_service.cpp create mode 100644 Source/Services/RealTimeActivity/real_time_activity_service_factory.cpp create mode 100644 Source/Services/RealTimeActivity/real_time_activity_subscription.cpp create mode 100644 Source/Services/RealTimeActivity/real_time_activity_subscription_error_event_args.cpp create mode 100644 Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialEventArgs_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialEventType_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialManagerExtraDetailLevel_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialManager_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/SocialManager_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/SocialUserGroupType_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.h create mode 100644 Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.cpp create mode 100644 Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.h create mode 100644 Source/Services/Social/Manager/internal_social_event.cpp create mode 100644 Source/Services/Social/Manager/peoplehub_service.cpp create mode 100644 Source/Services/Social/Manager/preferred_color.cpp create mode 100644 Source/Services/Social/Manager/social_event.cpp create mode 100644 Source/Services/Social/Manager/social_graph.cpp create mode 100644 Source/Services/Social/Manager/social_manager.cpp create mode 100644 Source/Services/Social/Manager/social_manager_internal.h create mode 100644 Source/Services/Social/Manager/social_manager_presence_record.cpp create mode 100644 Source/Services/Social/Manager/social_manager_presence_title_record.cpp create mode 100644 Source/Services/Social/Manager/social_user_group_loaded_event_args.cpp create mode 100644 Source/Services/Social/Manager/title_history.cpp create mode 100644 Source/Services/Social/Manager/xbox_social_user.cpp create mode 100644 Source/Services/Social/Manager/xbox_social_user_group.cpp create mode 100644 Source/Services/Social/Manager/xbox_user_id_container.cpp create mode 100644 Source/Services/Social/WinRT/PresenceFilter_WinRT.h create mode 100644 Source/Services/Social/WinRT/ProfileService_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/ProfileService_WinRT.h create mode 100644 Source/Services/Social/WinRT/RelationshipFilter_WinRT.h create mode 100644 Source/Services/Social/WinRT/ReputationFeedbackType_WinRT.h create mode 100644 Source/Services/Social/WinRT/ReputationService_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/ReputationService_WinRT.h create mode 100644 Source/Services/Social/WinRT/SocialGroupConstants_WinRT.h create mode 100644 Source/Services/Social/WinRT/SocialNotificationType_WinRT.h create mode 100644 Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.h create mode 100644 Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.h create mode 100644 Source/Services/Social/WinRT/SocialRelationship_WinRT.h create mode 100644 Source/Services/Social/WinRT/SocialService_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/SocialService_WinRT.h create mode 100644 Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.h create mode 100644 Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.h create mode 100644 Source/Services/Social/WinRT/XboxUserProfile_WinRT.cpp create mode 100644 Source/Services/Social/WinRT/XboxUserProfile_WinRT.h create mode 100644 Source/Services/Social/profile_service.cpp create mode 100644 Source/Services/Social/reputation_feedback_request.cpp create mode 100644 Source/Services/Social/reputation_service.cpp create mode 100644 Source/Services/Social/social_internal.h create mode 100644 Source/Services/Social/social_relationship_change_event_args.cpp create mode 100644 Source/Services/Social/social_relationship_change_subscription.cpp create mode 100644 Source/Services/Social/social_service.cpp create mode 100644 Source/Services/Social/social_service_impl.cpp create mode 100644 Source/Services/Social/xbox_social_relationship.cpp create mode 100644 Source/Services/Social/xbox_social_relationship_result.cpp create mode 100644 Source/Services/Social/xbox_user_profile.cpp create mode 100644 Source/Services/Stats/WinRT/RequestedStatistics_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/RequestedStatistics_WinRT.h create mode 100644 Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.h create mode 100644 Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.h create mode 100644 Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.h create mode 100644 Source/Services/Stats/WinRT/Statistic_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/Statistic_WinRT.h create mode 100644 Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.h create mode 100644 Source/Services/Stats/WinRT/UserStatisticsService_WinRT.cpp create mode 100644 Source/Services/Stats/WinRT/UserStatisticsService_WinRT.h create mode 100644 Source/Services/Stats/requested_statistics.cpp create mode 100644 Source/Services/Stats/service_configuration_statistic.cpp create mode 100644 Source/Services/Stats/statistic.cpp create mode 100644 Source/Services/Stats/statistic_change_event_args.cpp create mode 100644 Source/Services/Stats/statistic_change_subscription.cpp create mode 100644 Source/Services/Stats/user_statistics_internal.h create mode 100644 Source/Services/Stats/user_statistics_result.cpp create mode 100644 Source/Services/Stats/user_statistics_service.cpp create mode 100644 Source/Services/Stats/user_statistics_service_impl.cpp create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.cpp create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.cpp create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.cpp create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageBlobType_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageETagMatchCondition_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.cpp create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.cpp create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.h create mode 100644 Source/Services/TitleStorage/WinRT/TitleStorageType_WinRT.h create mode 100644 Source/Services/TitleStorage/title_storage_blob_metadata.cpp create mode 100644 Source/Services/TitleStorage/title_storage_blob_metadata_result.cpp create mode 100644 Source/Services/TitleStorage/title_storage_blob_result.cpp create mode 100644 Source/Services/TitleStorage/title_storage_quota.cpp create mode 100644 Source/Services/TitleStorage/title_storage_service.cpp create mode 100644 Source/Services/Tournaments/WinRT/TournamentArbitrationState_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentArbitrationStatus_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentGameResultSource_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentGameResultState_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentReference_WinRT.cpp create mode 100644 Source/Services/Tournaments/WinRT/TournamentReference_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentRegistrationReason_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentRegistrationState_WinRT.h create mode 100644 Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.cpp create mode 100644 Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.h create mode 100644 Source/Services/Tournaments/tournament_reference.cpp create mode 100644 Source/Services/Tournaments/tournament_team_result.cpp create mode 100644 Source/Shared/Desktop/local_config_desktop.cpp create mode 100644 Source/Shared/Logger/ERA_ETW.h create mode 100644 Source/Shared/Logger/ERA_ETW.man create mode 100644 Source/Shared/Logger/android/logcat_output.cpp create mode 100644 Source/Shared/Logger/android/logcat_output.h create mode 100644 Source/Shared/Logger/console_output.cpp create mode 100644 Source/Shared/Logger/console_output.h create mode 100644 Source/Shared/Logger/custom_output.cpp create mode 100644 Source/Shared/Logger/custom_output.h create mode 100644 Source/Shared/Logger/debug_output.cpp create mode 100644 Source/Shared/Logger/debug_output.h create mode 100644 Source/Shared/Logger/era_etw.rc create mode 100644 Source/Shared/Logger/era_etwTEMP.BIN create mode 100644 Source/Shared/Logger/era_etw_MSG00001.bin create mode 100644 Source/Shared/Logger/era_etw_headergen_readme.txt create mode 100644 Source/Shared/Logger/etw_output.cpp create mode 100644 Source/Shared/Logger/etw_output.h create mode 100644 Source/Shared/Logger/iOS/debug_output_ios.cpp create mode 100644 Source/Shared/Logger/log.cpp create mode 100644 Source/Shared/Logger/log.h create mode 100644 Source/Shared/Logger/log_entry.cpp create mode 100644 Source/Shared/Logger/log_output.cpp create mode 100644 Source/Shared/WinRT/AppConfiguration_WinRT.cpp create mode 100644 Source/Shared/WinRT/AppConfiguration_WinRT.h create mode 100644 Source/Shared/WinRT/Event_WinRT.cpp create mode 100644 Source/Shared/WinRT/Event_WinRT.h create mode 100644 Source/Shared/WinRT/HttpCallRequestMessage_WinRT.cpp create mode 100644 Source/Shared/WinRT/HttpCallRequestMessage_WinRT.h create mode 100644 Source/Shared/WinRT/HttpRequestMessageType_WinRT.h create mode 100644 Source/Shared/WinRT/Macros_WinRT.h create mode 100644 Source/Shared/WinRT/ServiceCallLoggingConfig_WinRT.cpp create mode 100644 Source/Shared/WinRT/ServiceCallLoggingConfig_WinRT.h create mode 100644 Source/Shared/WinRT/SignInUIEmphasisFeature_WinRT.h create mode 100644 Source/Shared/WinRT/SignInUIGameCategory_WinRT.h create mode 100644 Source/Shared/WinRT/SignInUISettings_WinRT.cpp create mode 100644 Source/Shared/WinRT/SignInUISettings_WinRT.h create mode 100644 Source/Shared/WinRT/Utils_WinRT.cpp create mode 100644 Source/Shared/WinRT/Utils_WinRT.h create mode 100644 Source/Shared/WinRT/XboxLiveContextSettings_WinRT.cpp create mode 100644 Source/Shared/WinRT/XboxLiveContextSettings_WinRT.h create mode 100644 Source/Shared/WinRT/XboxLiveLogCallEventArgs_WinRT.cpp create mode 100644 Source/Shared/WinRT/XboxLiveLogCallEventArgs_WinRT.h create mode 100644 Source/Shared/WinRT/XboxLiveServicesSettings_WinRT.cpp create mode 100644 Source/Shared/WinRT/XboxLiveServicesSettings_WinRT.h create mode 100644 Source/Shared/WinRT/XboxServiceCallRoutedEventArgs_WinRT.cpp create mode 100644 Source/Shared/WinRT/XboxServiceCallRoutedEventArgs_WinRT.h create mode 100644 Source/Shared/WinRT/XboxServicesDiagnosticsTraceLevel_WinRT.h create mode 100644 Source/Shared/WinRT/local_config_winrt.cpp create mode 100644 Source/Shared/a/http_call_jni.cpp create mode 100644 Source/Shared/a/http_call_jni.h create mode 100644 Source/Shared/a/http_call_static_glue.cpp create mode 100644 Source/Shared/a/http_call_static_glue.h create mode 100644 Source/Shared/a/interop_jni.cpp create mode 100644 Source/Shared/a/interop_jni.h create mode 100644 Source/Shared/a/jni_utils.h create mode 100644 Source/Shared/a/local_config_a.cpp create mode 100644 Source/Shared/a/local_config_jni.cpp create mode 100644 Source/Shared/a/local_config_jni.h create mode 100644 Source/Shared/a/local_config_static_glue.cpp create mode 100644 Source/Shared/a/local_config_static_glue.h create mode 100644 Source/Shared/a/title_callable_ui_jni.h create mode 100644 Source/Shared/a/utils_a.cpp create mode 100644 Source/Shared/a/utils_a.h create mode 100644 Source/Shared/a/xbox_live_app_config_android.cpp create mode 100644 Source/Shared/a/xbox_live_app_config_jni.cpp create mode 100644 Source/Shared/a/xbox_live_app_config_static_glue.h create mode 100644 Source/Shared/build_version.h create mode 100644 Source/Shared/errors.cpp create mode 100644 Source/Shared/http_call_impl.cpp create mode 100644 Source/Shared/http_call_impl.h create mode 100644 Source/Shared/http_call_request_message.cpp create mode 100644 Source/Shared/http_call_response.cpp create mode 100644 Source/Shared/http_call_response.h create mode 100644 Source/Shared/http_client.cpp create mode 100644 Source/Shared/http_client.h create mode 100644 Source/Shared/i/local_config_i.mm create mode 100644 Source/Shared/i/utils_locales_ios.mm create mode 100644 Source/Shared/initiator.cpp create mode 100644 Source/Shared/initiator.h create mode 100644 Source/Shared/local_config.cpp create mode 100644 Source/Shared/local_config.h create mode 100644 Source/Shared/mem.cpp create mode 100644 Source/Shared/perf_tester.h create mode 100644 Source/Shared/service_call_logger.cpp create mode 100644 Source/Shared/service_call_logger.h create mode 100644 Source/Shared/service_call_logger_data.cpp create mode 100644 Source/Shared/service_call_logger_data.h create mode 100644 Source/Shared/service_call_logger_protocol.cpp create mode 100644 Source/Shared/service_call_logger_protocol.h create mode 100644 Source/Shared/service_call_logging_config.cpp create mode 100644 Source/Shared/shared_macros.h create mode 100644 Source/Shared/telemetry.cpp create mode 100644 Source/Shared/telemetry.h create mode 100644 Source/Shared/u/local_config_u.cpp create mode 100644 Source/Shared/user_context.cpp create mode 100644 Source/Shared/user_context.h create mode 100644 Source/Shared/utils.cpp create mode 100644 Source/Shared/utils.h create mode 100644 Source/Shared/utils_locales.cpp create mode 100644 Source/Shared/web_socket_client.cpp create mode 100644 Source/Shared/web_socket_client.h create mode 100644 Source/Shared/web_socket_connection.cpp create mode 100644 Source/Shared/web_socket_connection.h create mode 100644 Source/Shared/web_socket_connection_state.h create mode 100644 Source/Shared/xbox_live_app_config.cpp create mode 100644 Source/Shared/xbox_live_context_settings.cpp create mode 100644 Source/Shared/xbox_live_services_settings.cpp create mode 100644 Source/Shared/xbox_service_call_routed_event_args.cpp create mode 100644 Source/Shared/xbox_system_factory.cpp create mode 100644 Source/Shared/xbox_system_factory.h create mode 100644 Source/Shared/xbox_system_factory_ios.mm create mode 100644 Source/System/WinRT/GetTokenAndSignatureResult_WinRT.cpp create mode 100644 Source/System/WinRT/GetTokenAndSignatureResult_WinRT.h create mode 100644 Source/System/WinRT/SignInResult_WinRT.h create mode 100644 Source/System/WinRT/SignInStatus_WinRT.h create mode 100644 Source/System/WinRT/User_WinRT.cpp create mode 100644 Source/System/WinRT/User_WinRT.h create mode 100644 Source/System/a/auth_flow_result_jni.cpp create mode 100644 Source/System/a/auth_flow_result_jni.h create mode 100644 Source/System/a/auth_flow_result_static_glue.cpp create mode 100644 Source/System/a/auth_flow_result_static_glue.h create mode 100644 Source/System/a/java_interop.cpp create mode 100644 Source/System/a/java_interop.h create mode 100644 Source/System/a/user_android.cpp create mode 100644 Source/System/a/user_auth_android.cpp create mode 100644 Source/System/a/user_auth_android.h create mode 100644 Source/System/a/user_impl_a.h create mode 100644 Source/System/a/user_impl_android.cpp create mode 100644 Source/System/a/user_impl_delegated_android.cpp create mode 100644 Source/System/auth/Desktop/Ecdsa.cpp create mode 100644 Source/System/auth/Desktop/algorithm_provider.cpp create mode 100644 Source/System/auth/Desktop/algorithm_provider.h create mode 100644 Source/System/auth/Desktop/ip_address_desktop.cpp create mode 100644 Source/System/auth/Desktop/request_signer.cpp create mode 100644 Source/System/auth/Desktop/sha256.cpp create mode 100644 Source/System/auth/Desktop/sha256.h create mode 100644 Source/System/auth/Unix/big_num.cpp create mode 100644 Source/System/auth/Unix/big_num.h create mode 100644 Source/System/auth/Unix/ecdsa_unix.cpp create mode 100644 Source/System/auth/Unix/ip_address_unix.cpp create mode 100644 Source/System/auth/Unix/request_signer.cpp create mode 100644 Source/System/auth/Unix/sha256.cpp create mode 100644 Source/System/auth/Unix/sha256.h create mode 100644 Source/System/auth/auth_manager.cpp create mode 100644 Source/System/auth/auth_manager.h create mode 100644 Source/System/auth/cidr.cpp create mode 100644 Source/System/auth/cidr.h create mode 100644 Source/System/auth/device_token_service.cpp create mode 100644 Source/System/auth/device_token_service.h create mode 100644 Source/System/auth/ecdsa.h create mode 100644 Source/System/auth/ip_address.cpp create mode 100644 Source/System/auth/ip_address.h create mode 100644 Source/System/auth/json_web_key.cpp create mode 100644 Source/System/auth/json_web_key.h create mode 100644 Source/System/auth/nsal.cpp create mode 100644 Source/System/auth/nsal.h create mode 100644 Source/System/auth/nsal_endpoint.cpp create mode 100644 Source/System/auth/nsal_endpoint.h create mode 100644 Source/System/auth/request_signer.h create mode 100644 Source/System/auth/request_signer_helpers.cpp create mode 100644 Source/System/auth/request_signer_helpers.h create mode 100644 Source/System/auth/service_token_service.cpp create mode 100644 Source/System/auth/service_token_service.h create mode 100644 Source/System/auth/signature_policy.cpp create mode 100644 Source/System/auth/signature_policy.h create mode 100644 Source/System/auth/title_token_service.cpp create mode 100644 Source/System/auth/title_token_service.h create mode 100644 Source/System/auth/token_error.cpp create mode 100644 Source/System/auth/token_error.h create mode 100644 Source/System/auth/token_manager.cpp create mode 100644 Source/System/auth/token_manager.h create mode 100644 Source/System/auth/token_request.cpp create mode 100644 Source/System/auth/token_request.h create mode 100644 Source/System/auth/token_result.cpp create mode 100644 Source/System/auth/token_result.h create mode 100644 Source/System/auth/trie.cpp create mode 100644 Source/System/auth/trie.h create mode 100644 Source/System/auth/user_token_service.cpp create mode 100644 Source/System/auth/user_token_service.h create mode 100644 Source/System/auth/xbox_live_server.cpp create mode 100644 Source/System/auth/xbox_live_server_impl.cpp create mode 100644 Source/System/auth/xbox_live_server_impl.h create mode 100644 Source/System/auth/xsts_token_service.cpp create mode 100644 Source/System/auth/xsts_token_service.h create mode 100644 Source/System/auth/xtitle_service.cpp create mode 100644 Source/System/auth/xtitle_service.h create mode 100644 Source/System/auth_config.cpp create mode 100644 Source/System/auth_config.h create mode 100644 Source/System/iOS/XBLDictionaryToJSON.h create mode 100644 Source/System/iOS/XBLDictionaryToJSON.mm create mode 100644 Source/System/iOS/XBLServiceManager.h create mode 100644 Source/System/iOS/XBLServiceManager.mm create mode 100644 Source/System/iOS/XBLiOSGlobalState.h create mode 100644 Source/System/iOS/XBLiOSGlobalState.mm create mode 100644 Source/System/iOS/XboxTelemetry/UTCIdpNames.h create mode 100644 Source/System/iOS/XboxTelemetry/UTCIdpNames.mm create mode 100644 Source/System/iOS/XboxTelemetry/XLSCll.h create mode 100644 Source/System/iOS/XboxTelemetry/XLSCll.mm create mode 100644 Source/System/iOS/XboxUIDelegates/XBLSignInHandler.h create mode 100644 Source/System/iOS/XboxUIDelegates/XBLSignInHandler.mm create mode 100644 Source/System/iOS/XboxUIDelegates/XboxSignInHandler.h create mode 100644 Source/System/iOS/XboxUIDelegates/XboxSignInHandler.mm create mode 100644 Source/System/iOS/XboxUIDelegates/sign_in_delegate_ios.h create mode 100644 Source/System/iOS/XboxUIDelegates/sign_in_delegate_ios.mm create mode 100644 Source/System/iOS/auth/user_auth_ios.h create mode 100644 Source/System/iOS/auth/user_auth_ios.mm create mode 100644 Source/System/iOS/xbox_cll.mm create mode 100644 Source/System/iOS/xbox_live_app_config_ios.mm create mode 100644 Source/System/ppltasks_extra.h create mode 100644 Source/System/ppltasks_extra_unix.h create mode 100644 Source/System/system_internal.h create mode 100644 Source/System/token_and_signature_result.cpp create mode 100644 Source/System/user.cpp create mode 100644 Source/System/user_impl.cpp create mode 100644 Source/System/user_impl.h create mode 100644 Source/System/user_impl_idp.cpp create mode 100644 Source/System/user_impl_ios.h create mode 100644 Source/System/user_impl_ios.mm create mode 100644 Source/System/user_impl_server.cpp create mode 100644 Source/System/user_ios.mm create mode 100644 Source/System/xbox_live_mutex.cpp create mode 100644 Tests/UnitTests/Mocks/MockHttpCall.cpp create mode 100644 Tests/UnitTests/Mocks/MockHttpCall.h create mode 100644 Tests/UnitTests/Mocks/MockHttpClient.cpp create mode 100644 Tests/UnitTests/Mocks/MockHttpClient.h create mode 100644 Tests/UnitTests/Mocks/MockLocalConfig.cpp create mode 100644 Tests/UnitTests/Mocks/MockLocalConfig.h create mode 100644 Tests/UnitTests/Mocks/MockMultiplayer.cpp create mode 100644 Tests/UnitTests/Mocks/MockMultiplayer.h create mode 100644 Tests/UnitTests/Mocks/MockSocialManager.cpp create mode 100644 Tests/UnitTests/Mocks/MockSocialManager.h create mode 100644 Tests/UnitTests/Mocks/MockUser.cpp create mode 100644 Tests/UnitTests/Mocks/MockUser.h create mode 100644 Tests/UnitTests/Mocks/MockUserTokenService.cpp create mode 100644 Tests/UnitTests/Mocks/MockUserTokenService.h create mode 100644 Tests/UnitTests/Mocks/MockWebSocketClient.h create mode 100644 Tests/UnitTests/Mocks/MockXTitleService.cpp create mode 100644 Tests/UnitTests/Mocks/MockXTitleService.h create mode 100644 Tests/UnitTests/Mocks/MockXboxSystemFactory.cpp create mode 100644 Tests/UnitTests/Mocks/MockXboxSystemFactory.h create mode 100644 Tests/UnitTests/Mocks/MockXstsTokenService.cpp create mode 100644 Tests/UnitTests/Mocks/MockXstsTokenService.h create mode 100644 Tests/UnitTests/Mocks/StockMocks.cpp create mode 100644 Tests/UnitTests/Mocks/StockMocks.h create mode 100644 Tests/UnitTests/Support/DefineTestMacros.h create mode 100644 Tests/UnitTests/Support/TAEF/UnitTestBase.cpp create mode 100644 Tests/UnitTests/Support/TAEF/UnitTestBase.h create mode 100644 Tests/UnitTests/Support/TAEF/UnitTestBase_winrt.cpp create mode 100644 Tests/UnitTests/Support/TAEF/UnitTestBase_winrt.h create mode 100644 Tests/UnitTests/Support/TAEF/UnitTestIncludes_TAEF.h create mode 100644 Tests/UnitTests/Support/TE/UnitTestHelpers.cpp create mode 100644 Tests/UnitTests/Support/TE/UnitTestHelpers.h create mode 100644 Tests/UnitTests/Support/TE/UnitTestIncludes_TE.h create mode 100644 Tests/UnitTests/Support/UnitTestIncludes.h create mode 100644 Tests/UnitTests/Support/iso8601.cpp create mode 100644 Tests/UnitTests/Support/iso8601.h create mode 100644 Tests/UnitTests/Support/unittest_output.cpp create mode 100644 Tests/UnitTests/Support/unittest_output.h create mode 100644 Tests/UnitTests/Tests/Services/AchievementsTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/ContextualSearchTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/EntertainmentProfileTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/ErrorTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/GameServerPlatformTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/LeaderboardTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/MarketplaceTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/MatchmakingTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/MultiplayerManagerTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/MultiplayerTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/PeoplehubTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/PresenceTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/PrivacyTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/ProfileTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/RealTimeActivityTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/ReputationTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/RtaTestHelper.cpp create mode 100644 Tests/UnitTests/Tests/Services/RtaTestHelper.h create mode 100644 Tests/UnitTests/Tests/Services/SocialManagerHelper.h create mode 100644 Tests/UnitTests/Tests/Services/SocialManagerTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/SocialTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/StatsTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/StringVerifyTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/TestResponses/Matchmaking.json create mode 100644 Tests/UnitTests/Tests/Services/TestResponses/Multiplayer.json create mode 100644 Tests/UnitTests/Tests/Services/TestResponses/MultiplayerManager.json create mode 100644 Tests/UnitTests/Tests/Services/TitleStorageTests.cpp create mode 100644 Tests/UnitTests/Tests/Services/TournamentsTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/EventTests_WinRT.cpp create mode 100644 Tests/UnitTests/Tests/Shared/HttpCallResponseTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/HttpCallSettingsTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/HttpCallSettingsTests_WinRT.cpp create mode 100644 Tests/UnitTests/Tests/Shared/LogTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/ServiceCallLoggerTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/UtilTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/WebsocketTests.cpp create mode 100644 Tests/UnitTests/Tests/Shared/XboxLiveContextTests.cpp create mode 100644 Tests/UnitTests/Tests/System/CidrTests.cpp create mode 100644 Tests/UnitTests/Tests/System/EcdsaTests.cpp create mode 100644 Tests/UnitTests/Tests/System/IpAddressTests.cpp create mode 100644 Tests/UnitTests/Tests/System/NsalTests.cpp create mode 100644 Tests/UnitTests/Tests/System/RequestSignerTests.cpp create mode 100644 Tests/UnitTests/Tests/System/TokenErrorResponseTests.cpp create mode 100644 Tests/UnitTests/Tests/System/TokenResultTests.cpp create mode 100644 Tests/UnitTests/Tests/System/UserTests.cpp create mode 100644 Tests/UnitTests/Tests/System/UserTests_WinRT.cpp create mode 100644 Tests/UnitTests/Tests/System/UserTokenResultTests.cpp create mode 100644 Tests/UnitTests/Tests/System/UserTokenServiceTests.cpp create mode 100644 Tests/UnitTests/Tests/System/XTitleServiceTests.cpp create mode 100644 Tests/UnitTests/Tests/System/XboxSystemFactoryTests.cpp create mode 100644 Tests/UnitTests/Tests/System/XstsTokenServiceTests.cpp create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.Cpp.UWP.nuspec create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.Cpp.UWP.targets create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.Cpp.XboxOneXDK.nuspec create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.Cpp.XboxOneXDK.targets create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.WinRT.UWP.nuspec create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.WinRT.UWP.targets create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.WinRT.XboxOneXDK.nuspec create mode 100644 Utilities/Nuget/Microsoft.Xbox.Live.Services.API.WinRT.XboxOneXDK.targets create mode 100644 Utilities/VSOBuildScripts/ABIHeaderGen/DurangoVars.cmd create mode 100644 Utilities/VSOBuildScripts/ABIHeaderGen/GenerateABIOnBuildServer.cmd create mode 100644 Utilities/VSOBuildScripts/CppWinRTCompiler/CompileCppWinRT.cmd create mode 100644 Utilities/VSOBuildScripts/CppWinRTCompiler/ERA.rsp create mode 100644 Utilities/VSOBuildScripts/CppWinRTCompiler/WinSDK.rsp create mode 100644 Utilities/VSOBuildScripts/FindAndReplace.exe create mode 100644 Utilities/VSOBuildScripts/GenSDKBuildCppFile.exe create mode 100644 Utilities/VSOBuildScripts/GenSDKBuildCppFile/App.config create mode 100644 Utilities/VSOBuildScripts/GenSDKBuildCppFile/GenSDKBuildCppFile.csproj create mode 100644 Utilities/VSOBuildScripts/GenSDKBuildCppFile/GenSDKBuildCppFile.sln create mode 100644 Utilities/VSOBuildScripts/GenSDKBuildCppFile/Program.cs create mode 100644 Utilities/VSOBuildScripts/GenSDKBuildCppFile/Properties/AssemblyInfo.cs create mode 100644 Utilities/VSOBuildScripts/postBuildScript.cmd create mode 100644 Utilities/VSOBuildScripts/preCompileScript.cmd create mode 100644 Utilities/VSOBuildScripts/setBuildVersion.cmd create mode 100644 Utilities/VSOBuildScripts/skipBuild.cmd create mode 100644 nuget.config create mode 100644 signConfig.xml create mode 100644 xdk.extcomp create mode 100644 xsapi.staticlib.props diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1ff0c423 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..65afa39f --- /dev/null +++ b/.gitignore @@ -0,0 +1,111 @@ +.gitconfig +.git-credentials + +# Ignore OpenSSL and Boost build files for iOS + +.gitk +.config/git/gitk + +**/.vs/ + +Casablanca*/Build_iOS/OpenSSL-for-iPhone/ +Casablanca*/Build_iOS/boostoniphone/ +Casablanca*/Build_iOS/openssl/ +Casablanca*/Build_iOS/boost.framework/ +Casablanca*/Build_iOS/build.ios/ +Casablanca*/Build_iOS/ios-cmake/ + +#nuget packages +External/Packages/* + +# Xcode + +xcuserdata + +# Mac + +.DS_Store + +# VS temp files +**/*.sln.ide/ +**/*.opensdf +**/*.sdf +**/*.suo +**/*.opendb +**/*.VC.db +**/*.user +**/ipch/ +**/Generated Files/ +**/AppPackages/* +**/*.orig +**/pingme.txt +**/*.cache +**/dlldata.c +**/*_i.c +**/*_p.c +**/*.metaproj +**/*.metaproj.tmp +**/*.opendb +**/*.coveragexml + +**/Durango/ +**/XboxOne.x64/ +Samples/**/bin/ +Samples/**/Debug/ +Samples/**/Release/ +Samples/**/Profile/ +Samples/**/Lib/ +Samples/**/.workspace/ +Source/**/bin/ +Source/**/gen/ +Source/**/Debug/ +Source/**/Release/ +Archive/**/Debug/ +Archive/**/Release/ +Archive/**/Durango/ +Archive/**/Lib/ +Archive/**/*.winmd +Build/**/Debug/ +Build/**/Release/ +External/**/lib/ +External/**/bin/ +External/**/Debug/ +External/**/Release/ +tests/**/bin/ +tests/**/Debug/ +tests/**/Release/ +Tools/**/bin/ +Tools/**/obj/ +**/*.classpath + +**/local.properties + +**/.workspace/ + +#Doxygen temp files +Docs/xblsdk_cpp/ +Docs/xblsdk_winrt/ +Docs/External/ +Docs/xim_cpp/ + +# Unit Test +FakesAssemblies/ +TestResults/ + +# Build objects + +Casablanca/Intermediate/ +Obj/ +Binaries/ +Win32/ +Debug/ +Release/ +ARM/ + +# Allow files in our /Build folder +!/Build +!/Casablanca + +!TAEF/** + +**/.vs/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..5c50d8ea --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "External/cpprestsdk"] + path = External/cpprestsdk + url = https://github.com/jasonsandlin/cpprestsdk.git diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Build.Durango.Cpp.props b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Build.Durango.Cpp.props new file mode 100644 index 00000000..343d88d9 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Build.Durango.Cpp.props @@ -0,0 +1,29 @@ + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + + + + + ixmlhttprequest2.lib;combase.lib;kernelx.lib;uuid.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + + + + msxml6.lib;runtimeobject.lib;mincore.lib;mincore_legacy.lib;mincore_obsolete.lib;user32.lib;uuid.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.sln b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.sln new file mode 100644 index 00000000..509c8edf --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.110.XDK.Cpp", "Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj", "{8F96710E-5169-4917-8874-7DE248F4D243}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "casablanca110.xbox", "..\..\External\cpprestsdk\Release\src\build\vs11.xbox\casablanca110.Xbox.vcxproj", "{E621C269-D177-4C1B-80EA-C0A274B7A151}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|Durango.ActiveCfg = Debug|Durango + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|Durango.Build.0 = Debug|Durango + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|Durango.ActiveCfg = Release|Durango + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|Durango.Build.0 = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.ActiveCfg = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.Build.0 = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.ActiveCfg = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.Build.0 = Release|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Debug|Durango.ActiveCfg = Debug|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Debug|Durango.Build.0 = Debug|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Release|Durango.ActiveCfg = Release|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj new file mode 100644 index 00000000..a9a7ddce --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj @@ -0,0 +1,386 @@ + + + + + Debug + Durango + + + Release + Durango + + + + + title + {8F96710E-5169-4917-8874-7DE248F4D243} + Win32Proj + Microsoft.Xbox.Services.110.XDK.Cpp + Microsoft.Xbox.Services + en-US + 11.0 + true + true + StaticLibrary + false + false + + + v110 + + + + true + Unicode + + + Unicode + false + false + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {e621c269-d177-4c1b-80ea-c0a274b7a151} + + + + + Use + _NO_ASYNCRTIMP;_NO_PPLXIMP;_NO_XSAPIIMP;%(PreprocessorDefinitions) + _XSAPIIMP_EXPORT;%(PreprocessorDefinitions) + _VARIADIC_MAX=10;ENABLE_INTSAFE_SIGNED_FUNCTIONS;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /Zm250 %(AdditionalOptions) + $(OutDir)$(ProjectName).pdb + Level4 + false + true + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Desktop; + $(ProjectDir)\..\..\Source\Services\Common\Durango; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Achievements; + $(ProjectDir)\..\..\Source\Services\Leaderboard; + $(ProjectDir)\..\..\Source\Services\Stats; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Matchmaking; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\; + $(ProjectDir)\..\..\Include; + $(ProjectDir)\..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\TitleStorage; + %(AdditionalIncludeDirectories) + + + Console + + + /ignore:4264 %(AdditionalOptions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + + + /ignore:4264 %(AdditionalOptions) + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj.filters b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj.filters new file mode 100644 index 00000000..ab7263f9 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Cpp.vcxproj.filters @@ -0,0 +1,903 @@ + + + + + {6608be30-e73a-44dc-89f4-bbae78aa0877} + + + {67d5c9b8-1ece-48da-8048-8f7a7b3456ea} + + + {a10dda2a-8d3d-4d37-aa6c-b8200939bb72} + + + {f6f5f2e6-4803-46ad-a9c3-c78735a5310f} + + + {6a65ddda-fa44-472f-9330-8a61a35822e4} + + + {104d8f4f-6a5d-410c-a9ca-f35ad13a6947} + + + {1c135ef4-998b-4085-8511-0e0df5c9276d} + + + {9e2ecd8b-a225-4608-ad19-04d9f208879d} + + + {d7992e81-b6dd-4019-b6ad-0120179a764e} + + + {445f8c8a-0143-4214-bf51-8542f9752990} + + + {6d5ac48d-71c7-4fd0-a2c4-e274aea87ef9} + + + {2cd0260c-1aa0-48a1-8ea2-0bea92c5fef0} + + + {2537d770-c646-4fb7-822a-3a01480b37b0} + + + {e787eb28-a6d4-4b09-a3ea-f3e05aba564e} + + + {824cab2e-845a-4410-b308-41acda6f2b22} + + + {ab536799-29a7-42e5-acaa-94ac987ae6cf} + + + {e7814213-f187-402d-8163-17af50c41b89} + + + {3f42a4b7-3191-4589-b2fa-2763820d762a} + + + {a3b66114-c964-40b0-af39-21a6d09992eb} + + + {eefe0d87-3c09-46f8-9c87-112f5de6f2a2} + + + {4c480269-72ca-4198-ac95-b375458e053c} + + + {73644e7c-c648-4d11-9012-c96a4a1b2a52} + + + {369eecf7-03a0-44f0-af01-10ac8e3a3bcf} + + + {5047323b-fba7-4e05-84e2-e5bad7c80e72} + + + {bca879e6-bf06-4f96-814e-a0c35d1a0e0a} + + + + + Shared + + + Shared + + + Shared + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Social + + + C++ Source\Social + + + Shared + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\RTA + + + C++ Source\RTA + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Multiplayer + + + C++ Source\RTA + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Common\Desktop + + + C++ Source\Common\Desktop + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + Shared + + + C++ Source\Multiplayer + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + Shared + + + C++ Source\GameServerPlatform + + + Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + Shared + + + C++ Source\RTA + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Common + + + C++ Source\Presence + + + C++ Source\UserStats + + + System + + + C++ Source\Social + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Social\Manager + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + Shared + + + Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + Shared\logger + + + Shared + + + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Common\Desktop + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Presence + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\UserStats + + + C++ Source\Social + + + C++ Source\Common + + + Shared + + + Shared + + + C++ Public Includes + + + Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\Social\Manager + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Misc + + + Shared + + + C++ Public Includes + + + C++ Public Includes + + + System + + + System + + + Shared\logger + + + Shared\logger + + + C++ Source\Misc + + + Shared + + + C++ Public Includes + + + Shared\logger + + + Shared\logger + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.sln b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.sln new file mode 100644 index 00000000..5ce28f69 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.110.XDK.Ship.Cpp", "Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj", "{20E87245-DA60-40E5-9938-ABB445E78467}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "casablanca110.xbox", "..\..\External\cpprestsdk\Release\src\build\vs11.xbox\casablanca110.Xbox.vcxproj", "{E621C269-D177-4C1B-80EA-C0A274B7A151}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {20E87245-DA60-40E5-9938-ABB445E78467}.Debug|Durango.ActiveCfg = Debug|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Debug|Durango.Build.0 = Debug|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Release|Durango.ActiveCfg = Release|Durango + {20E87245-DA60-40E5-9938-ABB445E78467}.Release|Durango.Build.0 = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.ActiveCfg = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.Build.0 = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.ActiveCfg = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj new file mode 100644 index 00000000..58301da7 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Durango + + + Release + Durango + + + + + title + {20E87245-DA60-40E5-9938-ABB445E78467} + Win32Proj + Microsoft.Xbox.Services.110.XDK.Ship.Cpp + Microsoft.Xbox.Services + en-US + 11.0 + true + true + StaticLibrary + v110 + false + false + + + + true + Unicode + + + Unicode + false + false + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {e621c269-d177-4c1b-80ea-c0a274b7a151} + + + + + Use + _NO_ASYNCRTIMP;_NO_PPLXIMP;_NO_XSAPIIMP;%(PreprocessorDefinitions) + _XSAPIIMP_EXPORT;%(PreprocessorDefinitions) + _VARIADIC_MAX=10;ENABLE_INTSAFE_SIGNED_FUNCTIONS;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /Zm250 %(AdditionalOptions) + $(OutDir)$(ProjectName).pdb + Level4 + false + true + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Desktop; + $(ProjectDir)\..\..\Source\Services\Common\Durango; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Achievements; + $(ProjectDir)\..\..\Source\Services\Leaderboard; + $(ProjectDir)\..\..\Source\Services\Stats; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Matchmaking; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\; + $(ProjectDir)\..\..\Include; + $(ProjectDir)\..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\TitleStorage; + %(AdditionalIncludeDirectories) + + + Console + + + /ignore:4264 %(AdditionalOptions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + + + /ignore:4264 %(AdditionalOptions) + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj.filters b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj.filters new file mode 100644 index 00000000..db43968b --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/Microsoft.Xbox.Services.110.XDK.Ship.Cpp.vcxproj.filters @@ -0,0 +1,261 @@ + + + + + {6608be30-e73a-44dc-89f4-bbae78aa0877} + + + {67d5c9b8-1ece-48da-8048-8f7a7b3456ea} + + + {a10dda2a-8d3d-4d37-aa6c-b8200939bb72} + + + {f6f5f2e6-4803-46ad-a9c3-c78735a5310f} + + + {6a65ddda-fa44-472f-9330-8a61a35822e4} + + + {104d8f4f-6a5d-410c-a9ca-f35ad13a6947} + + + {1c135ef4-998b-4085-8511-0e0df5c9276d} + + + {9e2ecd8b-a225-4608-ad19-04d9f208879d} + + + {d7992e81-b6dd-4019-b6ad-0120179a764e} + + + {445f8c8a-0143-4214-bf51-8542f9752990} + + + {6d5ac48d-71c7-4fd0-a2c4-e274aea87ef9} + + + {2cd0260c-1aa0-48a1-8ea2-0bea92c5fef0} + + + {2537d770-c646-4fb7-822a-3a01480b37b0} + + + {e787eb28-a6d4-4b09-a3ea-f3e05aba564e} + + + {824cab2e-845a-4410-b308-41acda6f2b22} + + + {ab536799-29a7-42e5-acaa-94ac987ae6cf} + + + {e7814213-f187-402d-8163-17af50c41b89} + + + {369eecf7-03a0-44f0-af01-10ac8e3a3bcf} + + + {3f42a4b7-3191-4589-b2fa-2763820d762a} + + + {e2fa6a55-15a6-4f89-a716-7fc00fd95c2c} + + + {a3b66114-c964-40b0-af39-21a6d09992eb} + + + {eefe0d87-3c09-46f8-9c87-112f5de6f2a2} + + + {23644df4-afdf-4298-95eb-97d634eda04c} + + + + + C++ Source\Common\Desktop + + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + Shared\Desktop + + + C++ Source\Common\Desktop + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Common\Durango + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Multiplayer\Manager + + + System + + + C++ Source\Presence + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\UserStats + + + C++ Source\Social + + + C++ Source\Common + + + Shared + + + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.110.XDK.Cpp/build.cpp b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/build.cpp new file mode 100644 index 00000000..bc0d8fc8 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.110.XDK.Cpp/build.cpp @@ -0,0 +1,207 @@ +#include "pch.h" + +#include "..\..\Source\Services\Achievements\achievement.cpp" +#include "..\..\Source\Services\Achievements\achievements_result.cpp" +#include "..\..\Source\Services\Achievements\achievement_media_asset.cpp" +#include "..\..\Source\Services\Achievements\achievement_progression.cpp" +#include "..\..\Source\Services\Achievements\achievement_requirement.cpp" +#include "..\..\Source\Services\Achievements\achievement_reward.cpp" +#include "..\..\Source\Services\Achievements\achievement_service.cpp" +#include "..\..\Source\Services\Achievements\achievement_time_window.cpp" +#include "..\..\Source\Services\Achievements\achievement_title_association.cpp" +#include "..\..\Source\Services\Common\xbox_live_context_impl.cpp" +#include "..\..\Source\Services\Common\Desktop\XboxLiveContext_Desktop.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile_list_contains_item_result.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile_list_xbox_one_pins.cpp" +#include "..\..\Source\Services\GameServerPlatform\allocation_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\cluster_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_image_set.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_metadata_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_platform_service.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_port_mapping.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_ticket_status.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_variant.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_variant_schema.cpp" +#include "..\..\Source\Services\GameServerPlatform\quality_of_service_server.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_column.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_result.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_row.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_serializers.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_service.cpp" +#include "..\..\Source\Services\Marketplace\browse_catalog_result.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item_availability.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item_details.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item_image.cpp" +#include "..\..\Source\Services\Marketplace\catalog_service.cpp" +#include "..\..\Source\Services\Marketplace\catalog_total.cpp" +#include "..\..\Source\Services\Marketplace\consume_inventory_item_request.cpp" +#include "..\..\Source\Services\Marketplace\consume_inventory_item_result.cpp" +#include "..\..\Source\Services\Marketplace\inventory_item.cpp" +#include "..\..\Source\Services\Marketplace\inventory_items_result.cpp" +#include "..\..\Source\Services\Marketplace\inventory_service.cpp" +#include "..\..\Source\Services\Matchmaking\create_match_ticket_response.cpp" +#include "..\..\Source\Services\Matchmaking\hopper_statistics_response.cpp" +#include "..\..\Source\Services\Matchmaking\matchmaking_service.cpp" +#include "..\..\Source\Services\Matchmaking\match_ticket_details_response.cpp" +#include "..\..\Source\Services\Misc\contextual_config_result.cpp" +#include "..\..\Source\Services\Misc\contextual_search_broadcast.cpp" +#include "..\..\Source\Services\Misc\contextual_search_configured_stat.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clips_result.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip_stat.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip_thumbnail.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip_uri_info.cpp" +#include "..\..\Source\Services\Misc\contextual_search_service.cpp" +#include "..\..\Source\Services\Misc\string_service.cpp" +#include "..\..\Source\Services\Misc\verify_string_result.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_details.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_query_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_get_sessions_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_invite.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_invite_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_managed_initialization.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_peer_to_host_requirements.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_peer_to_peer_requirements.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_quality_of_service_measurement.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_search_handle_details.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_search_handle_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_service.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_service_impl.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_arbitration_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_capabilities.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_change_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_constants.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_matchmaking_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_member.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_member_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_properties.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_reference.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_states.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_tournaments_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_subscription.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_transfer_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\find_match_completed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\host_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\join_lobby_completed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\matchmaking_client_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_joined_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_left_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_property_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_pending_reader.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_pending_request.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_event.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_game_client.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_game_session.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_lobby_client.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_lobby_session.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_local_user.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_local_user_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_manager_utils.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_member.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_session_writer.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\perform_qos_measurements_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\session_property_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\tournament_game_session_ready_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\tournament_registration_state_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\user_added_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\user_removed_event_args.cpp" +#include "..\..\Source\Services\Presence\device_presence_change_event_args.cpp" +#include "..\..\Source\Services\Presence\device_presence_change_subscription.cpp" +#include "..\..\Source\Services\Presence\media_presence_data.cpp" +#include "..\..\Source\Services\Presence\presence_activity_data.cpp" +#include "..\..\Source\Services\Presence\presence_broadcast_record.cpp" +#include "..\..\Source\Services\Presence\presence_data.cpp" +#include "..\..\Source\Services\Presence\presence_device_record.cpp" +#include "..\..\Source\Services\Presence\presence_media_record.cpp" +#include "..\..\Source\Services\Presence\presence_record.cpp" +#include "..\..\Source\Services\Presence\presence_service.cpp" +#include "..\..\Source\Services\Presence\presence_service_impl.cpp" +#include "..\..\Source\Services\Presence\presence_title_record.cpp" +#include "..\..\Source\Services\Presence\presence_title_request.cpp" +#include "..\..\Source\Services\Presence\presence_user_batch_request.cpp" +#include "..\..\Source\Services\Presence\title_presence_change_event_args.cpp" +#include "..\..\Source\Services\Presence\title_presence_change_subscription.cpp" +#include "..\..\Source\Services\Privacy\multiple_permissions_check_result.cpp" +#include "..\..\Source\Services\Privacy\permission_check_result.cpp" +#include "..\..\Source\Services\Privacy\permission_deny_reason.cpp" +#include "..\..\Source\Services\Privacy\privacy_service.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_service.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_service_factory.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_subscription.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_subscription_error_event_args.cpp" +#include "..\..\Source\Services\Social\profile_service.cpp" +#include "..\..\Source\Services\Social\reputation_feedback_request.cpp" +#include "..\..\Source\Services\Social\reputation_service.cpp" +#include "..\..\Source\Services\Social\social_relationship_change_event_args.cpp" +#include "..\..\Source\Services\Social\social_relationship_change_subscription.cpp" +#include "..\..\Source\Services\Social\social_service.cpp" +#include "..\..\Source\Services\Social\social_service_impl.cpp" +#include "..\..\Source\Services\Social\xbox_social_relationship.cpp" +#include "..\..\Source\Services\Social\xbox_social_relationship_result.cpp" +#include "..\..\Source\Services\Social\xbox_user_profile.cpp" +#include "..\..\Source\Services\Social\Manager\peoplehub_service.cpp" +#include "..\..\Source\Services\Social\Manager\preferred_color.cpp" +#include "..\..\Source\Services\Social\Manager\social_event.cpp" +#include "..\..\Source\Services\Social\Manager\social_graph.cpp" +#include "..\..\Source\Services\Social\Manager\social_manager.cpp" +#include "..\..\Source\Services\Social\Manager\social_user_group_loaded_event_args.cpp" +#include "..\..\Source\Services\Social\Manager\title_history.cpp" +#include "..\..\Source\Services\Social\Manager\xbox_social_user.cpp" +#include "..\..\Source\Services\Social\Manager\xbox_social_user_group.cpp" +#include "..\..\Source\Services\Stats\requested_statistics.cpp" +#include "..\..\Source\Services\Stats\service_configuration_statistic.cpp" +#include "..\..\Source\Services\Stats\statistic.cpp" +#include "..\..\Source\Services\Stats\statistic_change_event_args.cpp" +#include "..\..\Source\Services\Stats\statistic_change_subscription.cpp" +#include "..\..\Source\Services\Stats\user_statistics_result.cpp" +#include "..\..\Source\Services\Stats\user_statistics_service.cpp" +#include "..\..\Source\Services\Stats\user_statistics_service_impl.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_metadata.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_metadata_result.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_result.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_quota.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_service.cpp" +#include "..\..\Source\Services\Tournaments\tournament.cpp" +#include "..\..\Source\Services\Tournaments\tournaments_result.cpp" +#include "..\..\Source\Services\Tournaments\tournament_game.cpp" +#include "..\..\Source\Services\Tournaments\tournament_reference.cpp" +#include "..\..\Source\Services\Tournaments\tournament_service.cpp" +#include "..\..\Source\Services\Tournaments\tournament_stage.cpp" +#include "..\..\Source\Services\Tournaments\tournament_team.cpp" +#include "..\..\Source\Services\Tournaments\tournament_teams.cpp" +#include "..\..\Source\Services\Tournaments\tournament_team_result.cpp" +#include "..\..\Source\Shared\errors.cpp" +#include "..\..\Source\Shared\http_call_impl.cpp" +#include "..\..\Source\Shared\http_call_request_message.cpp" +#include "..\..\Source\Shared\http_call_response.cpp" +#include "..\..\Source\Shared\http_client.cpp" +#include "..\..\Source\Shared\initiator.cpp" +#include "..\..\Source\Shared\local_config.cpp" +#include "..\..\Source\Shared\service_call_logger.cpp" +#include "..\..\Source\Shared\service_call_logger_data.cpp" +#include "..\..\Source\Shared\service_call_logger_protocol.cpp" +#include "..\..\Source\Shared\service_call_logging_config.cpp" +#include "..\..\Source\Shared\telemetry.cpp" +#include "..\..\Source\Shared\user_context.cpp" +#include "..\..\Source\Shared\utils.cpp" +#include "..\..\Source\Shared\utils_locales.cpp" +#include "..\..\Source\Shared\web_socket_client.cpp" +#include "..\..\Source\Shared\web_socket_connection.cpp" +#include "..\..\Source\Shared\xbox_live_app_config.cpp" +#include "..\..\Source\Shared\xbox_live_context_settings.cpp" +#include "..\..\Source\Shared\xbox_service_call_routed_event_args.cpp" +#include "..\..\Source\Shared\xbox_system_factory.cpp" +#include "..\..\Source\Shared\Desktop\local_config_desktop.cpp" +#include "..\..\Source\Shared\Logger\console_output.cpp" +#include "..\..\Source\Shared\Logger\debug_output.cpp" +#include "..\..\Source\Shared\Logger\log.cpp" +#include "..\..\Source\Shared\Logger\log_entry.cpp" +#include "..\..\Source\Shared\Logger\log_output.cpp" +#include "..\..\Source\System\xbox_live_mutex.cpp" diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.sln b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.sln new file mode 100644 index 00000000..48a2de13 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.140.UWP.Cpp", "Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj", "{8F96710E-5169-4917-8874-7DE248F4D243}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp.static", "..\..\External\cpprestsdk\Release\src\build\vs14.uwp\cpprestsdk140.uwp.static.vcxproj", "{9AD285A2-301E-47A0-A299-14AD5D4F2758}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\External\cpprestsdk\Release\src\build\winrt.vcxitems*{9ad285a2-301e-47a0-a299-14ad5d4f2758}*SharedItemsImports = 4 + ..\..\External\cpprestsdk\Release\src\build\common.vcxitems*{9ad285a2-301e-47a0-a299-14ad5d4f2758}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|ARM.ActiveCfg = Debug|ARM + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|ARM.Build.0 = Debug|ARM + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x64.ActiveCfg = Debug|x64 + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x64.Build.0 = Debug|x64 + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x86.ActiveCfg = Debug|Win32 + {8F96710E-5169-4917-8874-7DE248F4D243}.Debug|x86.Build.0 = Debug|Win32 + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|ARM.ActiveCfg = Release|ARM + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|ARM.Build.0 = Release|ARM + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|x64.ActiveCfg = Release|x64 + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|x64.Build.0 = Release|x64 + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|x86.ActiveCfg = Release|Win32 + {8F96710E-5169-4917-8874-7DE248F4D243}.Release|x86.Build.0 = Release|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|ARM.ActiveCfg = Debug|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|ARM.Build.0 = Debug|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x64.ActiveCfg = Debug|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x64.Build.0 = Debug|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x86.ActiveCfg = Debug|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x86.Build.0 = Debug|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|ARM.ActiveCfg = Release|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|ARM.Build.0 = Release|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x64.ActiveCfg = Release|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x64.Build.0 = Release|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x86.ActiveCfg = Release|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj new file mode 100644 index 00000000..627053a0 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj @@ -0,0 +1,409 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {8F96710E-5169-4917-8874-7DE248F4D243} + Win32Proj + StaticLibrary + v140 + Unicode + Windows Store + 10.0 + en-US + 14.0 + true + false + 10.0.14393.0 + 10.0.10240.0 + + + + true + true + + + false + true + false + + + true + + + + + + + + Use + Level3 + _NO_ASYNCRTIMP;_NO_PPLXIMP;_NO_XSAPIIMP;%(PreprocessorDefinitions) + _XSAPIIMP_EXPORT;%(PreprocessorDefinitions) + true + /bigobj /Zm300 %(AdditionalOptions) + $(OutDir)$(ProjectName).pdb + pch.h + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Desktop; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\Misc; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\Shared\WinRT; + $(ProjectDir)\..\..\Include; + ..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\System\WinRT; + $(ProjectDir)\..\..\Source\System; + %(AdditionalIncludeDirectories) + + true + + + Bcrypt.lib;Pathcch.lib;Ws2_32.lib;%(AdditionalDependencies) + Windows + true + false + + + /ignore:4099 /ignore:4264 + + + + + + + MaxSpeed + true + true + NDEBUG;%(PreprocessorDefinitions) + false + + + true + true + + + + $(MSBuildProjectName) + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectFolder)\ + $(ProjectDir)..\..\Obj\$(Configuration)\$(Platform)\$(ProjectFolder)\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {9AD285A2-301E-47A0-A299-14AD5D4F2758} + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj.filters b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj.filters new file mode 100644 index 00000000..f18a46c6 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Cpp.vcxproj.filters @@ -0,0 +1,915 @@ + + + + + {b79b5071-f94f-443a-b903-1b604db21b8e} + + + {e9e0bd97-69fe-4b02-9f7d-b3cfe9ba4124} + + + {f7602d0a-0baf-4796-b386-097b3cbd025e} + + + {5eb1bf88-b7c6-4004-8f89-a51e2a57015b} + + + {c39487ed-7f31-418f-9787-9376286701e9} + + + {0c334ed5-8f7a-4075-a144-38e4fd0cd7dd} + + + {2bd48536-64fb-44b8-80e2-e811e05b4bb3} + + + {7d5155f9-c8c2-445d-b47b-672ae2fc75b7} + + + {8f56c797-92e5-4c3f-80de-930c15740770} + + + {0a2fe2db-9350-4606-81c6-01c2830d4f7b} + + + {9c6c080f-e261-4948-9bb0-fa2b7d4977dd} + + + {5f357938-0de3-4ba8-bfb4-0d09d88d2e73} + + + {2c7f11e9-3f8e-4935-9a4d-418922b96b80} + + + {8d036207-30a2-41b5-b472-be8757efa25c} + + + {8b4f0f8e-eb71-4ff7-93f8-df2f59384ee3} + + + {b6ce571b-a137-4d72-9a7e-6bd4e338fa2f} + + + {70aae843-2a60-4668-9d25-8459b935bb33} + + + {b5d473a0-e56e-4c1a-a15a-27f5eaa2feee} + + + {dc690502-8de4-4b6f-b5df-6bde484da01e} + + + {1b3da718-f52c-4001-97be-262f70a10a9a} + + + {0d68e1d2-b7d1-4df5-a4d9-0006ddbbb16e} + + + {f5c7d6bd-2bf5-4adb-ab7a-e5c1a1a77b73} + + + {abf9b438-2d5f-4eeb-a1da-5afe2f282511} + + + {dbe50f14-df74-4c7f-ad72-b5b0307db128} + + + {afd7a8d3-c708-4e19-85b4-bdb3a28fbfe8} + + + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\RTA + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Presence + + + C++ Source\Shared + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\Shared + + + C++ Source\Multiplayer + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Common\Desktop + + + C++ Source\Common\Desktop + + + C++ Source\Shared + + + C++ Source\GameServerPlatform + + + C++ Source\Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\System + + + C++ Source\Shared + + + C++ Source\Events + + + C++ Source\Shared + + + C++ Source\Misc + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\RTA + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Shared\WinRT + + + C++ Source\Shared\WinRT + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Presence + + + C++ Source\System + + + C++ Source\UserStats + + + C++ Source\Common + + + C++ Source\Shared + + + C++ Source\Social + + + C++ Source\Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Social\Manager + + + C++ Source\Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\System + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Misc + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Shared + + + C++ Source\RTA + + + C++ Source\Shared + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Social\Manager + + + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\System + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Common\Desktop + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Misc + + + C++ Public Includes + + + C++ Source\Multiplayer\Manager + + + C++ Source\Shared\WinRT + + + C++ Source\System + + + C++ Source\Social + + + C++ Source\Presence + + + C++ Source\Multiplayer + + + C++ Source\UserStats + + + C++ Source\Common + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Source\Social\Manager + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Misc + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Source\System + + + C++ Source\Common + + + C++ Source\System + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\RTA + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.sln b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.sln new file mode 100644 index 00000000..096846d5 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.140.UWP.Ship.Cpp", "Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj", "{47FF466B-C455-48C0-8D89-37E3FC0897F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Debug|ARM.ActiveCfg = Debug|ARM + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Debug|ARM.Build.0 = Debug|ARM + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Debug|x64.ActiveCfg = Debug|x64 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Debug|x64.Build.0 = Debug|x64 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Debug|x86.ActiveCfg = Debug|Win32 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Debug|x86.Build.0 = Debug|Win32 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Release|ARM.ActiveCfg = Release|ARM + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Release|ARM.Build.0 = Release|ARM + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Release|x64.ActiveCfg = Release|x64 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Release|x64.Build.0 = Release|x64 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Release|x86.ActiveCfg = Release|Win32 + {47FF466B-C455-48C0-8D89-37E3FC0897F8}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj new file mode 100644 index 00000000..341ae840 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {47FF466B-C455-48C0-8D89-37E3FC0897F8} + Win32Proj + StaticLibrary + v140 + Unicode + Windows Store + 10.0 + en-US + 14.0 + true + false + 10.0.14393.0 + 10.0.10240.0 + + + + true + true + + + false + true + false + + + true + + + + + + + + Use + Level3 + _NO_ASYNCRTIMP;_NO_PPLXIMP;_NO_XSAPIIMP;%(PreprocessorDefinitions) + _XSAPIIMP_EXPORT;%(PreprocessorDefinitions) + true + /bigobj /Zm250 %(AdditionalOptions) + $(OutDir)$(ProjectName).pdb + pch.h + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Desktop; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\Misc; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\Shared\WinRT; + $(ProjectDir)\..\..\Include; + ..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\System\WinRT; + $(ProjectDir)\..\..\Source\System; + %(AdditionalIncludeDirectories) + + true + + + Bcrypt.lib;Pathcch.lib;Ws2_32.lib;%(AdditionalDependencies) + Windows + true + false + + + /ignore:4099 /ignore:4264 + + + + + + + MaxSpeed + true + true + NDEBUG;%(PreprocessorDefinitions) + false + + + true + true + + + + $(MSBuildProjectName) + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectFolder)\ + $(ProjectDir)..\..\Obj\$(Configuration)\$(Platform)\$(ProjectFolder)\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {9AD285A2-301E-47A0-A299-14AD5D4F2758} + + + + + Create + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj.filters b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj.filters new file mode 100644 index 00000000..c878d129 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/Microsoft.Xbox.Services.140.UWP.Ship.Cpp.vcxproj.filters @@ -0,0 +1,92 @@ + + + + + {b79b5071-f94f-443a-b903-1b604db21b8e} + + + + + + + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.UWP.Cpp/build.cpp b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/build.cpp new file mode 100644 index 00000000..1c508f63 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.Cpp/build.cpp @@ -0,0 +1,206 @@ +#include "pch.h" + +#include "..\..\Source\Services\Achievements\achievement.cpp" +#include "..\..\Source\Services\Achievements\achievements_result.cpp" +#include "..\..\Source\Services\Achievements\achievement_media_asset.cpp" +#include "..\..\Source\Services\Achievements\achievement_progression.cpp" +#include "..\..\Source\Services\Achievements\achievement_requirement.cpp" +#include "..\..\Source\Services\Achievements\achievement_reward.cpp" +#include "..\..\Source\Services\Achievements\achievement_service.cpp" +#include "..\..\Source\Services\Achievements\achievement_time_window.cpp" +#include "..\..\Source\Services\Achievements\achievement_title_association.cpp" +#include "..\..\Source\Services\Common\xbox_live_context_impl.cpp" +#include "..\..\Source\Services\Common\Desktop\pch.cpp" +#include "..\..\Source\Services\Common\Desktop\XboxLiveContext_Desktop.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile_list_contains_item_result.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile_list_xbox_one_pins.cpp" +#include "..\..\Source\Services\Events\events_service.cpp" +#include "..\..\Source\Services\GameServerPlatform\allocation_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\cluster_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_image_set.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_metadata_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_platform_service.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_port_mapping.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_ticket_status.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_variant.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_variant_schema.cpp" +#include "..\..\Source\Services\GameServerPlatform\quality_of_service_server.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_column.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_result.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_row.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_serializers.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_service.cpp" +#include "..\..\Source\Services\Matchmaking\create_match_ticket_response.cpp" +#include "..\..\Source\Services\Matchmaking\hopper_statistics_response.cpp" +#include "..\..\Source\Services\Matchmaking\matchmaking_service.cpp" +#include "..\..\Source\Services\Matchmaking\match_ticket_details_response.cpp" +#include "..\..\Source\Services\Misc\contextual_config_result.cpp" +#include "..\..\Source\Services\Misc\contextual_search_broadcast.cpp" +#include "..\..\Source\Services\Misc\contextual_search_configured_stat.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clips_result.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip_stat.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip_thumbnail.cpp" +#include "..\..\Source\Services\Misc\contextual_search_game_clip_uri_info.cpp" +#include "..\..\Source\Services\Misc\contextual_search_service.cpp" +#include "..\..\Source\Services\Misc\notification_service.cpp" +#include "..\..\Source\Services\Misc\string_service.cpp" +#include "..\..\Source\Services\Misc\title_callable_ui.cpp" +#include "..\..\Source\Services\Misc\verify_string_result.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_details.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_query_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_get_sessions_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_invite.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_invite_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_managed_initialization.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_peer_to_host_requirements.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_peer_to_peer_requirements.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_quality_of_service_measurement.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_search_handle_details.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_search_handle_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_service.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_service_impl.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_arbitration_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_capabilities.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_change_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_constants.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_matchmaking_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_member.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_member_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_properties.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_reference.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_states.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_tournaments_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_subscription.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_transfer_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\find_match_completed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\host_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\join_lobby_completed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\matchmaking_client_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_joined_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_left_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_property_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_pending_reader.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_pending_request.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_event.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_game_client.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_game_session.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_lobby_client.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_lobby_session.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_local_user.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_local_user_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_manager_utils.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_member.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_session_writer.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\perform_qos_measurements_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\session_property_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\tournament_game_session_ready_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\tournament_registration_state_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\user_added_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\user_removed_event_args.cpp" +#include "..\..\Source\Services\Presence\device_presence_change_event_args.cpp" +#include "..\..\Source\Services\Presence\device_presence_change_subscription.cpp" +#include "..\..\Source\Services\Presence\media_presence_data.cpp" +#include "..\..\Source\Services\Presence\presence_activity_data.cpp" +#include "..\..\Source\Services\Presence\presence_broadcast_record.cpp" +#include "..\..\Source\Services\Presence\presence_data.cpp" +#include "..\..\Source\Services\Presence\presence_device_record.cpp" +#include "..\..\Source\Services\Presence\presence_media_record.cpp" +#include "..\..\Source\Services\Presence\presence_record.cpp" +#include "..\..\Source\Services\Presence\presence_service.cpp" +#include "..\..\Source\Services\Presence\presence_service_impl.cpp" +#include "..\..\Source\Services\Presence\presence_title_record.cpp" +#include "..\..\Source\Services\Presence\presence_title_request.cpp" +#include "..\..\Source\Services\Presence\presence_user_batch_request.cpp" +#include "..\..\Source\Services\Presence\presence_writer.cpp" +#include "..\..\Source\Services\Presence\title_presence_change_event_args.cpp" +#include "..\..\Source\Services\Presence\title_presence_change_subscription.cpp" +#include "..\..\Source\Services\Privacy\multiple_permissions_check_result.cpp" +#include "..\..\Source\Services\Privacy\permission_check_result.cpp" +#include "..\..\Source\Services\Privacy\permission_deny_reason.cpp" +#include "..\..\Source\Services\Privacy\privacy_service.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_service.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_service_factory.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_subscription.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_subscription_error_event_args.cpp" +#include "..\..\Source\Services\Social\profile_service.cpp" +#include "..\..\Source\Services\Social\reputation_feedback_request.cpp" +#include "..\..\Source\Services\Social\reputation_service.cpp" +#include "..\..\Source\Services\Social\social_relationship_change_event_args.cpp" +#include "..\..\Source\Services\Social\social_relationship_change_subscription.cpp" +#include "..\..\Source\Services\Social\social_service.cpp" +#include "..\..\Source\Services\Social\social_service_impl.cpp" +#include "..\..\Source\Services\Social\xbox_social_relationship.cpp" +#include "..\..\Source\Services\Social\xbox_social_relationship_result.cpp" +#include "..\..\Source\Services\Social\xbox_user_profile.cpp" +#include "..\..\Source\Services\Social\Manager\peoplehub_service.cpp" +#include "..\..\Source\Services\Social\Manager\preferred_color.cpp" +#include "..\..\Source\Services\Social\Manager\social_event.cpp" +#include "..\..\Source\Services\Social\Manager\social_graph.cpp" +#include "..\..\Source\Services\Social\Manager\social_manager.cpp" +#include "..\..\Source\Services\Social\Manager\social_user_group_loaded_event_args.cpp" +#include "..\..\Source\Services\Social\Manager\title_history.cpp" +#include "..\..\Source\Services\Social\Manager\xbox_social_user.cpp" +#include "..\..\Source\Services\Social\Manager\xbox_social_user_group.cpp" +#include "..\..\Source\Services\Stats\requested_statistics.cpp" +#include "..\..\Source\Services\Stats\service_configuration_statistic.cpp" +#include "..\..\Source\Services\Stats\statistic.cpp" +#include "..\..\Source\Services\Stats\statistic_change_event_args.cpp" +#include "..\..\Source\Services\Stats\statistic_change_subscription.cpp" +#include "..\..\Source\Services\Stats\user_statistics_result.cpp" +#include "..\..\Source\Services\Stats\user_statistics_service.cpp" +#include "..\..\Source\Services\Stats\user_statistics_service_impl.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_metadata.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_metadata_result.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_result.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_quota.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_service.cpp" +#include "..\..\Source\Services\Tournaments\tournament.cpp" +#include "..\..\Source\Services\Tournaments\tournaments_result.cpp" +#include "..\..\Source\Services\Tournaments\tournament_game.cpp" +#include "..\..\Source\Services\Tournaments\tournament_reference.cpp" +#include "..\..\Source\Services\Tournaments\tournament_service.cpp" +#include "..\..\Source\Services\Tournaments\tournament_stage.cpp" +#include "..\..\Source\Services\Tournaments\tournament_team.cpp" +#include "..\..\Source\Services\Tournaments\tournament_teams.cpp" +#include "..\..\Source\Services\Tournaments\tournament_team_result.cpp" +#include "..\..\Source\Shared\errors.cpp" +#include "..\..\Source\Shared\http_call_impl.cpp" +#include "..\..\Source\Shared\http_call_request_message.cpp" +#include "..\..\Source\Shared\http_call_response.cpp" +#include "..\..\Source\Shared\http_client.cpp" +#include "..\..\Source\Shared\initiator.cpp" +#include "..\..\Source\Shared\local_config.cpp" +#include "..\..\Source\Shared\service_call_logger.cpp" +#include "..\..\Source\Shared\service_call_logger_data.cpp" +#include "..\..\Source\Shared\service_call_logger_protocol.cpp" +#include "..\..\Source\Shared\service_call_logging_config.cpp" +#include "..\..\Source\Shared\telemetry.cpp" +#include "..\..\Source\Shared\user_context.cpp" +#include "..\..\Source\Shared\utils.cpp" +#include "..\..\Source\Shared\utils_locales.cpp" +#include "..\..\Source\Shared\web_socket_client.cpp" +#include "..\..\Source\Shared\web_socket_connection.cpp" +#include "..\..\Source\Shared\xbox_live_app_config.cpp" +#include "..\..\Source\Shared\xbox_live_context_settings.cpp" +#include "..\..\Source\Shared\xbox_service_call_routed_event_args.cpp" +#include "..\..\Source\Shared\xbox_system_factory.cpp" +#include "..\..\Source\Shared\Logger\console_output.cpp" +#include "..\..\Source\Shared\Logger\debug_output.cpp" +#include "..\..\Source\Shared\Logger\log.cpp" +#include "..\..\Source\Shared\Logger\log_entry.cpp" +#include "..\..\Source\Shared\Logger\log_output.cpp" +#include "..\..\Source\Shared\WinRT\Event_WinRT.cpp" +#include "..\..\Source\Shared\WinRT\local_config_winrt.cpp" +#include "..\..\Source\System\auth_config.cpp" +#include "..\..\Source\System\token_and_signature_result.cpp" +#include "..\..\Source\System\user.cpp" +#include "..\..\Source\System\user_impl.cpp" +#include "..\..\Source\System\user_impl_idp.cpp" +#include "..\..\Source\System\xbox_live_mutex.cpp" diff --git a/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.sln b/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.sln new file mode 100644 index 00000000..032d6e0b --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.sln @@ -0,0 +1,59 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.22823.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services", "Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj", "{D496A895-8C6B-46DC-A256-B623611D8FAA}" + ProjectSection(ProjectDependencies) = postProject + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5} = {8EE38792-FFD4-4897-BB32-308A4DDCF0C5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp", "..\..\External\cpprestsdk\Release\src\build\vs14.uwp\cpprestsdk140.uwp.vcxproj", "{8EE38792-FFD4-4897-BB32-308A4DDCF0C5}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\External\cpprestsdk\Release\src\build\winrt.vcxitems*{8ee38792-ffd4-4897-bb32-308a4ddcf0c5}*SharedItemsImports = 4 + ..\..\External\cpprestsdk\Release\src\build\common.vcxitems*{8ee38792-ffd4-4897-bb32-308a4ddcf0c5}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Debug|ARM.ActiveCfg = Debug|ARM + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Debug|ARM.Build.0 = Debug|ARM + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Debug|x64.ActiveCfg = Debug|x64 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Debug|x64.Build.0 = Debug|x64 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Debug|x86.ActiveCfg = Debug|Win32 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Debug|x86.Build.0 = Debug|Win32 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Release|ARM.ActiveCfg = Release|ARM + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Release|ARM.Build.0 = Release|ARM + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Release|x64.ActiveCfg = Release|x64 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Release|x64.Build.0 = Release|x64 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Release|x86.ActiveCfg = Release|Win32 + {D496A895-8C6B-46DC-A256-B623611D8FAA}.Release|x86.Build.0 = Release|Win32 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|ARM.ActiveCfg = Debug|ARM + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|ARM.Build.0 = Debug|ARM + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|x64.ActiveCfg = Debug|x64 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|x64.Build.0 = Debug|x64 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|x64.Deploy.0 = Debug|x64 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|x86.ActiveCfg = Debug|Win32 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|x86.Build.0 = Debug|Win32 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Debug|x86.Deploy.0 = Debug|Win32 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|ARM.ActiveCfg = Release|ARM + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|ARM.Build.0 = Release|ARM + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|x64.ActiveCfg = Release|x64 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|x64.Build.0 = Release|x64 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|x64.Deploy.0 = Release|x64 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|x86.ActiveCfg = Release|Win32 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|x86.Build.0 = Release|Win32 + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj b/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj new file mode 100644 index 00000000..61c58995 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj @@ -0,0 +1,779 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + title + {D496A895-8C6B-46DC-A256-B623611D8FAA} + Win32Proj + Microsoft.Xbox.Services + Microsoft.Xbox.Services + en-US + 14.0 + true + true + DynamicLibrary + v140 + Windows Store + 10.0 + false + Unicode + 10.0.14393.0 + 10.0.10240.0 + + + + true + + + false + true + + + + + + + + Use + _WINRT_DLL;_NO_XSAPIIMP;ENABLE_INTSAFE_SIGNED_FUNCTIONS;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /Zm250 %(AdditionalOptions) + Level4 + true + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\WinRT; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Social\WinRT; + $(ProjectDir)\..\..\Source\Services\Achievements; + $(ProjectDir)\..\..\Source\Services\Achievements\WinRT; + $(ProjectDir)\..\..\Source\Services\Tournaments; + $(ProjectDir)\..\..\Source\Services\Tournaments\WinRT; + $(ProjectDir)\..\..\Source\Services\Leaderboard; + $(ProjectDir)\..\..\Source\Services\Leaderboard\WinRT; + $(ProjectDir)\..\..\Source\Services\Stats; + $(ProjectDir)\..\..\Source\Services\Stats\WinRT; + $(ProjectDir)\..\..\Source\Services\Misc; + $(ProjectDir)\..\..\Source\Services\Misc\WinRT; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Multiplayer\WinRT; + $(ProjectDir)\..\..\Source\Services\Matchmaking; + $(ProjectDir)\..\..\Source\Services\Matchmaking\WinRT; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity\WinRT; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform\WinRT; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\Shared\WinRT; + $(ProjectDir)\..\..\Include; + $(ProjectDir)\..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\System\WinRT; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\Presence\WinRT; + $(ProjectDir)\..\..\Source\Services\TitleStorage; + $(ProjectDir)\..\..\Source\Services\TitleStorage\WinRT; + $(ProjectDir)\..\..\Source\Services\Privacy; + $(ProjectDir)\..\..\Source\Services\Privacy\WinRT; + $(ProjectDir)\..\..\Source\Services\Events; + $(ProjectDir)\..\..\Source\Services\Events\WinRT; + %(AdditionalIncludeDirectories) + false + + + windowsapp.lib;msxml6.lib;%(AdditionalDependencies) + Console + false + + + + + _WINRT_DLL;_DEBUG;%(PreprocessorDefinitions) + + + Debug + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {8EE38792-FFD4-4897-BB32-308A4DDCF0C5} + + + + $(MSBuildProjectName) + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectFolder)\ + $(ProjectDir)..\..\Obj\$(Configuration)\$(Platform)\$(ProjectFolder)\ + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj.filters b/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj.filters new file mode 100644 index 00000000..60cf1ac6 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.UWP.WinRT/Microsoft.Xbox.Services.140.UWP.WinRT.vcxproj.filters @@ -0,0 +1,2063 @@ + + + + + {6608be30-e73a-44dc-89f4-bbae78aa0877} + + + {67d5c9b8-1ece-48da-8048-8f7a7b3456ea} + + + {f6f5f2e6-4803-46ad-a9c3-c78735a5310f} + + + {26eadad8-3d0b-475c-84e4-6dc126cb5fff} + + + {6a65ddda-fa44-472f-9330-8a61a35822e4} + + + {01dc44ad-31df-470b-8281-ca0a1020564f} + + + {3b9fd829-77aa-4466-a0e4-0c7326b9117a} + + + {a4ff7207-f1ef-4c73-b98c-8e12901b2bd7} + + + {104d8f4f-6a5d-410c-a9ca-f35ad13a6947} + + + {1c135ef4-998b-4085-8511-0e0df5c9276d} + + + {edd1d7ab-f093-474a-9dad-5ca99752ff83} + + + {7f530c4d-dae5-43e8-a01b-8cc3f35ca5de} + + + {9e2ecd8b-a225-4608-ad19-04d9f208879d} + + + {fb328832-470d-4d8d-b92e-8a23b064b605} + + + {d7992e81-b6dd-4019-b6ad-0120179a764e} + + + {f48525ca-a3b9-48be-90b1-898fa663a3b1} + + + {445f8c8a-0143-4214-bf51-8542f9752990} + + + {db5e1db4-d646-4571-bd4e-e3d649862801} + + + {6d5ac48d-71c7-4fd0-a2c4-e274aea87ef9} + + + {2cd0260c-1aa0-48a1-8ea2-0bea92c5fef0} + + + {77e546bb-4a2e-4a7f-99b2-7db30b31b54f} + + + {2e2ec17f-e891-42f6-b336-535a40250e9f} + + + {2537d770-c646-4fb7-822a-3a01480b37b0} + + + {2da35adf-bd5f-4879-a2cb-c3fec75379dc} + + + {23feaf85-09ae-4ec0-ab50-213e820a2977} + + + {5c87eff6-df34-46d1-b063-7d1738abdcdf} + + + {e8cc579c-5827-4272-a2b9-d3084c04402f} + + + {3676454a-5890-4133-accb-70d005c29600} + + + {a10dda2a-8d3d-4d37-aa6c-b8200939bb72} + + + {7e36c273-adcf-4c93-a0fe-47c1eb0ac288} + + + {5690ce39-9554-4652-9ba0-f0ac4765ff13} + + + {6509ec03-d5ec-419f-803c-c5cd7e2c9135} + + + {e787eb28-a6d4-4b09-a3ea-f3e05aba564e} + + + {4d2eb7c6-1fb6-4a9d-a7a7-b955c0e3e647} + + + {79801b79-464b-4dc6-876b-395068ae96ab} + + + {b701563d-2967-443e-8fce-c8f4fa4e8b8d} + + + {4cc98a65-fd9f-4615-a343-c9a8f36edceb} + + + {fc6f4412-c76b-4654-9163-835528b6d904} + + + {8f16d081-b006-4c1b-9e87-05bd46dccf55} + + + {d9eb68c9-cd91-4b0b-b81a-315c20273827} + + + {aa613892-4cf7-42b6-80ac-7d625677500e} + + + {83b082eb-a286-42d6-bb71-43dd01a81745} + + + {436eee84-8885-4804-8eb8-5f005c7d83f8} + + + {7b3bd908-cbe9-4e01-b13b-b002b3148bb7} + + + {d037f7b1-d574-4d1c-b2d1-7f9da4797f7c} + + + {0cf444ab-723f-4e1f-bff0-09144910eae5} + + + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Common\WinRT + + + C++ Source\Common + + + C++ Source\Shared\WinRT Source + + + C++ Source\System\WinRT Source + + + C++ Source\System\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\Social\WinRT Source + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared + + + C++ Source\Shared\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Shared + + + C++ Source\RTA + + + C++ Source\RTA\WinRT + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\Multiplayer + + + C++ Source\RTA + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Shared + + + C++ Source\Presence + + + C++ Source\UserStats\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\Multiplayer + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\Shared + + + C++ Source\Shared\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Shared + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Shared + + + C++ Source\Presence + + + C++ Source\Presence\WinRT + + + C++ Source\GameServerPlatform + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Shared + + + C++ Source\Events + + + C++ Source\Events\WinRT + + + C++ Source\System + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Misc\WinRT + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared + + + C++ Source\RTA\WinRT + + + C++ Source\RTA + + + C++ Source\Misc + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Common\Desktop + + + C++ Source\Presence + + + C++ Source\UserStats + + + C++ Source\System + + + C++ Source\Common + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Misc\WinRT + + + C++ Source\System + + + C++ Source\Multiplayer\Manager + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Common\Desktop + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared + + + C++ Source\Shared\WinRT Source + + + C++ Source\RTA\WinRT + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments + + + C++ Source\Tournaments\WinRT + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Misc + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Source\RTA + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Shared + + + C++ Source\Shared\Logger + + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared\WinRT Source + + + + + C++ Source\Shared\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Common\WinRT + + + C++ Source\Common + + + C++ Source\Shared\WinRT Source + + + C++ Source\System\WinRT Source + + + C++ Source\System\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\System + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Public Includes + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Public Includes + + + C++ Source\Shared\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Public Includes + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\RTA\WinRT + + + C++ Public Includes + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\UserStats\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\RTA\WinRT + + + C++ Source\RTA\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Public Includes + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Public Includes + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Privacy\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Public Includes + + + C++ Source\Presence\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Misc\WinRT + + + C++ Public Includes + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Events\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Source\Shared\WinRT Source + + + C++ Public Includes + + + C++ Source\RTA\WinRT + + + C++ Source\RTA\WinRT + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\System\WinRT Source + + + C++ Source\System\WinRT Source + + + C++ Source\Misc + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer + + + C++ Source\Presence + + + C++ Source\RTA + + + C++ Source\UserStats + + + C++ Source\Common + + + C++ Source\Misc\WinRT + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared\WinRT Source + + + C++ Public Includes + + + C++ Source\Shared\WinRT Source + + + C++ Source\RTA\WinRT + + + C++ Source\Misc + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Public Includes + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\System + + + C++ Source\System + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Public Includes + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\System + + + C++ Source\Common + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Shared\Logger + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared\Logger + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Shared + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Shared\Logger + + + C++ Public Includes + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + + C++ Source\Shared\WinRT Source + + + C++ Source\Shared\WinRT Source + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Build.Durango.Cpp.props b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Build.Durango.Cpp.props new file mode 100644 index 00000000..343d88d9 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Build.Durango.Cpp.props @@ -0,0 +1,29 @@ + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + + + + + ixmlhttprequest2.lib;combase.lib;kernelx.lib;uuid.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + + + + msxml6.lib;runtimeobject.lib;mincore.lib;mincore_legacy.lib;mincore_obsolete.lib;user32.lib;uuid.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.sln b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.sln new file mode 100644 index 00000000..c47eb5c7 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.140.XDK.Cpp", "Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj", "{8A112040-CDA1-4490-B518-62DFCC451FA7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "casablanca140.xbox", "..\..\External\cpprestsdk\Release\src\build\vs14.xbox\casablanca140.Xbox.vcxproj", "{E621C269-D177-4C1B-80EA-C0A274B7A151}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8A112040-CDA1-4490-B518-62DFCC451FA7}.Debug|Durango.ActiveCfg = Debug|Durango + {8A112040-CDA1-4490-B518-62DFCC451FA7}.Debug|Durango.Build.0 = Debug|Durango + {8A112040-CDA1-4490-B518-62DFCC451FA7}.Release|Durango.ActiveCfg = Release|Durango + {8A112040-CDA1-4490-B518-62DFCC451FA7}.Release|Durango.Build.0 = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.ActiveCfg = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.Build.0 = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.ActiveCfg = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj new file mode 100644 index 00000000..fa12d0e0 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj @@ -0,0 +1,398 @@ + + + + + Debug + Durango + + + Release + Durango + + + + + title + {8A112040-CDA1-4490-B518-62DFCC451FA7} + Win32Proj + Microsoft.Xbox.Services.140.XDK.Cpp + Microsoft.Xbox.Services + en-US + 11.0 + true + true + StaticLibrary + false + false + + + v140 + + + + true + Unicode + + + Unicode + false + false + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {e621c269-d177-4c1b-80ea-c0a274b7a151} + + + + + + + + + + $(MSBuildProjectName) + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectFolder)\ + $(ProjectDir)..\..\Obj\$(Configuration)\$(Platform)\$(ProjectFolder)\ + + + + Use + _NO_ASYNCRTIMP;_NO_PPLXIMP;_NO_XSAPIIMP;%(PreprocessorDefinitions) + _XSAPIIMP_EXPORT;%(PreprocessorDefinitions) + _VARIADIC_MAX=10;ENABLE_INTSAFE_SIGNED_FUNCTIONS;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /Zm250 %(AdditionalOptions) + $(OutDir)$(ProjectName).pdb + Level4 + false + true + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Desktop; + $(ProjectDir)\..\..\Source\Services\Common\Durango; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Achievements; + $(ProjectDir)\..\..\Source\Services\Leaderboard; + $(ProjectDir)\..\..\Source\Services\Stats; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Matchmaking; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\; + $(ProjectDir)\..\..\Include; + $(ProjectDir)\..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\TitleStorage; + %(AdditionalIncludeDirectories) + + + Console + + + /ignore:4264 %(AdditionalOptions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + + + /ignore:4264 %(AdditionalOptions) + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj.filters b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj.filters new file mode 100644 index 00000000..9b6f4752 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Cpp.vcxproj.filters @@ -0,0 +1,919 @@ + + + + + {6608be30-e73a-44dc-89f4-bbae78aa0877} + + + {67d5c9b8-1ece-48da-8048-8f7a7b3456ea} + + + {a10dda2a-8d3d-4d37-aa6c-b8200939bb72} + + + {f6f5f2e6-4803-46ad-a9c3-c78735a5310f} + + + {6a65ddda-fa44-472f-9330-8a61a35822e4} + + + {104d8f4f-6a5d-410c-a9ca-f35ad13a6947} + + + {1c135ef4-998b-4085-8511-0e0df5c9276d} + + + {9e2ecd8b-a225-4608-ad19-04d9f208879d} + + + {d7992e81-b6dd-4019-b6ad-0120179a764e} + + + {445f8c8a-0143-4214-bf51-8542f9752990} + + + {6d5ac48d-71c7-4fd0-a2c4-e274aea87ef9} + + + {2cd0260c-1aa0-48a1-8ea2-0bea92c5fef0} + + + {2537d770-c646-4fb7-822a-3a01480b37b0} + + + {e787eb28-a6d4-4b09-a3ea-f3e05aba564e} + + + {824cab2e-845a-4410-b308-41acda6f2b22} + + + {ab536799-29a7-42e5-acaa-94ac987ae6cf} + + + {e7814213-f187-402d-8163-17af50c41b89} + + + {369eecf7-03a0-44f0-af01-10ac8e3a3bcf} + + + {3f42a4b7-3191-4589-b2fa-2763820d762a} + + + {a3b66114-c964-40b0-af39-21a6d09992eb} + + + {eefe0d87-3c09-46f8-9c87-112f5de6f2a2} + + + {4c480269-72ca-4198-ac95-b375458e053c} + + + {73644e7c-c648-4d11-9012-c96a4a1b2a52} + + + {913eb5c7-cb7d-4812-9873-7a438283f9bf} + + + {09008b38-238f-4b13-a705-034cdd061884} + + + {dca6a2fb-0dbb-431e-9f45-fcf1257f20b2} + + + + + Shared + + + Shared + + + Shared + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Social + + + C++ Source\Social + + + Shared + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\RTA + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Multiplayer + + + C++ Source\RTA + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Common\Desktop + + + C++ Source\Common\Desktop + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + Shared + + + C++ Source\Multiplayer + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + Shared + + + C++ Source\GameServerPlatform + + + Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + Shared + + + C++ Source\RTA + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Common + + + C++ Source\Presence + + + C++ Source\UserStats + + + System + + + C++ Source\Social + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Tournaments + + + C++ Source\Social\Manager + + + Shared\Logger + + + Shared\logger + + + Shared\Logger + + + Shared\Logger + + + Shared\Logger + + + Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\RTA + + + Shared + + + Shared\Logger + + + C++ Source\Social\Manager + + + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Common\Desktop + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Presence + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\UserStats + + + C++ Source\Social + + + C++ Source\Common + + + Shared + + + Shared + + + C++ Public Includes + + + Shared + + + C++ Source\Multiplayer\Manager + + + C++ Source\Social\Manager + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Misc + + + Shared + + + C++ Public Includes + + + C++ Public Includes + + + System + + + System + + + Shared\Logger + + + Shared\Logger + + + Shared + + + C++ Public Includes + + + Shared\Logger + + + Shared\Debug + + + Shared\Logger + + + Shared\Logger + + + + + Shared\Logger + + + + + Shared\Logger + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj new file mode 100644 index 00000000..d0baf0da --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Durango + + + Release + Durango + + + + + title + {20E87245-DA60-40E5-9938-ABB445E78467} + Win32Proj + Microsoft.Xbox.Services.140.XDK.Ship.Cpp + Microsoft.Xbox.Services + en-US + 11.0 + true + true + StaticLibrary + v140 + false + false + + + + true + Unicode + + + Unicode + false + false + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {e621c269-d177-4c1b-80ea-c0a274b7a151} + + + + + Use + _NO_ASYNCRTIMP;_NO_PPLXIMP;_NO_XSAPIIMP;%(PreprocessorDefinitions) + _XSAPIIMP_EXPORT;%(PreprocessorDefinitions) + _VARIADIC_MAX=10;ENABLE_INTSAFE_SIGNED_FUNCTIONS;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /Zm250 %(AdditionalOptions) + $(OutDir)$(ProjectName).pdb + Level4 + false + true + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Desktop; + $(ProjectDir)\..\..\Source\Services\Common\Durango; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Achievements; + $(ProjectDir)\..\..\Source\Services\Leaderboard; + $(ProjectDir)\..\..\Source\Services\Stats; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Matchmaking; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\; + $(ProjectDir)\..\..\Include; + $(ProjectDir)\..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\TitleStorage; + %(AdditionalIncludeDirectories) + + + Console + + + /ignore:4264 %(AdditionalOptions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + + + /ignore:4264 %(AdditionalOptions) + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj.filters b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj.filters new file mode 100644 index 00000000..0f4e709f --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/Microsoft.Xbox.Services.140.XDK.Ship.Cpp.vcxproj.filters @@ -0,0 +1,233 @@ + + + + + {6608be30-e73a-44dc-89f4-bbae78aa0877} + + + {67d5c9b8-1ece-48da-8048-8f7a7b3456ea} + + + {a10dda2a-8d3d-4d37-aa6c-b8200939bb72} + + + {f6f5f2e6-4803-46ad-a9c3-c78735a5310f} + + + {6a65ddda-fa44-472f-9330-8a61a35822e4} + + + {104d8f4f-6a5d-410c-a9ca-f35ad13a6947} + + + {1c135ef4-998b-4085-8511-0e0df5c9276d} + + + {9e2ecd8b-a225-4608-ad19-04d9f208879d} + + + {d7992e81-b6dd-4019-b6ad-0120179a764e} + + + {445f8c8a-0143-4214-bf51-8542f9752990} + + + {6d5ac48d-71c7-4fd0-a2c4-e274aea87ef9} + + + {2cd0260c-1aa0-48a1-8ea2-0bea92c5fef0} + + + {2537d770-c646-4fb7-822a-3a01480b37b0} + + + {e787eb28-a6d4-4b09-a3ea-f3e05aba564e} + + + {824cab2e-845a-4410-b308-41acda6f2b22} + + + {ab536799-29a7-42e5-acaa-94ac987ae6cf} + + + {e7814213-f187-402d-8163-17af50c41b89} + + + {369eecf7-03a0-44f0-af01-10ac8e3a3bcf} + + + {3f42a4b7-3191-4589-b2fa-2763820d762a} + + + {e2fa6a55-15a6-4f89-a716-7fc00fd95c2c} + + + {a3b66114-c964-40b0-af39-21a6d09992eb} + + + {eefe0d87-3c09-46f8-9c87-112f5de6f2a2} + + + + + + C++ Source\Common\Desktop + + + + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + Shared\Desktop + + + C++ Source\Common\Desktop + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Common\Durango + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Multiplayer\Manager + + + System + + + C++ Source\Presence + + + C++ Source\Multiplayer + + + C++ Source\UserStats + + + C++ Source\Social + + + C++ Source\Common + + + Shared + + + C++ Public Includes + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.XDK.Cpp/build.cpp b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/build.cpp new file mode 100644 index 00000000..2c58e0d3 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.Cpp/build.cpp @@ -0,0 +1,197 @@ +#include "pch.h" + +#include "..\..\Source\Services\Achievements\achievement.cpp" +#include "..\..\Source\Services\Achievements\achievements_result.cpp" +#include "..\..\Source\Services\Achievements\achievement_media_asset.cpp" +#include "..\..\Source\Services\Achievements\achievement_progression.cpp" +#include "..\..\Source\Services\Achievements\achievement_requirement.cpp" +#include "..\..\Source\Services\Achievements\achievement_reward.cpp" +#include "..\..\Source\Services\Achievements\achievement_service.cpp" +#include "..\..\Source\Services\Achievements\achievement_time_window.cpp" +#include "..\..\Source\Services\Achievements\achievement_title_association.cpp" +#include "..\..\Source\Services\Common\xbox_live_context_impl.cpp" +#include "..\..\Source\Services\Common\Desktop\XboxLiveContext_Desktop.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile_list_contains_item_result.cpp" +#include "..\..\Source\Services\EntertainmentProfile\entertainment_profile_list_xbox_one_pins.cpp" +#include "..\..\Source\Services\GameServerPlatform\allocation_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\cluster_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_image_set.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_metadata_result.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_platform_service.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_port_mapping.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_server_ticket_status.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_variant.cpp" +#include "..\..\Source\Services\GameServerPlatform\game_variant_schema.cpp" +#include "..\..\Source\Services\GameServerPlatform\quality_of_service_server.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_column.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_result.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_row.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_serializers.cpp" +#include "..\..\Source\Services\Leaderboard\leaderboard_service.cpp" +#include "..\..\Source\Services\Marketplace\browse_catalog_result.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item_availability.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item_details.cpp" +#include "..\..\Source\Services\Marketplace\catalog_item_image.cpp" +#include "..\..\Source\Services\Marketplace\catalog_service.cpp" +#include "..\..\Source\Services\Marketplace\catalog_total.cpp" +#include "..\..\Source\Services\Marketplace\consume_inventory_item_request.cpp" +#include "..\..\Source\Services\Marketplace\consume_inventory_item_result.cpp" +#include "..\..\Source\Services\Marketplace\inventory_item.cpp" +#include "..\..\Source\Services\Marketplace\inventory_items_result.cpp" +#include "..\..\Source\Services\Marketplace\inventory_service.cpp" +#include "..\..\Source\Services\Matchmaking\create_match_ticket_response.cpp" +#include "..\..\Source\Services\Matchmaking\hopper_statistics_response.cpp" +#include "..\..\Source\Services\Matchmaking\matchmaking_service.cpp" +#include "..\..\Source\Services\Matchmaking\match_ticket_details_response.cpp" +#include "..\..\Source\Services\Misc\contextual_config_result.cpp" +#include "..\..\Source\Services\Misc\contextual_search_broadcast.cpp" +#include "..\..\Source\Services\Misc\contextual_search_configured_stat.cpp" +#include "..\..\Source\Services\Misc\contextual_search_service.cpp" +#include "..\..\Source\Services\Misc\string_service.cpp" +#include "..\..\Source\Services\Misc\verify_string_result.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_details.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_activity_query_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_get_sessions_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_invite.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_invite_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_managed_initialization.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_peer_to_host_requirements.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_peer_to_peer_requirements.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_quality_of_service_measurement.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_service.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_service_impl.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_arbitration_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_capabilities.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_change_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_constants.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_matchmaking_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_member.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_member_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_properties.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_reference.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_request.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_states.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_session_tournaments_server.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_subscription.cpp" +#include "..\..\Source\Services\Multiplayer\multiplayer_transfer_handle_post_request.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\find_match_completed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\host_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\join_lobby_completed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\matchmaking_client_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_joined_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_left_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\member_property_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_pending_reader.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_client_pending_request.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_event.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_game_client.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_game_session.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_lobby_client.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_lobby_session.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_local_user.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_local_user_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_manager.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_manager_utils.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_member.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\multiplayer_session_writer.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\perform_qos_measurements_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\session_property_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\tournament_game_session_ready_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\tournament_registration_state_changed_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\user_added_event_args.cpp" +#include "..\..\Source\Services\Multiplayer\Manager\user_removed_event_args.cpp" +#include "..\..\Source\Services\Presence\device_presence_change_event_args.cpp" +#include "..\..\Source\Services\Presence\device_presence_change_subscription.cpp" +#include "..\..\Source\Services\Presence\media_presence_data.cpp" +#include "..\..\Source\Services\Presence\presence_activity_data.cpp" +#include "..\..\Source\Services\Presence\presence_broadcast_record.cpp" +#include "..\..\Source\Services\Presence\presence_data.cpp" +#include "..\..\Source\Services\Presence\presence_device_record.cpp" +#include "..\..\Source\Services\Presence\presence_media_record.cpp" +#include "..\..\Source\Services\Presence\presence_record.cpp" +#include "..\..\Source\Services\Presence\presence_service.cpp" +#include "..\..\Source\Services\Presence\presence_service_impl.cpp" +#include "..\..\Source\Services\Presence\presence_title_record.cpp" +#include "..\..\Source\Services\Presence\presence_title_request.cpp" +#include "..\..\Source\Services\Presence\presence_user_batch_request.cpp" +#include "..\..\Source\Services\Presence\title_presence_change_event_args.cpp" +#include "..\..\Source\Services\Presence\title_presence_change_subscription.cpp" +#include "..\..\Source\Services\Privacy\multiple_permissions_check_result.cpp" +#include "..\..\Source\Services\Privacy\permission_check_result.cpp" +#include "..\..\Source\Services\Privacy\permission_deny_reason.cpp" +#include "..\..\Source\Services\Privacy\privacy_service.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_service.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_subscription.cpp" +#include "..\..\Source\Services\RealTimeActivity\real_time_activity_subscription_error_event_args.cpp" +#include "..\..\Source\Services\Social\profile_service.cpp" +#include "..\..\Source\Services\Social\reputation_feedback_request.cpp" +#include "..\..\Source\Services\Social\reputation_service.cpp" +#include "..\..\Source\Services\Social\social_relationship_change_event_args.cpp" +#include "..\..\Source\Services\Social\social_relationship_change_subscription.cpp" +#include "..\..\Source\Services\Social\social_service.cpp" +#include "..\..\Source\Services\Social\social_service_impl.cpp" +#include "..\..\Source\Services\Social\xbox_social_relationship.cpp" +#include "..\..\Source\Services\Social\xbox_social_relationship_result.cpp" +#include "..\..\Source\Services\Social\xbox_user_profile.cpp" +#include "..\..\Source\Services\Social\Manager\peoplehub_service.cpp" +#include "..\..\Source\Services\Social\Manager\preferred_color.cpp" +#include "..\..\Source\Services\Social\Manager\social_event.cpp" +#include "..\..\Source\Services\Social\Manager\social_graph.cpp" +#include "..\..\Source\Services\Social\Manager\social_manager.cpp" +#include "..\..\Source\Services\Social\Manager\title_history.cpp" +#include "..\..\Source\Services\Social\Manager\xbox_social_user.cpp" +#include "..\..\Source\Services\Social\Manager\xbox_social_user_group.cpp" +#include "..\..\Source\Services\Stats\requested_statistics.cpp" +#include "..\..\Source\Services\Stats\service_configuration_statistic.cpp" +#include "..\..\Source\Services\Stats\statistic.cpp" +#include "..\..\Source\Services\Stats\statistic_change_event_args.cpp" +#include "..\..\Source\Services\Stats\statistic_change_subscription.cpp" +#include "..\..\Source\Services\Stats\user_statistics_result.cpp" +#include "..\..\Source\Services\Stats\user_statistics_service.cpp" +#include "..\..\Source\Services\Stats\user_statistics_service_impl.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_metadata.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_metadata_result.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_blob_result.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_quota.cpp" +#include "..\..\Source\Services\TitleStorage\title_storage_service.cpp" +#include "..\..\Source\Services\Tournaments\tournament.cpp" +#include "..\..\Source\Services\Tournaments\tournaments_result.cpp" +#include "..\..\Source\Services\Tournaments\tournament_game.cpp" +#include "..\..\Source\Services\Tournaments\tournament_reference.cpp" +#include "..\..\Source\Services\Tournaments\tournament_service.cpp" +#include "..\..\Source\Services\Tournaments\tournament_stage.cpp" +#include "..\..\Source\Services\Tournaments\tournament_team.cpp" +#include "..\..\Source\Services\Tournaments\tournament_teams.cpp" +#include "..\..\Source\Services\Tournaments\tournament_team_result.cpp" +#include "..\..\Source\Shared\errors.cpp" +#include "..\..\Source\Shared\http_call_impl.cpp" +#include "..\..\Source\Shared\http_call_request_message.cpp" +#include "..\..\Source\Shared\http_call_response.cpp" +#include "..\..\Source\Shared\http_client.cpp" +#include "..\..\Source\Shared\local_config.cpp" +#include "..\..\Source\Shared\service_call_logger.cpp" +#include "..\..\Source\Shared\service_call_logger_data.cpp" +#include "..\..\Source\Shared\service_call_logger_protocol.cpp" +#include "..\..\Source\Shared\service_call_logging_config.cpp" +#include "..\..\Source\Shared\telemetry.cpp" +#include "..\..\Source\Shared\user_context.cpp" +#include "..\..\Source\Shared\utils.cpp" +#include "..\..\Source\Shared\utils_locales.cpp" +#include "..\..\Source\Shared\web_socket_client.cpp" +#include "..\..\Source\Shared\web_socket_connection.cpp" +#include "..\..\Source\Shared\xbox_live_app_config.cpp" +#include "..\..\Source\Shared\xbox_live_context_settings.cpp" +#include "..\..\Source\Shared\xbox_service_call_routed_event_args.cpp" +#include "..\..\Source\Shared\xbox_system_factory.cpp" +#include "..\..\Source\Shared\Desktop\local_config_desktop.cpp" +#include "..\..\Source\System\xbox_live_mutex.cpp" +#include "..\..\Source\Shared\Logger\debug_output.cpp" +#include "..\..\Source\Shared\Logger\log.cpp" +#include "..\..\Source\Shared\Logger\log_entry.cpp" +#include "..\..\Source\Shared\Logger\log_output.cpp" +#include "..\..\Source\Shared\initiator.cpp" diff --git a/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Build.Durango.Cpp.props b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Build.Durango.Cpp.props new file mode 100644 index 00000000..18185d3f --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Build.Durango.Cpp.props @@ -0,0 +1,29 @@ + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + + + + + ixmlhttprequest2.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + + + + msxml6.lib;runtimeobject.lib;mincore.lib;mincore_legacy.lib;mincore_obsolete.lib;user32.lib;uuid.lib;etwplus.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + diff --git a/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.sln b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.sln new file mode 100644 index 00000000..04120d75 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.140.XDK.WinRT", "Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj", "{9BF96BF1-7E60-49B7-A137-E6C961A28336}" + ProjectSection(ProjectDependencies) = postProject + {E621C269-D177-4C1B-80EA-C0A274B7A151} = {E621C269-D177-4C1B-80EA-C0A274B7A151} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "casablanca140.xbox", "..\..\External\cpprestsdk\Release\src\build\vs14.xbox\casablanca140.Xbox.vcxproj", "{E621C269-D177-4C1B-80EA-C0A274B7A151}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9BF96BF1-7E60-49B7-A137-E6C961A28336}.Debug|Durango.ActiveCfg = Debug|Durango + {9BF96BF1-7E60-49B7-A137-E6C961A28336}.Debug|Durango.Build.0 = Debug|Durango + {9BF96BF1-7E60-49B7-A137-E6C961A28336}.Release|Durango.ActiveCfg = Release|Durango + {9BF96BF1-7E60-49B7-A137-E6C961A28336}.Release|Durango.Build.0 = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.ActiveCfg = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.Build.0 = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.ActiveCfg = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj new file mode 100644 index 00000000..f9df0f55 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj @@ -0,0 +1,782 @@ + + + + + Debug + Durango + + + Release + Durango + + + + + title + {9BF96BF1-7E60-49B7-A137-E6C961A28336} + Win32Proj + Microsoft.Xbox.Services.140.XDK.WinRT + Microsoft.Xbox.Services + en-US + 14.0 + true + true + DynamicLibrary + false + false + + + v140 + + + + true + Unicode + + + Unicode + false + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {e621c269-d177-4c1b-80ea-c0a274b7a151} + + + + + Use + _VARIADIC_MAX=10;ENABLE_INTSAFE_SIGNED_FUNCTIONS;_NO_XSAPIIMP;_NO_ASYNCRTIMP;_NO_PPLXIMP;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /Zm250 %(AdditionalOptions) + Level4 + true + false + true + + $(ProjectDir); + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\WinRT; + $(ProjectDir)\..\..\Source\Services\Tournaments; + $(ProjectDir)\..\..\Source\Services\Tournaments\WinRT; + $(ProjectDir)\..\..\Source\Services\Common\Durango; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Social\WinRT; + $(ProjectDir)\..\..\Source\Services\Achievements; + $(ProjectDir)\..\..\Source\Services\Achievements\WinRT; + $(ProjectDir)\..\..\Source\Services\EntertainmentProfile; + $(ProjectDir)\..\..\Source\Services\EntertainmentProfile\WinRT; + $(ProjectDir)\..\..\Source\Services\Leaderboard; + $(ProjectDir)\..\..\Source\Services\Leaderboard\WinRT; + $(ProjectDir)\..\..\Source\Services\Stats; + $(ProjectDir)\..\..\Source\Services\Stats\WinRT; + $(ProjectDir)\..\..\Source\Services\Misc; + $(ProjectDir)\..\..\Source\Services\Misc\WinRT; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Multiplayer\WinRT; + $(ProjectDir)\..\..\Source\Services\Matchmaking; + $(ProjectDir)\..\..\Source\Services\Matchmaking\WinRT; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity\WinRT; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform; + $(ProjectDir)\..\..\Source\Services\GameServerPlatform\WinRT; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\Shared\WinRT; + $(ProjectDir)\..\..\Source\; + $(ProjectDir)\..\..\Include; + $(ProjectDir)\..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\Presence\WinRT; + $(ProjectDir)\..\..\Source\Services\TitleStorage; + $(ProjectDir)\..\..\Source\Services\TitleStorage\WinRT; + $(ProjectDir)\..\..\Source\Services\Privacy; + $(ProjectDir)\..\..\Source\Services\Privacy\WinRT; + $(ProjectDir)\..\..\Source\Services\Marketplace; + $(ProjectDir)\..\..\Source\Services\Marketplace\WinRT; + $(ProjectDir)..\..\Source\Services\Events; + $(ProjectDir)..\..\Source\Services\Events\WinRT; + %(AdditionalIncludeDirectories) + + + Console + + + + + NDEBUG;%(PreprocessorDefinitions) + + + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + $(OutDir)$(TargetName).pdb + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj.filters b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj.filters new file mode 100644 index 00000000..d6d82bbe --- /dev/null +++ b/Build/Microsoft.Xbox.Services.140.XDK.WinRT/Microsoft.Xbox.Services.140.XDK.WinRT.vcxproj.filters @@ -0,0 +1,2106 @@ + + + + + {6608be30-e73a-44dc-89f4-bbae78aa0877} + + + {67d5c9b8-1ece-48da-8048-8f7a7b3456ea} + + + {a10dda2a-8d3d-4d37-aa6c-b8200939bb72} + + + {7e36c273-adcf-4c93-a0fe-47c1eb0ac288} + + + {f6f5f2e6-4803-46ad-a9c3-c78735a5310f} + + + {26eadad8-3d0b-475c-84e4-6dc126cb5fff} + + + {6a65ddda-fa44-472f-9330-8a61a35822e4} + + + {01dc44ad-31df-470b-8281-ca0a1020564f} + + + {104d8f4f-6a5d-410c-a9ca-f35ad13a6947} + + + {1c135ef4-998b-4085-8511-0e0df5c9276d} + + + {edd1d7ab-f093-474a-9dad-5ca99752ff83} + + + {7f530c4d-dae5-43e8-a01b-8cc3f35ca5de} + + + {9e2ecd8b-a225-4608-ad19-04d9f208879d} + + + {fb328832-470d-4d8d-b92e-8a23b064b605} + + + {d7992e81-b6dd-4019-b6ad-0120179a764e} + + + {f48525ca-a3b9-48be-90b1-898fa663a3b1} + + + {445f8c8a-0143-4214-bf51-8542f9752990} + + + {db5e1db4-d646-4571-bd4e-e3d649862801} + + + {6d5ac48d-71c7-4fd0-a2c4-e274aea87ef9} + + + {2cd0260c-1aa0-48a1-8ea2-0bea92c5fef0} + + + {77e546bb-4a2e-4a7f-99b2-7db30b31b54f} + + + {2e2ec17f-e891-42f6-b336-535a40250e9f} + + + {2537d770-c646-4fb7-822a-3a01480b37b0} + + + {2da35adf-bd5f-4879-a2cb-c3fec75379dc} + + + {e787eb28-a6d4-4b09-a3ea-f3e05aba564e} + + + {4d2eb7c6-1fb6-4a9d-a7a7-b955c0e3e647} + + + {715b321e-c849-43e4-86d6-4a4b6e5ada95} + + + {ffea2a8f-1e40-46a9-b163-f93271cbaecf} + + + {ad31e97a-877a-400d-9334-5511c91f3f87} + + + {81e67785-2ccf-41b1-85ee-62e9d1b3bf2d} + + + {16a2c57b-58a8-4719-b4e9-340b6895cc80} + + + {d95384ba-e87d-4720-b3e1-80ba72a551b3} + + + {26aa58f6-786c-490c-a504-857e5d4b434a} + + + {dd641cb0-5275-41e8-a61c-0cb79399eeb3} + + + {f962017b-f770-4297-96bc-1be7aee43b4e} + + + {bccae8c6-0f2b-4600-874e-9fee1332dfe8} + + + {c22cbb70-2b96-4ae7-9696-ffd4535320c4} + + + {3879b0ae-2cb3-43c7-b9cc-c86bddf0499c} + + + {4ef7f29d-fce3-43d2-9663-62b90aeca9b0} + + + {f2b6a020-9f66-4b3e-82da-d04078643d8d} + + + {44e52e9a-ab3d-4aa1-9845-883ede92d001} + + + {030ec34c-29e1-49f5-a708-3173eba35bbe} + + + {36ec36fe-4a3a-43bf-b992-048aa268c42b} + + + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Common\WinRT + + + C++ Source\Common + + + Shared\WinRT Source + + + Shared\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + Shared + + + Shared + + + Shared + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\Social\WinRT Source + + + C++ Source\Social + + + C++ Source\Social + + + Shared\WinRT Source + + + Shared + + + Shared\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\RTA + + + C++ Source\RTA + + + C++ Source\RTA\WinRT + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\Multiplayer + + + C++ Source\RTA + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\UserStats\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\Multiplayer + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage\WinRT Source + + + Shared + + + Shared\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + Shared + + + Shared + + + Shared + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + Shared + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + C++ Source\Marketplace + + + Shared + + + C++ Source\Presence\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Multiplayer\WinRT Source + + + Shared + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + Shared\WinRT Source + + + Shared + + + C++ Source\RTA + + + C++ Source\RTA\WinRT + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\RTA\WinRT + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Common\Desktop + + + C++ Source\Presence + + + System + + + C++ Source\UserStats + + + C++ Source\Common + + + C++ Source\Social + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Common\Desktop + + + Shared + + + Shared + + + Shared + + + Shared\WinRT Source + + + Shared + + + Shared + + + Shared\WinRT Source + + + C++ Source\RTA\WinRT + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + Shared + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + Shared + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile + + + C++ Source\EntertainmentProfile\WinRT + + + C++ Source\EntertainmentProfile\WinRT + + + C++ Source\EntertainmentProfile\WinRT + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Tournaments + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments + + + C++ Source\Tournaments\WinRT + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + Shared\logger + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + Shared + + + Shared + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + Shared\logger + + + Shared + + + Shared\WinRT Source + + + Shared\WinRT Source + + + + + Shared\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Common\WinRT + + + C++ Source\Common + + + Shared\WinRT Source + + + Shared\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Public Includes + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Achievements\WinRT + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Source\Leaderboard\WinRT + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Public Includes + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + Shared\WinRT Source + + + C++ Public Includes + + + Shared\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Public Includes + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Source\Matchmaking\WinRT Source + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Public Includes + + + C++ Source\RTA\WinRT + + + C++ Public Includes + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\UserStats\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\Presence\WinRT + + + C++ Source\RTA\WinRT + + + C++ Source\RTA\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Public Includes + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + Shared\WinRT Source + + + Shared\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Source\TitleStorage\WinRT Source + + + C++ Public Includes + + + Shared + + + Shared + + + Shared + + + Shared + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Source\Privacy\WinRT Source + + + C++ Public Includes + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Source\Marketplace\WinRT + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Presence\WinRT + + + C++ Source\GameServerPlatform\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Misc\WinRT + + + Shared + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + Shared\WinRT Source + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\RTA\WinRT + + + C++ Source\RTA\WinRT + + + C++ Source\Multiplayer\Manager + + + C++ Public Includes + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\RTA + + + C++ Source\Social + + + System + + + C++ Source\Common + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager + + + C++ Public Includes + + + Shared + + + C++ Public Includes + + + Shared + + + Shared\WinRT Source + + + Shared + + + C++ Source\RTA\WinRT + + + C++ Public Includes + + + Shared\WinRT Source + + + C++ Source\Misc + + + C++ Public Includes + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + Shared + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + Shared + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Multiplayer\Manager\WinRT Source + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\EntertainmentProfile\WinRT + + + C++ Source\EntertainmentProfile\WinRT + + + C++ Source\EntertainmentProfile\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Source\Social\WinRT Source + + + C++ Public Includes + + + System + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Tournaments\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + Shared\logger + + + Shared\logger + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + C++ Source\Misc\WinRT + + + Shared + + + C++ Source\Multiplayer\WinRT Source + + + C++ Source\Multiplayer\WinRT Source + + + C++ Public Includes + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + C++ Source\Social\Manager\WinRT + + + Shared\logger + + + Shared\logger + + + Shared\WinRT Source + + + Shared\WinRT Source + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.Android/.project b/Build/Microsoft.Xbox.Services.Android/.project new file mode 100644 index 00000000..1f63618e --- /dev/null +++ b/Build/Microsoft.Xbox.Services.Android/.project @@ -0,0 +1,17 @@ + + + Microsoft.Xbox.Services.Android + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/Build/Microsoft.Xbox.Services.Android/.settings/org.eclipse.jdt.core.prefs b/Build/Microsoft.Xbox.Services.Android/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..8768e699 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.Android/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.sln b/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.sln new file mode 100644 index 00000000..74a10598 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.Android", "Microsoft.Xbox.Services.Android.vcxproj", "{5FA18992-3E85-4090-B21E-6EF7FB613A44}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.android", "..\..\External\cpprestsdk\Release\src\build\vs14.android\casablanca140.android.vcxproj", "{AFB49019-965B-4C10-BAFF-C86C16D58010}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\External\cpprestsdk\Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + ..\..\External\cpprestsdk\Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Debug|ARM.ActiveCfg = Debug|ARM + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Debug|ARM.Build.0 = Debug|ARM + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Debug|x86.ActiveCfg = Debug|x86 + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Debug|x86.Build.0 = Debug|x86 + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Release|ARM.ActiveCfg = Release|ARM + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Release|ARM.Build.0 = Release|ARM + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Release|x86.ActiveCfg = Release|x86 + {5FA18992-3E85-4090-B21E-6EF7FB613A44}.Release|x86.Build.0 = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.ActiveCfg = Debug|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.Build.0 = Debug|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.ActiveCfg = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.Build.0 = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.ActiveCfg = Release|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.Build.0 = Release|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.ActiveCfg = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj b/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj new file mode 100644 index 00000000..8a77d40d --- /dev/null +++ b/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj @@ -0,0 +1,501 @@ + + + + + Debug + ARM + + + Debug + x86 + + + Release + ARM + + + Release + x86 + + + + {5fa18992-3e85-4090-b21e-6ef7fb613a44} + Android + Microsoft_Xbox_Services_Android + 14.0 + Android + 2.0 + + + + StaticLibrary + true + Clang_3_8 + + + StaticLibrary + true + Clang_3_8 + + + StaticLibrary + false + Clang_3_8 + + + StaticLibrary + false + Clang_3_8 + + + + + + + + + + + + + + + + + + ..\..\..\..\lib\boost\include\;%(AdditionalIncludeDirectories) + ..\..\..\..\lib\openssl\include\;%(AdditionalIncludeDirectories) + + + + ..\..\External\cpprestsdk\Release\include\;$(IncludePath) + true + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\ + + + ..\..\External\cpprestsdk\Release\include\;$(IncludePath) + true + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\ + + + ..\..\External\cpprestsdk\Release\include\;$(IncludePath) + true + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\ + + + ..\..\External\cpprestsdk\Release\include\;$(IncludePath) + true + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\ + + + + Use + $(MSBuildThisFileDirectory)..\..\Source\Services\Common\Unix\pch.h + CompileAsCpp + $(ProjectDir).; + $(ProjectDir)\..\..\Source\Services; + $(ProjectDir)\..\..\Source\Services\Common; + $(ProjectDir)\..\..\Source\Services\Common\Unix; + $(ProjectDir)\..\..\Source\Services\Social\Manager; + $(ProjectDir)\..\..\Source\Services\Social; + $(ProjectDir)\..\..\Source\Services\Multiplayer; + $(ProjectDir)\..\..\Source\Services\Presence; + $(ProjectDir)\..\..\Source\Services\RealTimeActivity; + $(ProjectDir)\..\..\Source\Shared; + $(ProjectDir)\..\..\Source\Shared\Desktop; + $(ProjectDir)\..\..\Include; + ..\..\External\cpprestsdk\Release\include; + $(ProjectDir)\..\..\Source\System\Desktop; + $(ProjectDir)\..\..\Source\System; + $(ProjectDir)\..\..\Source\System\auth\Desktop; + $(ProjectDir)\..\..\Source\System\auth; + $(ProjectDir)\..\..\Source\Services\Misc; + %(AdditionalIncludeDirectories) + -std=c++11 -stdlib=libc++ %(AdditionalOptions) + -std=c++11 -stdlib=libc++ %(AdditionalOptions) + -std=c++11 -stdlib=libc++ %(AdditionalOptions) + -std=c++11 -stdlib=libc++ %(AdditionalOptions) + Enabled + Enabled + Enabled + Enabled + TurnOffAllWarnings + TurnOffAllWarnings + TurnOffAllWarnings + TurnOffAllWarnings + true + true + true + true + XSAPI_A=1;XSAPI_U=1;XSAPI_CPP=1;__STDC_WANT_LIB_EXT1__=1;%(PreprocessorDefinitions) + XSAPI_A=1;XSAPI_U=1;XSAPI_CPP=1;__STDC_WANT_LIB_EXT1__=1;%(PreprocessorDefinitions) + XSAPI_A=1;XSAPI_U=1;XSAPI_CPP=1;__STDC_WANT_LIB_EXT1__=1;%(PreprocessorDefinitions) + XSAPI_A=1;XSAPI_U=1;XSAPI_CPP=1;__STDC_WANT_LIB_EXT1__=1;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {afb49019-965b-4c10-baff-c86c16d58010} + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj.filters b/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj.filters new file mode 100644 index 00000000..391f1e01 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.Android/Microsoft.Xbox.Services.Android.vcxproj.filters @@ -0,0 +1,1125 @@ + + + + + {b79b5071-f94f-443a-b903-1b604db21b8e} + + + {e9e0bd97-69fe-4b02-9f7d-b3cfe9ba4124} + + + {f7602d0a-0baf-4796-b386-097b3cbd025e} + + + {5eb1bf88-b7c6-4004-8f89-a51e2a57015b} + + + {c39487ed-7f31-418f-9787-9376286701e9} + + + {0c334ed5-8f7a-4075-a144-38e4fd0cd7dd} + + + {2bd48536-64fb-44b8-80e2-e811e05b4bb3} + + + {7d5155f9-c8c2-445d-b47b-672ae2fc75b7} + + + {8f56c797-92e5-4c3f-80de-930c15740770} + + + {0a2fe2db-9350-4606-81c6-01c2830d4f7b} + + + {9c6c080f-e261-4948-9bb0-fa2b7d4977dd} + + + {5f357938-0de3-4ba8-bfb4-0d09d88d2e73} + + + {2c7f11e9-3f8e-4935-9a4d-418922b96b80} + + + {8d036207-30a2-41b5-b472-be8757efa25c} + + + {8b4f0f8e-eb71-4ff7-93f8-df2f59384ee3} + + + {b6ce571b-a137-4d72-9a7e-6bd4e338fa2f} + + + {70aae843-2a60-4668-9d25-8459b935bb33} + + + {dc690502-8de4-4b6f-b5df-6bde484da01e} + + + {0d68e1d2-b7d1-4df5-a4d9-0006ddbbb16e} + + + {ac78cdb0-adff-47bb-88b9-70c054a317d6} + + + {c1c8fec1-d17f-40a4-8afe-ed1d903a2619} + + + {3029adfc-dd63-464b-ae3d-0022da410d1f} + + + {85f1eb36-3a7a-423c-8e6b-bb257ed9c510} + + + {73afb567-0046-4673-9f59-d7fca6b8bc26} + + + {a1b62f74-4c3a-48cf-b9ff-d6f3fbc1312c} + + + {8ffd87c6-9eda-4354-9713-c0e724865b56} + + + {5d0b5226-c407-4e40-a457-85c3ee92201d} + + + {25a7f18e-58fd-4c25-8ca2-dbd220fc9464} + + + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\System + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Achievements + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Matchmaking + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\Privacy + + + C++ Source\RTA + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\UserStats + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\Presence + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\GameServerPlatform + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Shared + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\TitleStorage + + + C++ Source\Shared + + + C++ Source\Multiplayer + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Common\Desktop + + + C++ Source\Shared + + + C++ Source\GameServerPlatform + + + C++ Source\Shared + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Shared + + + C++ Source\RTA + + + C++ Source\Multiplayer + + + C++ Source\System + + + C++ Source\Shared + + + C++ Source\Common + + + C++ Source\Shared + + + C++ Source\System + + + C++ Source\System + + + C++ Source\Multiplayer + + + C++ Source\Social + + + C++ Source\UserStats + + + C++ Source\Presence + + + C++ Source\System + + + C++ Source\Social + + + C++ Source\Social + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Shared + + + C++ Source\System\a + + + C++ Source\System\a + + + C++ Source\Shared\a + + + C++ Source\System\unix + + + C++ Source\System\unix + + + C++ Source\System\unix + + + C++ Source\System\unix + + + C++ Source\System\unix + + + C++ Source\System + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\Events + + + C++ Source\System\a + + + C++ Source\Shared\a + + + C++ Source\Shared\u + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\System\a + + + C++ Source\System\a + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Common\Unix + + + C++ Source\Common + + + C++ Source\Presence + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Multiplayer + + + C++ Source\Multiplayer + + + C++ Source\Shared\a + + + C++ Source\System\a + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Shared\Logger + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Multiplayer\Manager + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Misc + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\RTA + + + C++ Source\Shared\Logger\android + + + C++ Source\Shared + + + C++ Source\Shared\Logger + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\Social\Manager + + + C++ Source\System\a + + + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Leaderboard + + + C++ Source\Leaderboard + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Public Includes + + + C++ Source\Shared + + + C++ Public Includes + + + C++ Source\Common + + + C++ Source\Shared + + + C++ Source\Common + + + C++ Source\System + + + C++ Source\Shared + + + C++ Source\Shared + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\System + + + C++ Source\Misc + + + C++ Public Includes + + + C++ Source\System + + + C++ Source\System\a + + + C++ Source\Multiplayer + + + C++ Source\Shared\a + + + C++ Source\System\unix + + + C++ Source\System\unix + + + C++ Source\System + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Public Includes + + + C++ Source\System\a + + + C++ Public Includes + + + C++ Source\System\unix + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\Shared\a + + + C++ Source\UserStats + + + C++ Source\System\a + + + C++ Source\System\a + + + C++ Source\Misc + + + C++ Source\Common\Unix + + + C++ Source\Common + + + C++ Source\Social + + + C++ Source\Presence + + + C++ Source\Misc + + + C++ Public Includes + + + C++ Source\Shared\a + + + C++ Source\RTA + + + C++ Source\Shared\Logger + + + C++ Source\Multiplayer\Manager + + + C++ Source\Shared + + + C++ Source\Misc + + + C++ Source\Shared + + + C++ Source\Shared\Logger\android + + + C++ Source\Shared\Logger + + + C++ Source\Social\Manager + + + C++ Source\System\a + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems b/Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems new file mode 100644 index 00000000..d10b34e1 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems @@ -0,0 +1,706 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + 248F659F-DAC5-46E8-AC09-60EC9FC95053 + true + d1830d79-4511-471f-8897-7213d1988ca2 + {e73d47a1-2cf5-4ada-b9e7-f2619f666162} + Microsoft.Xbox.System.120.UnitTest.Shared + Microsoft.Xbox.System.140.UnitTest.Shared + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems.filters b/Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems.filters new file mode 100644 index 00000000..c928660b --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.Shared/Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems.filters @@ -0,0 +1,2193 @@ + + + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\Include + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System\WinRT + + + XSAPI\System\WinRT + + + XSAPI\System\WinRT + + + XSAPI\System\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Common + + + XSAPI\Services\Common + + + XSAPI\Services\Common\WinRT + + + XSAPI\Services\Common\WinRT + + + XSAPI\Services\EntertainmentProfile\WinRT + + + XSAPI\Services\EntertainmentProfile\WinRT + + + XSAPI\Services\EntertainmentProfile\WinRT + + + XSAPI\Services\Events\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Include + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + + + {211196ac-e51a-4500-b3aa-bda845e61e06} + + + {9292ef46-6467-4e89-a0ed-3f6c67e1464b} + + + {63cd81f2-b08f-41fd-ac09-8f2a7d8ef3bd} + + + {795105f8-43d5-4775-9b78-584f575b65ac} + + + {1a8e5778-519a-4eeb-a7bf-abf5859c3994} + + + {9b38e939-82fe-488f-b61c-5301baeb7499} + + + {a8f881c2-8626-467f-ad39-7ae46cd0f49a} + + + {f523e9b8-ceec-44b7-9a7c-1ba0b488632e} + + + {88db0712-d16f-41f6-8782-86b92a3cc41f} + + + {fd662fa1-4498-4661-bc58-728b00583990} + + + {90545594-33d1-48e8-b965-74528429063c} + + + {9633fcdd-97f3-4d26-808e-6d8364797ff1} + + + {1e50b5ef-dfe7-4c4f-9b3a-6440165ed26e} + + + {88b30342-f986-4055-ab31-0380d4d91677} + + + {817faa9f-51a3-4a6c-801e-c88eb9db73b5} + + + {75ba5cb4-d519-4d63-9642-e1b35befac9d} + + + {eb4c3b1f-e19c-45dd-af98-6086808bb7c4} + + + {221ffd7e-5716-4b2d-afd6-aac0ef4baf83} + + + {d1a44358-f38c-4ec9-b2d7-caacb2b5ffef} + + + {b76f1a38-f655-466e-b49b-44ab14bf501b} + + + {d73285c9-0a1d-481c-b31d-553845a52c13} + + + {bd6964f5-39fe-4acf-8d0d-3b93a07a34c6} + + + {ee880c88-0019-4e4d-9aeb-08f4e05901a1} + + + {2c07f507-08c7-4a11-9583-3b36688ea738} + + + {3be3e4bc-bda5-4d6e-ab32-e769e940663a} + + + {f93e5cc1-3812-4237-9869-5aa6ac797310} + + + {f0b03c04-a984-49e0-83a9-59ac94e77d67} + + + {7f7d1de9-0007-4eb7-a264-d85e4e3a387c} + + + {b4c16103-5ab5-456f-9d2d-467836830fc9} + + + {da15369f-4fa0-4f95-9cc3-6c47e641515f} + + + {5eb55da5-5c58-4f31-a332-9e093d251b59} + + + {859901ff-e038-4a66-8fda-320f384a9aeb} + + + {6b1169c9-535a-4166-848b-1ecaeb83225c} + + + {24a44121-a0a8-4bac-856b-463b5e256d31} + + + {c9f9ecef-c2a4-4301-b68c-5fd58e0d9b15} + + + {e007a9bd-ed1f-4f22-8eb6-22928f387bd9} + + + {56a52bb6-92b7-4c2e-b22d-e87253d2bed4} + + + {e93851c2-acc0-4dfe-bacc-70677b2b5939} + + + {c6ac1181-5dfa-4275-b50c-b02a4e310dc2} + + + {bf4c3aae-1730-4cc9-8df8-caf5b95baa92} + + + {d5f6e25f-a579-4ae2-b504-de1a30c447bc} + + + {d76d8f79-c9aa-4e8b-aeb2-bc703e16a25f} + + + {291bde9f-6768-4047-9bff-636cf59749fb} + + + {827b3b64-7716-4c23-abdf-a8e4b3b0c0c0} + + + {c7c2e557-414d-4a02-b903-a291f80301c6} + + + {7170ef92-e75d-4ede-a2ae-d3bcf406956f} + + + {c81f709b-04e9-4eda-bbbf-9f0dfada975b} + + + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System + + + XSAPI\System\WinRT + + + XSAPI\System\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared\Logger + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Shared + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Achievements\WinRT + + + XSAPI\Services\Common + + + XSAPI\Services\Common\Desktop + + + XSAPI\Services\Common\WinRT + + + XSAPI\Services\Common\WinRT + + + XSAPI\Services\EntertainmentProfile + + + XSAPI\Services\EntertainmentProfile + + + XSAPI\Services\EntertainmentProfile + + + XSAPI\Services\EntertainmentProfile\WinRT + + + XSAPI\Services\EntertainmentProfile\WinRT + + + XSAPI\Services\EntertainmentProfile\WinRT + + + XSAPI\Services\Events + + + XSAPI\Services\Events\WinRT + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\GameServerPlatform\WinRT + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Leaderboard\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace\WinRT + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Marketplace + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Misc\WinRT + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager\WinRT + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Multiplayer\Manager + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence\WinRT + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Presence + + + XSAPI\Services\Privacy + + + XSAPI\Services\Privacy + + + XSAPI\Services\Privacy + + + XSAPI\Services\Privacy + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\Privacy\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA\WinRT + + + XSAPI\Services\RTA + + + XSAPI\Services\RTA + + + XSAPI\Services\RTA + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social\WinRT + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats\WinRT + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\Stats + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage\WinRT + + + XSAPI\Services\TitleStorage + + + XSAPI\Services\TitleStorage + + + XSAPI\Services\TitleStorage + + + XSAPI\Services\TitleStorage + + + XSAPI\Services\TitleStorage + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments\WinRT + + + XSAPI\Services\Touraments + + + XSAPI\Services\Touraments + + + XSAPI\Services\Matchmaking + + + XSAPI\Services\Matchmaking + + + XSAPI\Services\Matchmaking + + + XSAPI\Services\Matchmaking + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Services\Matchmaking\WinRT + + + XSAPI\Shared + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Shared + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\Social\Manager\WinRT + + + XSAPI\Services\RTA + + + XSAPI\Services\Misc + + + XSAPI\Shared\Logger + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + XSAPI\Shared\Logger + + + XSAPI\Shared\WinRT + + + XSAPI\Shared\WinRT + + + XSAPI\System + + + XSAPI\Services\Social\Manager + + + XSAPI\Services\Multiplayer + + + XSAPI\Services\Multiplayer\WinRT + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.sln b/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.sln new file mode 100644 index 00000000..8cc31f7b --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.UnitTest.140.TAEF", "Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj", "{15F89B6A-312D-49A6-BBA6-CFD9242DB58E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.System.140.UnitTest.Shared", "..\Microsoft.Xbox.Services.UnitTest.140.Shared\Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems", "{E73D47A1-2CF5-4ADA-B9E7-F2619F666162}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.static", "..\..\External\cpprestsdk\Release\src\build\vs14\casablanca140.static.vcxproj", "{04D42F35-E5D5-4D95-980E-1BD7E900F2DD}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\External\cpprestsdk\Release\src\build\common.vcxitems*{04d42f35-e5d5-4d95-980e-1bd7e900f2dd}*SharedItemsImports = 4 + ..\..\External\cpprestsdk\Release\src\build\win32.vcxitems*{04d42f35-e5d5-4d95-980e-1bd7e900f2dd}*SharedItemsImports = 4 + ..\Microsoft.Xbox.Services.UnitTest.140.Shared\Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems*{15f89b6a-312d-49a6-bba6-cfd9242db58e}*SharedItemsImports = 4 + ..\Microsoft.Xbox.Services.UnitTest.140.Shared\Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems*{e73d47a1-2cf5-4ada-b9e7-f2619f666162}*SharedItemsImports = 9 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Debug|ARM.ActiveCfg = Debug|Win32 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Debug|x64.ActiveCfg = Debug|x64 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Debug|x64.Build.0 = Debug|x64 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Debug|x86.ActiveCfg = Debug|Win32 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Debug|x86.Build.0 = Debug|Win32 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Release|ARM.ActiveCfg = Release|Win32 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Release|x64.ActiveCfg = Release|x64 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Release|x64.Build.0 = Release|x64 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Release|x86.ActiveCfg = Release|Win32 + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E}.Release|x86.Build.0 = Release|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|ARM.ActiveCfg = Debug|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|ARM.Build.0 = Debug|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x64.ActiveCfg = Debug|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x64.Build.0 = Debug|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x86.ActiveCfg = Debug|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x86.Build.0 = Debug|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|ARM.ActiveCfg = Release|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|ARM.Build.0 = Release|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x64.ActiveCfg = Release|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x64.Build.0 = Release|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x86.ActiveCfg = Release|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj b/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj new file mode 100644 index 00000000..f55ffe67 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj @@ -0,0 +1,256 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + Microsoft.Xbox.Services.UnitTest.140.TAEF + {15F89B6A-312D-49A6-BBA6-CFD9242DB58E} + Microsoft.Xbox.System.Test + 10.0.10240.0 + 10.0.10240.0 + DynamicLibrary + v140 + Unicode + false + + + true + + + false + true + + + + + + + + + + + + + + + + + + /bigobj /Zm512 /GS %(AdditionalOptions) + $(ProjectDir); + $(ProjectDir)..\..\Source\Shared; + $(ProjectDir)..\..\Source\System; + $(ProjectDir)..\..\Source\System\auth; + $(ProjectDir)..\..\Source\Shared\WinRT; + $(ProjectDir)..\..\Source\System\WinRT; + $(ProjectDir)..\..\Source\System\Desktop; + $(ProjectDir)..\..\Source\System\auth\WinRT; + $(ProjectDir)..\..\Source\System\auth\Desktop; + $(ProjectDir)..\..\Source\Services; + $(ProjectDir)..\..\Source\Services\Common; + $(ProjectDir)..\..\Source\Services\Common\WinRT; + $(ProjectDir)..\..\Source\Services\Social; + $(ProjectDir)..\..\Source\Services\Social\WinRT; + $(ProjectDir)..\..\Source\Services\Achievements; + $(ProjectDir)..\..\Source\Services\Achievements\WinRT; + $(ProjectDir)..\..\Source\Services\EntertainmentProfile; + $(ProjectDir)..\..\Source\Services\EntertainmentProfile\WinRT; + $(ProjectDir)..\..\Source\Services\Leaderboard; + $(ProjectDir)..\..\Source\Services\Leaderboard\WinRT; + $(ProjectDir)..\..\Source\Services\Misc; + $(ProjectDir)..\..\Source\Services\Misc\WinRT; + $(ProjectDir)..\..\Source\Services\Stats; + $(ProjectDir)..\..\Source\Services\Stats\WinRT; + $(ProjectDir)..\..\Source\Services\Multiplayer; + $(ProjectDir)..\..\Source\Services\Multiplayer\WinRT; + $(ProjectDir)..\..\Source\Services\Multiplayer; + $(ProjectDir)..\..\Source\Services\Multiplayer\Manager; + $(ProjectDir)..\..\Source\Services\Multiplayer\Manager\WinRT; + $(ProjectDir)..\..\Source\Services\Social\Manager; + $(ProjectDir)..\..\Source\Services\Social\Manager\WinRT; + $(ProjectDir)..\..\Source\Services\Matchmaking; + $(ProjectDir)..\..\Source\Services\Matchmaking\WinRT; + $(ProjectDir)..\..\Source\Services\RealTimeActivity; + $(ProjectDir)..\..\Source\Services\RealTimeActivity\WinRT; + $(ProjectDir)..\..\Source\Services\Presence; + $(ProjectDir)..\..\Source\Services\Presence\WinRT; + $(ProjectDir)..\..\Source\Services\GameServerPlatform; + $(ProjectDir)..\..\Source\Services\GameServerPlatform\WinRT; + $(ProjectDir)..\..\Source\Services\TitleStorage; + $(ProjectDir)..\..\Source\Services\TitleStorage\WinRT; + $(ProjectDir)..\..\Source\Services\Privacy; + $(ProjectDir)..\..\Source\Services\Privacy\WinRT; + $(ProjectDir)..\..\Source\Services\Marketplace; + $(ProjectDir)..\..\Source\Services\Marketplace\WinRT; + $(ProjectDir)..\..\Source\Services\Tournaments; + $(ProjectDir)..\..\Source\Services\Tournaments\WinRT; + $(ProjectDir)..\..\Source\Services\Events; + $(ProjectDir)..\..\Source\Services\Events\WinRT; + $(ProjectDir)..\..\Include; + $(ProjectDir)..\..\Tests\UnitTests; + $(ProjectDir)..\..\Tests\UnitTests\Mocks; + $(ProjectDir)..\..\Tests\UnitTests\Support; + ..\..\External\cpprestsdk\Release\include; + ..\..\TAEF\Include; + ..\..\MorroMock; + %(AdditionalIncludeDirectories) + + + + ..\..\TAEF\Library\Release\x64;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\TAEF\Library\Release\x86\;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + USING_TAEF;DASHBOARD_PRINCIPLE_GROUP;_NO_ASYNCRTIMP;_NO_PPLXIMP;_XSAPIIMP_EXPORT;XBOX_SYSTEM;INLINE_TEST_METHOD_MARKUP;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;UNIT_TEST_SERVICES;USING_STOCK_CASABLANCA;%(PreprocessorDefinitions) + true + true + pch.h + $(IntDir)pch.pch + true + $(WindowsSdkDir_10)UnionMetadata;$(VCInstallDir)lib\store\references;%(AdditionalUsingDirectories) + + + true + Wex.Common.lib;Msxml6.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + false + Console + + + xcopy "$(ProjectDir)..\..\Tests\UnitTests\Tests\Services\TestResponses" "$(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\TestResponses" /e /y /i /r + + + + + Disabled + false + ProgramDatabase + 4592 + 4592 + + + + + MaxSpeed + true + true + 4592 + 4592 + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {04d42f35-e5d5-4d95-980e-1bd7e900f2dd} + + + + + + + + + + + + + Microsoft.Xbox.System.UnitTest + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\ + $(ProjectDir)..\..\Obj\$(Configuration)\$(Platform)\$(ProjectName)\ + $(ProjectDir)..\..\TAEF\Binaries\Release\$(PlatformTarget)\TestExecution\TE.exe + $(TargetPath) /inproc + WindowsLocalDebugger + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj.filters b/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj.filters new file mode 100644 index 00000000..9ceb41da --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TAEF/Microsoft.Xbox.Services.UnitTest.140.TAEF.vcxproj.filters @@ -0,0 +1,204 @@ + + + + + {d0c65fcc-4e8f-4806-a1f5-8c3bff619c60} + + + {427f65f2-ea07-4751-8bfa-e3e8d7c2371b} + + + {c195dd2d-462b-4f92-99ec-7222b823e3e7} + + + {7c1fb704-9ae9-44a6-99c2-60d96058f419} + + + {46185992-46f0-4ba5-a9a1-a9b38287821f} + + + {08277cd5-2226-46d9-872a-a61b46f724fe} + + + + + Tests\Support + + + Tests\Support + + + Tests\Support\TAEF + + + Tests\Support\TAEF + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Services + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + + + Tests\Support + + + Tests\Support + + + Tests\Support + + + Tests\Support + + + Tests\Support\TAEF + + + Tests\Support\TAEF + + + Tests\Support\TAEF + + + Tests\Services + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Support\Mocks + + + Tests\Services + + + Tests\Support\Mocks + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.sln b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.sln new file mode 100644 index 00000000..ee9c8061 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.Services.UnitTest.140.TAEF", "Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj", "{3092CCC9-DB6E-4199-95CC-4959950B95FA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Xbox.System.140.UnitTest.Shared", "..\Microsoft.Xbox.Services.UnitTest.140.Shared\Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems", "{E73D47A1-2CF5-4ADA-B9E7-F2619F666162}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.static", "..\..\External\cpprestsdk\Release\src\build\vs14\casablanca140.static.vcxproj", "{04D42F35-E5D5-4D95-980E-1BD7E900F2DD}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\Microsoft.Xbox.Services.UnitTest.140.Shared\Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems*{3092ccc9-db6e-4199-95cc-4959950b95fa}*SharedItemsImports = 4 + ..\..\External\cpprestsdk\Release\src\build\win32.vcxitems*{04d42f35-e5d5-4d95-980e-1bd7e900f2dd}*SharedItemsImports = 4 + ..\..\External\cpprestsdk\Release\src\build\common.vcxitems*{04d42f35-e5d5-4d95-980e-1bd7e900f2dd}*SharedItemsImports = 4 + ..\Microsoft.Xbox.Services.UnitTest.140.Shared\Microsoft.Xbox.Services.UnitTest.140.Shared.vcxitems*{e73d47a1-2cf5-4ada-b9e7-f2619f666162}*SharedItemsImports = 9 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Debug|ARM.ActiveCfg = Debug|Win32 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Debug|x64.ActiveCfg = Debug|x64 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Debug|x64.Build.0 = Debug|x64 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Debug|x86.ActiveCfg = Debug|Win32 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Debug|x86.Build.0 = Debug|Win32 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Release|ARM.ActiveCfg = Release|Win32 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Release|x64.ActiveCfg = Release|x64 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Release|x64.Build.0 = Release|x64 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Release|x86.ActiveCfg = Release|Win32 + {3092CCC9-DB6E-4199-95CC-4959950B95FA}.Release|x86.Build.0 = Release|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|ARM.ActiveCfg = Debug|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|ARM.Build.0 = Debug|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x64.ActiveCfg = Debug|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x64.Build.0 = Debug|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x86.ActiveCfg = Debug|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Debug|x86.Build.0 = Debug|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|ARM.ActiveCfg = Release|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|ARM.Build.0 = Release|ARM + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x64.ActiveCfg = Release|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x64.Build.0 = Release|x64 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x86.ActiveCfg = Release|Win32 + {04D42F35-E5D5-4D95-980E-1BD7E900F2DD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj new file mode 100644 index 00000000..25e3f86c --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj @@ -0,0 +1,343 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + /bigobj /Zm512 %(AdditionalOptions) + $(ProjectDir); + $(ProjectDir)..\..\Source\Shared; + $(ProjectDir)..\..\Source\System; + $(ProjectDir)..\..\Source\System\auth; + $(ProjectDir)..\..\Source\Shared\WinRT; + $(ProjectDir)..\..\Source\System\WinRT; + $(ProjectDir)..\..\Source\System\Desktop; + $(ProjectDir)..\..\Source\System\auth\WinRT; + $(ProjectDir)..\..\Source\System\auth\Desktop; + $(ProjectDir)..\..\Source\Services; + $(ProjectDir)..\..\Source\Services\Common; + $(ProjectDir)..\..\Source\Services\Common\WinRT; + $(ProjectDir)..\..\Source\Services\Social; + $(ProjectDir)..\..\Source\Services\Social\WinRT; + $(ProjectDir)..\..\Source\Services\Achievements; + $(ProjectDir)..\..\Source\Services\Achievements\WinRT; + $(ProjectDir)..\..\Source\Services\EntertainmentProfile; + $(ProjectDir)..\..\Source\Services\EntertainmentProfile\WinRT; + $(ProjectDir)..\..\Source\Services\Leaderboard; + $(ProjectDir)..\..\Source\Services\Leaderboard\WinRT; + $(ProjectDir)..\..\Source\Services\Misc; + $(ProjectDir)..\..\Source\Services\Misc\WinRT; + $(ProjectDir)..\..\Source\Services\Stats; + $(ProjectDir)..\..\Source\Services\Stats\WinRT; + $(ProjectDir)..\..\Source\Services\Multiplayer; + $(ProjectDir)..\..\Source\Services\Multiplayer\WinRT; + $(ProjectDir)..\..\Source\Services\Multiplayer; + $(ProjectDir)..\..\Source\Services\Multiplayer\Manager; + $(ProjectDir)..\..\Source\Services\Multiplayer\Manager\WinRT; + $(ProjectDir)..\..\Source\Services\Social\Manager; + $(ProjectDir)..\..\Source\Services\Social\Manager\WinRT; + $(ProjectDir)..\..\Source\Services\Matchmaking; + $(ProjectDir)..\..\Source\Services\Matchmaking\WinRT; + $(ProjectDir)..\..\Source\Services\RealTimeActivity; + $(ProjectDir)..\..\Source\Services\RealTimeActivity\WinRT; + $(ProjectDir)..\..\Source\Services\Presence; + $(ProjectDir)..\..\Source\Services\Presence\WinRT; + $(ProjectDir)..\..\Source\Services\GameServerPlatform; + $(ProjectDir)..\..\Source\Services\GameServerPlatform\WinRT; + $(ProjectDir)..\..\Source\Services\TitleStorage; + $(ProjectDir)..\..\Source\Services\TitleStorage\WinRT; + $(ProjectDir)..\..\Source\Services\Privacy; + $(ProjectDir)..\..\Source\Services\Privacy\WinRT; + $(ProjectDir)..\..\Source\Services\Marketplace; + $(ProjectDir)..\..\Source\Services\Marketplace\WinRT; + $(ProjectDir)..\..\Source\Services\Tournaments; + $(ProjectDir)..\..\Source\Services\Tournaments\WinRT; + $(ProjectDir)..\..\Source\Services\Events; + $(ProjectDir)..\..\Source\Services\Events\WinRT; + $(ProjectDir)..\..\Include; + $(ProjectDir)..\..\Tests\UnitTests; + $(ProjectDir)..\..\Tests\UnitTests\Mocks; + $(ProjectDir)..\..\Tests\UnitTests\Support; + $(ProjectDir)..\..\External\cpprestsdk\Release\include; + %(AdditionalIncludeDirectories) + + + + + Level3 + DASHBOARD_PRINCIPLE_GROUP;_NO_ASYNCRTIMP;_NO_PPLXIMP;_XSAPIIMP_EXPORT;XBOX_SYSTEM;INLINE_TEST_METHOD_MARKUP;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;UNIT_TEST_SERVICES;USING_STOCK_CASABLANCA;%(PreprocessorDefinitions) + true + true + /bigobj /Zm512 %(AdditionalOptions) + C:\Program Files (x86)\Windows Kits\10\UnionMetadata;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\store\references;%(AdditionalUsingDirectories) + + + true + Crypt32.lib;Winhttp.lib;Bcrypt.lib;Ws2_32.lib;pathcch.lib;Msxml6.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + false + Console + + + xcopy "$(ProjectDir)..\..\Tests\UnitTests\Tests\Services\TestResponses" "$(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\TestResponses" /e /y /i /r + + + + {3092CCC9-DB6E-4199-95CC-4959950B95FA} + Win32Proj + Microsoft.Xbox.Services.140.UnitTest + 8.1 + Microsoft.Xbox.Services.UnitTest.140.TE + + + + DynamicLibrary + true + v140 + Unicode + false + false + + + DynamicLibrary + true + v140 + Unicode + false + false + + + DynamicLibrary + false + v140 + true + Unicode + false + false + + + DynamicLibrary + false + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + + + + Level3 + Disabled + ..\..\Source;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + DASHBOARD_PRINCIPLE_GROUP;_NO_ASYNCRTIMP;_NO_PPLXIMP;_XSAPIIMP_EXPORT;XBOX_SYSTEM;INLINE_TEST_METHOD_MARKUP;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;UNIT_TEST_SERVICES;USING_STOCK_CASABLANCA;_DEBUG;%(PreprocessorDefinitions) + true + true + false + Use + pch.h + + + Windows + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Disabled + ..\..\Source;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + true + true + false + Use + pch.h + + + Windows + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Use + MaxSpeed + true + true + ..\..\Source;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + true + true + + + Windows + true + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Use + MaxSpeed + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + true + true + + + Windows + true + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {04d42f35-e5d5-4d95-980e-1bd7e900f2dd} + + + + Microsoft.Xbox.System.UnitTestNew + $(ProjectDir)..\..\Binaries\$(Configuration)\$(Platform)\$(ProjectName)\ + $(ProjectDir)..\..\Obj\$(Configuration)\$(Platform)\$(ProjectName)\ + + + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj.filters b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj.filters new file mode 100644 index 00000000..d63e4db9 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/Microsoft.Xbox.Services.UnitTest.140.TE.vcxproj.filters @@ -0,0 +1,205 @@ + + + + + {d0c65fcc-4e8f-4806-a1f5-8c3bff619c60} + + + {c195dd2d-462b-4f92-99ec-7222b823e3e7} + + + {7c1fb704-9ae9-44a6-99c2-60d96058f419} + + + {38fc3bb7-4762-4093-9357-2286624d23ff} + + + {9cef44ea-7d6e-4d7c-9856-a8a31045df5c} + + + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support\TE + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\ServiceTests + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Tests\Shared + + + Support + + + Support + + + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + Support + + + + XSAPI\Include + + + Support + + + Support\TE + + + Support\TE + + + Support + + + Tests\ServiceTests + + + Support + + + Support + + + Support + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestAll.runsettings b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestAll.runsettings new file mode 100644 index 00000000..ef9fa601 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestAll.runsettings @@ -0,0 +1,38 @@ + + + + x86 + + + + + + + + + + .*Microsoft::Xbox.* + .*xbox::services.* + + + + ^Platform::.* + ^Windows::Foundation::.* + ^std::.* + .*_abi_.* + Platform + Microsoft::VisualStudio::.* + Concurrency.* + + + + + .*CPPUnitTestFramework.* + + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestMultiplayerManager.runsettings b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestMultiplayerManager.runsettings new file mode 100644 index 00000000..bc543943 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestMultiplayerManager.runsettings @@ -0,0 +1,38 @@ + + + + x86 + + + + + + + + + + .*Microsoft::Xbox::Services::Multiplayer::Manager.* + .*xbox::services::multiplayer::manager.* + + + + ^Platform::.* + ^Windows::Foundation::.* + ^std::.* + .*_abi_.* + Platform + Microsoft::VisualStudio::.* + Concurrency.* + + + + + .*CPPUnitTestFramework.* + + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestSocialManager.runsettings b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestSocialManager.runsettings new file mode 100644 index 00000000..cff08bea --- /dev/null +++ b/Build/Microsoft.Xbox.Services.UnitTest.140.TE/TestSocialManager.runsettings @@ -0,0 +1,38 @@ + + + + x86 + + + + + + + + + + .*Microsoft::Xbox::Services::Social::Manager.* + .*xbox::services::social::manager.* + + + + ^Platform::.* + ^Windows::Foundation::.* + ^std::.* + .*_abi_.* + Platform + Microsoft::VisualStudio::.* + Concurrency.* + + + + + .*CPPUnitTestFramework.* + + + + + + + + \ No newline at end of file diff --git a/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.pbxproj b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2486eb22 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.pbxproj @@ -0,0 +1,2046 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 251DBDD71CE6DE41003AF56B /* utils_locales_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 251DBDD61CE6DE41003AF56B /* utils_locales_ios.mm */; }; + 255A36C31CD8353B00D3AD8E /* find_match_completed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36A61CD8353B00D3AD8E /* find_match_completed_event_args.cpp */; }; + 255A36C41CD8353B00D3AD8E /* host_changed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36A71CD8353B00D3AD8E /* host_changed_event_args.cpp */; }; + 255A36C51CD8353B00D3AD8E /* join_lobby_completed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36A81CD8353B00D3AD8E /* join_lobby_completed_event_args.cpp */; }; + 255A36C71CD8353B00D3AD8E /* member_joined_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36AA1CD8353B00D3AD8E /* member_joined_event_args.cpp */; }; + 255A36C81CD8353B00D3AD8E /* member_left_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36AB1CD8353B00D3AD8E /* member_left_event_args.cpp */; }; + 255A36C91CD8353B00D3AD8E /* member_property_changed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36AC1CD8353B00D3AD8E /* member_property_changed_event_args.cpp */; }; + 255A36CA1CD8353B00D3AD8E /* multiplayer_client_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36AD1CD8353B00D3AD8E /* multiplayer_client_manager.cpp */; }; + 255A36CB1CD8353B00D3AD8E /* multiplayer_client_pending_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36AE1CD8353B00D3AD8E /* multiplayer_client_pending_reader.cpp */; }; + 255A36CC1CD8353B00D3AD8E /* multiplayer_client_pending_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36AF1CD8353B00D3AD8E /* multiplayer_client_pending_request.cpp */; }; + 255A36CD1CD8353B00D3AD8E /* multiplayer_event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B01CD8353B00D3AD8E /* multiplayer_event.cpp */; }; + 255A36CE1CD8353B00D3AD8E /* multiplayer_game_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B11CD8353B00D3AD8E /* multiplayer_game_client.cpp */; }; + 255A36CF1CD8353B00D3AD8E /* multiplayer_game_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B21CD8353B00D3AD8E /* multiplayer_game_session.cpp */; }; + 255A36D01CD8353B00D3AD8E /* multiplayer_lobby_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B31CD8353B00D3AD8E /* multiplayer_lobby_client.cpp */; }; + 255A36D11CD8353B00D3AD8E /* multiplayer_lobby_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B41CD8353B00D3AD8E /* multiplayer_lobby_session.cpp */; }; + 255A36D21CD8353B00D3AD8E /* multiplayer_local_user_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B51CD8353B00D3AD8E /* multiplayer_local_user_manager.cpp */; }; + 255A36D31CD8353B00D3AD8E /* multiplayer_local_user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B61CD8353B00D3AD8E /* multiplayer_local_user.cpp */; }; + 255A36D41CD8353B00D3AD8E /* multiplayer_manager_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B81CD8353B00D3AD8E /* multiplayer_manager_utils.cpp */; }; + 255A36D51CD8353B00D3AD8E /* multiplayer_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36B91CD8353B00D3AD8E /* multiplayer_manager.cpp */; }; + 255A36D61CD8353B00D3AD8E /* multiplayer_member.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36BA1CD8353B00D3AD8E /* multiplayer_member.cpp */; }; + 255A36D71CD8353B00D3AD8E /* multiplayer_session_writer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36BB1CD8353B00D3AD8E /* multiplayer_session_writer.cpp */; }; + 255A36D81CD8353B00D3AD8E /* perform_qos_measurements_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36BC1CD8353B00D3AD8E /* perform_qos_measurements_event_args.cpp */; }; + 255A36D91CD8353B00D3AD8E /* session_property_changed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36BD1CD8353B00D3AD8E /* session_property_changed_event_args.cpp */; }; + 255A36DA1CD8353B00D3AD8E /* tournament_game_session_ready_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36BE1CD8353B00D3AD8E /* tournament_game_session_ready_event_args.cpp */; }; + 255A36DB1CD8353B00D3AD8E /* tournament_registration_state_changed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36BF1CD8353B00D3AD8E /* tournament_registration_state_changed_event_args.cpp */; }; + 255A36DC1CD8353B00D3AD8E /* user_added_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36C01CD8353B00D3AD8E /* user_added_event_args.cpp */; }; + 255A36DD1CD8353B00D3AD8E /* user_removed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255A36C11CD8353B00D3AD8E /* user_removed_event_args.cpp */; }; + 255A36DE1CD8353B00D3AD8E /* WinRT in Resources */ = {isa = PBXBuildFile; fileRef = 255A36C21CD8353B00D3AD8E /* WinRT */; }; + 32F5FBBF1CE7DB1D008A5E09 /* title_callable_ui.mm in Sources */ = {isa = PBXBuildFile; fileRef = 32F5FBBE1CE7DB1D008A5E09 /* title_callable_ui.mm */; }; + 670AA2F61C7657D300B3FB9A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670AA2F51C7657D300B3FB9A /* SystemConfiguration.framework */; }; + 6718D8B01C865AD0007FD4F6 /* XboxProviderBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6718D8AE1C865AD0007FD4F6 /* XboxProviderBridge.cpp */; }; + 6718D8B71C86605E007FD4F6 /* XBLSignInHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6718D8B61C86605E007FD4F6 /* XBLSignInHandler.mm */; }; + 6718D9161C9F69CA007FD4F6 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6718D9151C9F69CA007FD4F6 /* CoreText.framework */; }; + 6718F1C11CB76BF50000BF6E /* XBLServiceManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6718F1C01CB76BF50000BF6E /* XBLServiceManager.mm */; }; + 6718F1E51CB77FEB0000BF6E /* XBLDictionaryToJSON.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6718F1E41CB77FEB0000BF6E /* XBLDictionaryToJSON.mm */; }; + 671F66DB1CD43A0000119106 /* multiplayer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BF11AE61C17ABA400D111C9 /* multiplayer.h */; }; + 67210E721C6479E20008FFDB /* NSError+XSAPIExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 67210E251C6479E20008FFDB /* NSError+XSAPIExtensions.mm */; }; + 67210E731C6479E20008FFDB /* XboxProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 67210E271C6479E20008FFDB /* XboxProvider.mm */; }; + 677B9FCD1CD90F2900A28F96 /* XBLiOSGlobalState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 677B9FCC1CD90F2900A28F96 /* XBLiOSGlobalState.mm */; }; + 67F503A41CD98D8E00198DEA /* xbox_live_app_config_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 67F503A31CD98D8E00198DEA /* xbox_live_app_config_ios.mm */; }; + 9B118A951D4BFF070068B268 /* multiplayer_role_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B118A921D4BFF070068B268 /* multiplayer_role_info.cpp */; }; + 9B118A961D4BFF070068B268 /* multiplayer_role_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B118A931D4BFF070068B268 /* multiplayer_role_type.cpp */; }; + 9B118A971D4BFF070068B268 /* multiplayer_session_role_types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B118A941D4BFF070068B268 /* multiplayer_session_role_types.cpp */; }; + 9B118AC21D6D0B460068B268 /* debug_output_ios.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B118AC11D6D0B460068B268 /* debug_output_ios.cpp */; }; + 9B118ADB1D885FA80068B268 /* user_auth_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B118ADA1D885FA80068B268 /* user_auth_ios.mm */; }; + 9B118AE11D8B35230068B268 /* user_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B118AE01D8B35230068B268 /* user_impl_ios.mm */; }; + 9B2956121CE244CD0026A41C /* xbox_cll.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B2956101CE244CD0026A41C /* xbox_cll.mm */; }; + 9B2956151CE247490026A41C /* events_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B2956141CE247490026A41C /* events_service.cpp */; }; + 9B46ED461BED41D600076704 /* ecdsa_unix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B46ED441BED41D600076704 /* ecdsa_unix.cpp */; }; + 9B46ED471BED41D600076704 /* ip_address_unix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B46ED451BED41D600076704 /* ip_address_unix.cpp */; }; + 9B46ED511BF105A000076704 /* xbox_system_factory_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B46ED501BF105A000076704 /* xbox_system_factory_ios.mm */; }; + 9B46ED551BF14AFA00076704 /* user_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B46ED541BF14AFA00076704 /* user_ios.mm */; }; + 9B4933FA1CE8F29E00E7CE0B /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B4933F91CE8F29E00E7CE0B /* WebKit.framework */; }; + 9B4934791CEE1C1800E7CE0B /* notification_helper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B4934781CEE1C1800E7CE0B /* notification_helper.mm */; }; + 9B4B44A11D2F22C30060F1C5 /* real_time_activity_service_factory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4B44A01D2F22C30060F1C5 /* real_time_activity_service_factory.cpp */; }; + 9B4B44AF1D2F2D4C0060F1C5 /* log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4B44A91D2F2D4C0060F1C5 /* log.cpp */; }; + 9B4B44B01D2F2D4C0060F1C5 /* log_entry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4B44AB1D2F2D4C0060F1C5 /* log_entry.cpp */; }; + 9B4B44B11D2F2D4C0060F1C5 /* log_output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4B44AC1D2F2D4C0060F1C5 /* log_output.cpp */; }; + 9B5A0FD61BFA603A00BE12FD /* achievement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FB61BFA603A00BE12FD /* achievement.cpp */; }; + 9B5A0FD71BFA603A00BE12FD /* achievement_media_asset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FB71BFA603A00BE12FD /* achievement_media_asset.cpp */; }; + 9B5A0FD81BFA603A00BE12FD /* achievement_progression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FB81BFA603A00BE12FD /* achievement_progression.cpp */; }; + 9B5A0FD91BFA603A00BE12FD /* achievement_requirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FB91BFA603A00BE12FD /* achievement_requirement.cpp */; }; + 9B5A0FDA1BFA603A00BE12FD /* achievement_reward.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FBA1BFA603A00BE12FD /* achievement_reward.cpp */; }; + 9B5A0FDB1BFA603A00BE12FD /* achievement_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FBB1BFA603A00BE12FD /* achievement_service.cpp */; }; + 9B5A0FDC1BFA603A00BE12FD /* achievement_time_window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FBC1BFA603A00BE12FD /* achievement_time_window.cpp */; }; + 9B5A0FDD1BFA603A00BE12FD /* achievement_title_association.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FBD1BFA603A00BE12FD /* achievement_title_association.cpp */; }; + 9B5A0FDE1BFA603A00BE12FD /* achievements_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FBE1BFA603A00BE12FD /* achievements_result.cpp */; }; + 9B5A11C11BFA60E100BE12FD /* entertainment_profile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FE81BFA60E000BE12FD /* entertainment_profile.cpp */; }; + 9B5A11C21BFA60E100BE12FD /* entertainment_profile_list_contains_item_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FE91BFA60E000BE12FD /* entertainment_profile_list_contains_item_result.cpp */; }; + 9B5A11C31BFA60E100BE12FD /* entertainment_profile_list_xbox_one_pins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FEA1BFA60E000BE12FD /* entertainment_profile_list_xbox_one_pins.cpp */; }; + 9B5A11C41BFA60E100BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FEC1BFA60E000BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.cpp */; }; + 9B5A11C51BFA60E100BE12FD /* EntertainmentProfileListService_WinRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FEE1BFA60E000BE12FD /* EntertainmentProfileListService_WinRT.cpp */; }; + 9B5A11C61BFA60E100BE12FD /* EntertainmentProfileListVideoQueue_WinRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FF01BFA60E000BE12FD /* EntertainmentProfileListVideoQueue_WinRT.cpp */; }; + 9B5A11C91BFA60E100BE12FD /* allocation_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FF81BFA60E000BE12FD /* allocation_result.cpp */; }; + 9B5A11CA1BFA60E100BE12FD /* cluster_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FF91BFA60E000BE12FD /* cluster_result.cpp */; }; + 9B5A11CB1BFA60E100BE12FD /* game_server_image_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FFA1BFA60E000BE12FD /* game_server_image_set.cpp */; }; + 9B5A11CC1BFA60E100BE12FD /* game_server_metadata_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FFB1BFA60E000BE12FD /* game_server_metadata_result.cpp */; }; + 9B5A11CD1BFA60E100BE12FD /* game_server_platform_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FFC1BFA60E000BE12FD /* game_server_platform_service.cpp */; }; + 9B5A11CE1BFA60E100BE12FD /* game_server_port_mapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FFD1BFA60E000BE12FD /* game_server_port_mapping.cpp */; }; + 9B5A11CF1BFA60E100BE12FD /* game_server_ticket_status.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FFE1BFA60E000BE12FD /* game_server_ticket_status.cpp */; }; + 9B5A11D01BFA60E100BE12FD /* game_variant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A0FFF1BFA60E000BE12FD /* game_variant.cpp */; }; + 9B5A11D11BFA60E100BE12FD /* game_variant_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10001BFA60E000BE12FD /* game_variant_schema.cpp */; }; + 9B5A11D21BFA60E100BE12FD /* quality_of_service_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10011BFA60E000BE12FD /* quality_of_service_server.cpp */; }; + 9B5A11DD1BFA60E100BE12FD /* leaderboard_column.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A101A1BFA60E000BE12FD /* leaderboard_column.cpp */; }; + 9B5A11DE1BFA60E100BE12FD /* leaderboard_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A101C1BFA60E000BE12FD /* leaderboard_result.cpp */; }; + 9B5A11DF1BFA60E100BE12FD /* leaderboard_row.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A101D1BFA60E000BE12FD /* leaderboard_row.cpp */; }; + 9B5A11E01BFA60E100BE12FD /* leaderboard_serializers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A101E1BFA60E000BE12FD /* leaderboard_serializers.cpp */; }; + 9B5A11E11BFA60E100BE12FD /* leaderboard_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10201BFA60E000BE12FD /* leaderboard_service.cpp */; }; + 9B5A11FD1BFA60E100BE12FD /* create_match_ticket_response.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10541BFA60E000BE12FD /* create_match_ticket_response.cpp */; }; + 9B5A11FE1BFA60E100BE12FD /* hopper_statistics_response.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10551BFA60E000BE12FD /* hopper_statistics_response.cpp */; }; + 9B5A11FF1BFA60E100BE12FD /* match_ticket_details_response.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10561BFA60E000BE12FD /* match_ticket_details_response.cpp */; }; + 9B5A12001BFA60E100BE12FD /* matchmaking_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10571BFA60E000BE12FD /* matchmaking_service.cpp */; }; + 9B5A12031BFA60E100BE12FD /* contextual_config_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10621BFA60E000BE12FD /* contextual_config_result.cpp */; }; + 9B5A12041BFA60E100BE12FD /* contextual_search_broadcast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10641BFA60E000BE12FD /* contextual_search_broadcast.cpp */; }; + 9B5A12051BFA60E100BE12FD /* contextual_search_configured_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10651BFA60E000BE12FD /* contextual_search_configured_stat.cpp */; }; + 9B5A12061BFA60E100BE12FD /* contextual_search_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10661BFA60E000BE12FD /* contextual_search_service.cpp */; }; + 9B5A12081BFA60E100BE12FD /* string_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10691BFA60E000BE12FD /* string_service.cpp */; }; + 9B5A120A1BFA60E100BE12FD /* verify_string_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A106B1BFA60E000BE12FD /* verify_string_result.cpp */; }; + 9B5A12391BFA60E100BE12FD /* multiplayer_activity_details.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10BE1BFA60E000BE12FD /* multiplayer_activity_details.cpp */; }; + 9B5A123A1BFA60E100BE12FD /* multiplayer_activity_handle_post_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10BF1BFA60E000BE12FD /* multiplayer_activity_handle_post_request.cpp */; }; + 9B5A123B1BFA60E100BE12FD /* multiplayer_activity_query_post_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C01BFA60E000BE12FD /* multiplayer_activity_query_post_request.cpp */; }; + 9B5A123C1BFA60E100BE12FD /* multiplayer_get_sessions_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C11BFA60E000BE12FD /* multiplayer_get_sessions_request.cpp */; }; + 9B5A123D1BFA60E100BE12FD /* multiplayer_invite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C31BFA60E000BE12FD /* multiplayer_invite.cpp */; }; + 9B5A123E1BFA60E100BE12FD /* multiplayer_invite_handle_post_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C41BFA60E000BE12FD /* multiplayer_invite_handle_post_request.cpp */; }; + 9B5A123F1BFA60E100BE12FD /* multiplayer_managed_initialization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C51BFA60E000BE12FD /* multiplayer_managed_initialization.cpp */; }; + 9B5A12401BFA60E100BE12FD /* multiplayer_peer_to_host_requirements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C61BFA60E000BE12FD /* multiplayer_peer_to_host_requirements.cpp */; }; + 9B5A12411BFA60E100BE12FD /* multiplayer_peer_to_peer_requirements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C71BFA60E000BE12FD /* multiplayer_peer_to_peer_requirements.cpp */; }; + 9B5A12421BFA60E100BE12FD /* multiplayer_quality_of_service_measurement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C81BFA60E000BE12FD /* multiplayer_quality_of_service_measurement.cpp */; }; + 9B5A12431BFA60E100BE12FD /* multiplayer_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10C91BFA60E000BE12FD /* multiplayer_service.cpp */; }; + 9B5A12441BFA60E100BE12FD /* multiplayer_service_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10CA1BFA60E000BE12FD /* multiplayer_service_impl.cpp */; }; + 9B5A12451BFA60E100BE12FD /* multiplayer_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10CB1BFA60E000BE12FD /* multiplayer_session.cpp */; }; + 9B5A12461BFA60E100BE12FD /* multiplayer_session_capabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10CC1BFA60E000BE12FD /* multiplayer_session_capabilities.cpp */; }; + 9B5A12471BFA60E100BE12FD /* multiplayer_session_change_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10CD1BFA60E000BE12FD /* multiplayer_session_change_event_args.cpp */; }; + 9B5A12481BFA60E100BE12FD /* multiplayer_session_constants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10CE1BFA60E000BE12FD /* multiplayer_session_constants.cpp */; }; + 9B5A12491BFA60E100BE12FD /* multiplayer_session_matchmaking_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10CF1BFA60E000BE12FD /* multiplayer_session_matchmaking_server.cpp */; }; + 9B5A124A1BFA60E100BE12FD /* multiplayer_session_member.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D01BFA60E000BE12FD /* multiplayer_session_member.cpp */; }; + 9B5A124B1BFA60E100BE12FD /* multiplayer_session_member_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D11BFA60E000BE12FD /* multiplayer_session_member_request.cpp */; }; + 9B5A124C1BFA60E100BE12FD /* multiplayer_session_properties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D21BFA60E000BE12FD /* multiplayer_session_properties.cpp */; }; + 9B5A124D1BFA60E100BE12FD /* multiplayer_session_reference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D31BFA60E000BE12FD /* multiplayer_session_reference.cpp */; }; + 9B5A124E1BFA60E100BE12FD /* multiplayer_session_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D41BFA60E000BE12FD /* multiplayer_session_request.cpp */; }; + 9B5A124F1BFA60E100BE12FD /* multiplayer_session_states.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D51BFA60E000BE12FD /* multiplayer_session_states.cpp */; }; + 9B5A12501BFA60E100BE12FD /* multiplayer_subscription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D61BFA60E000BE12FD /* multiplayer_subscription.cpp */; }; + 9B5A12511BFA60E100BE12FD /* multiplayer_transfer_handle_post_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A10D71BFA60E000BE12FD /* multiplayer_transfer_handle_post_request.cpp */; }; + 9B5A12641BFA60E100BE12FD /* device_presence_change_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A110A1BFA60E000BE12FD /* device_presence_change_event_args.cpp */; }; + 9B5A12651BFA60E100BE12FD /* device_presence_change_subscription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A110B1BFA60E000BE12FD /* device_presence_change_subscription.cpp */; }; + 9B5A12661BFA60E100BE12FD /* media_presence_data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A110C1BFA60E000BE12FD /* media_presence_data.cpp */; }; + 9B5A12671BFA60E100BE12FD /* presence_activity_data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A110D1BFA60E000BE12FD /* presence_activity_data.cpp */; }; + 9B5A12681BFA60E100BE12FD /* presence_broadcast_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A110E1BFA60E000BE12FD /* presence_broadcast_record.cpp */; }; + 9B5A12691BFA60E100BE12FD /* presence_data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A110F1BFA60E000BE12FD /* presence_data.cpp */; }; + 9B5A126A1BFA60E100BE12FD /* presence_device_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11101BFA60E000BE12FD /* presence_device_record.cpp */; }; + 9B5A126B1BFA60E100BE12FD /* presence_media_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11121BFA60E000BE12FD /* presence_media_record.cpp */; }; + 9B5A126C1BFA60E100BE12FD /* presence_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11131BFA60E000BE12FD /* presence_record.cpp */; }; + 9B5A126D1BFA60E100BE12FD /* presence_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11141BFA60E000BE12FD /* presence_service.cpp */; }; + 9B5A126E1BFA60E100BE12FD /* presence_service_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11151BFA60E000BE12FD /* presence_service_impl.cpp */; }; + 9B5A126F1BFA60E100BE12FD /* presence_title_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11161BFA60E000BE12FD /* presence_title_record.cpp */; }; + 9B5A12701BFA60E100BE12FD /* presence_title_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11171BFA60E000BE12FD /* presence_title_request.cpp */; }; + 9B5A12711BFA60E100BE12FD /* presence_user_batch_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11181BFA60E000BE12FD /* presence_user_batch_request.cpp */; }; + 9B5A12721BFA60E100BE12FD /* presence_writer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11191BFA60E000BE12FD /* presence_writer.cpp */; }; + 9B5A12731BFA60E100BE12FD /* title_presence_change_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A111A1BFA60E000BE12FD /* title_presence_change_event_args.cpp */; }; + 9B5A12741BFA60E100BE12FD /* title_presence_change_subscription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A111B1BFA60E000BE12FD /* title_presence_change_subscription.cpp */; }; + 9B5A12801BFA60E100BE12FD /* multiple_permissions_check_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A113A1BFA60E000BE12FD /* multiple_permissions_check_result.cpp */; }; + 9B5A12811BFA60E100BE12FD /* permission_check_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A113B1BFA60E000BE12FD /* permission_check_result.cpp */; }; + 9B5A12821BFA60E100BE12FD /* permission_deny_reason.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A113C1BFA60E000BE12FD /* permission_deny_reason.cpp */; }; + 9B5A12831BFA60E100BE12FD /* privacy_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A113D1BFA60E000BE12FD /* privacy_service.cpp */; }; + 9B5A12891BFA60E100BE12FD /* real_time_activity_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A114A1BFA60E000BE12FD /* real_time_activity_service.cpp */; }; + 9B5A128A1BFA60E100BE12FD /* real_time_activity_subscription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A114B1BFA60E000BE12FD /* real_time_activity_subscription.cpp */; }; + 9B5A128B1BFA60E100BE12FD /* real_time_activity_subscription_error_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A114C1BFA60E000BE12FD /* real_time_activity_subscription_error_event_args.cpp */; }; + 9B5A129D1BFA60E100BE12FD /* profile_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11711BFA60E000BE12FD /* profile_service.cpp */; }; + 9B5A129E1BFA60E100BE12FD /* reputation_feedback_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11721BFA60E000BE12FD /* reputation_feedback_request.cpp */; }; + 9B5A129F1BFA60E100BE12FD /* reputation_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11731BFA60E000BE12FD /* reputation_service.cpp */; }; + 9B5A12A01BFA60E100BE12FD /* social_relationship_change_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11751BFA60E000BE12FD /* social_relationship_change_event_args.cpp */; }; + 9B5A12A11BFA60E100BE12FD /* social_relationship_change_subscription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11761BFA60E000BE12FD /* social_relationship_change_subscription.cpp */; }; + 9B5A12A21BFA60E100BE12FD /* social_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11771BFA60E000BE12FD /* social_service.cpp */; }; + 9B5A12A31BFA60E100BE12FD /* social_service_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11781BFA60E000BE12FD /* social_service_impl.cpp */; }; + 9B5A12AC1BFA60E100BE12FD /* xbox_social_relationship.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11911BFA60E000BE12FD /* xbox_social_relationship.cpp */; }; + 9B5A12AD1BFA60E100BE12FD /* xbox_social_relationship_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11921BFA60E000BE12FD /* xbox_social_relationship_result.cpp */; }; + 9B5A12AE1BFA60E100BE12FD /* xbox_user_profile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11931BFA60E000BE12FD /* xbox_user_profile.cpp */; }; + 9B5A12AF1BFA60E100BE12FD /* requested_statistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11951BFA60E000BE12FD /* requested_statistics.cpp */; }; + 9B5A12B01BFA60E100BE12FD /* service_configuration_statistic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11961BFA60E000BE12FD /* service_configuration_statistic.cpp */; }; + 9B5A12B11BFA60E100BE12FD /* statistic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11971BFA60E100BE12FD /* statistic.cpp */; }; + 9B5A12B21BFA60E100BE12FD /* statistic_change_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11981BFA60E100BE12FD /* statistic_change_event_args.cpp */; }; + 9B5A12B31BFA60E100BE12FD /* statistic_change_subscription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11991BFA60E100BE12FD /* statistic_change_subscription.cpp */; }; + 9B5A12B41BFA60E100BE12FD /* user_statistics_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A119B1BFA60E100BE12FD /* user_statistics_result.cpp */; }; + 9B5A12B51BFA60E100BE12FD /* user_statistics_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A119C1BFA60E100BE12FD /* user_statistics_service.cpp */; }; + 9B5A12B61BFA60E100BE12FD /* user_statistics_service_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A119D1BFA60E100BE12FD /* user_statistics_service_impl.cpp */; }; + 9B5A12BE1BFA60E100BE12FD /* title_storage_blob_metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11AE1BFA60E100BE12FD /* title_storage_blob_metadata.cpp */; }; + 9B5A12BF1BFA60E100BE12FD /* title_storage_blob_metadata_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11AF1BFA60E100BE12FD /* title_storage_blob_metadata_result.cpp */; }; + 9B5A12C01BFA60E100BE12FD /* title_storage_blob_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11B01BFA60E100BE12FD /* title_storage_blob_result.cpp */; }; + 9B5A12C11BFA60E100BE12FD /* title_storage_quota.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11B11BFA60E100BE12FD /* title_storage_quota.cpp */; }; + 9B5A12C21BFA60E100BE12FD /* title_storage_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A11B21BFA60E100BE12FD /* title_storage_service.cpp */; }; + 9B5A12CB1BFBF63600BE12FD /* pch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A12C91BFBF63600BE12FD /* pch.cpp */; }; + 9B5A12F51BFD2BF200BE12FD /* tournament_team_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B5A12D31BFD2BF200BE12FD /* tournament_team_result.cpp */; }; + 9B82502E1C1A40DF002C8F30 /* multiplayer_session_arbitration_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B82502C1C1A397F002C8F30 /* multiplayer_session_arbitration_server.cpp */; }; + 9B8250321C1A4A8F002C8F30 /* multiplayer_session_tournaments_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B8250311C1A4A8F002C8F30 /* multiplayer_session_tournaments_server.cpp */; }; + 9B8250341C1A4B34002C8F30 /* tournament_reference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B8250331C1A4B34002C8F30 /* tournament_reference.cpp */; }; + 9B847EB31CDD2823004E04B0 /* notification_service_i.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B847EB11CDD2823004E04B0 /* notification_service_i.mm */; }; + 9B847EB61CDD6928004E04B0 /* notification_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B847EB51CDD6928004E04B0 /* notification_service.cpp */; }; + 9B8A00B11BF2778B000337EA /* sign_in_delegate_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B8A00B01BF2778B000337EA /* sign_in_delegate_ios.mm */; }; + 9B9615E51BEA86FE00E79527 /* XboxLiveContext_Desktop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B9615E21BEA86FE00E79527 /* XboxLiveContext_Desktop.cpp */; }; + 9B97B7301BE1981B00CF1E29 /* errors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5971BE1981900CF1E29 /* errors.cpp */; }; + 9B97B7311BE1981B00CF1E29 /* http_call_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5981BE1981900CF1E29 /* http_call_impl.cpp */; }; + 9B97B7321BE1981B00CF1E29 /* http_call_request_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B59A1BE1981900CF1E29 /* http_call_request_message.cpp */; }; + 9B97B7331BE1981B00CF1E29 /* http_call_response.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B59B1BE1981900CF1E29 /* http_call_response.cpp */; }; + 9B97B7341BE1981B00CF1E29 /* http_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B59D1BE1981900CF1E29 /* http_client.cpp */; }; + 9B97B7351BE1981B00CF1E29 /* local_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B59F1BE1981900CF1E29 /* local_config.cpp */; }; + 9B97B7361BE1981B00CF1E29 /* service_call_logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5A11BE1981900CF1E29 /* service_call_logger.cpp */; }; + 9B97B7371BE1981B00CF1E29 /* service_call_logger_data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5A31BE1981900CF1E29 /* service_call_logger_data.cpp */; }; + 9B97B7391BE1981B00CF1E29 /* service_call_logging_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5A71BE1981900CF1E29 /* service_call_logging_config.cpp */; }; + 9B97B73A1BE1981B00CF1E29 /* telemetry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5A91BE1981900CF1E29 /* telemetry.cpp */; }; + 9B97B73B1BE1981B00CF1E29 /* user_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5AB1BE1981900CF1E29 /* user_context.cpp */; }; + 9B97B73C1BE1981B00CF1E29 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5AD1BE1981900CF1E29 /* utils.cpp */; }; + 9B97B73D1BE1981B00CF1E29 /* utils_locales.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5AF1BE1981900CF1E29 /* utils_locales.cpp */; }; + 9B97B73E1BE1981B00CF1E29 /* web_socket_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5B01BE1981900CF1E29 /* web_socket_client.cpp */; }; + 9B97B73F1BE1981B00CF1E29 /* web_socket_connection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5B21BE1981900CF1E29 /* web_socket_connection.cpp */; }; + 9B97B7481BE1981B00CF1E29 /* xbox_live_app_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5C81BE1981900CF1E29 /* xbox_live_app_config.cpp */; }; + 9B97B7491BE1981B00CF1E29 /* xbox_live_context_settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5C91BE1981900CF1E29 /* xbox_live_context_settings.cpp */; }; + 9B97B74A1BE1981B00CF1E29 /* xbox_service_call_routed_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5CA1BE1981900CF1E29 /* xbox_service_call_routed_event_args.cpp */; }; + 9B97B74B1BE1981B00CF1E29 /* xbox_system_factory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5CB1BE1981900CF1E29 /* xbox_system_factory.cpp */; }; + 9B97B74C1BE1981B00CF1E29 /* auth_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5CF1BE1981900CF1E29 /* auth_manager.cpp */; }; + 9B97B74D1BE1981B00CF1E29 /* cidr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5D11BE1981900CF1E29 /* cidr.cpp */; }; + 9B97B7531BE1981B00CF1E29 /* ip_address.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5DC1BE1981900CF1E29 /* ip_address.cpp */; }; + 9B97B7541BE1981B00CF1E29 /* json_web_key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5DE1BE1981900CF1E29 /* json_web_key.cpp */; }; + 9B97B7551BE1981B00CF1E29 /* nsal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5E01BE1981900CF1E29 /* nsal.cpp */; }; + 9B97B7561BE1981B00CF1E29 /* nsal_endpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5E21BE1981900CF1E29 /* nsal_endpoint.cpp */; }; + 9B97B7571BE1981B00CF1E29 /* request_signer_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5E51BE1981900CF1E29 /* request_signer_helpers.cpp */; }; + 9B97B7591BE1981B00CF1E29 /* signature_policy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5E91BE1981900CF1E29 /* signature_policy.cpp */; }; + 9B97B75A1BE1981B00CF1E29 /* title_token_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5EB1BE1981900CF1E29 /* title_token_service.cpp */; }; + 9B97B75B1BE1981B00CF1E29 /* token_error.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5ED1BE1981900CF1E29 /* token_error.cpp */; }; + 9B97B75C1BE1981B00CF1E29 /* token_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5EF1BE1981900CF1E29 /* token_manager.cpp */; }; + 9B97B75D1BE1981B00CF1E29 /* token_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5F11BE1981900CF1E29 /* token_request.cpp */; }; + 9B97B75E1BE1981B00CF1E29 /* token_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5F31BE1981900CF1E29 /* token_result.cpp */; }; + 9B97B75F1BE1981B00CF1E29 /* trie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5F51BE1981900CF1E29 /* trie.cpp */; }; + 9B97B7601BE1981C00CF1E29 /* user_token_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5F71BE1981900CF1E29 /* user_token_service.cpp */; }; + 9B97B7631BE1981C00CF1E29 /* xsts_token_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5FC1BE1981900CF1E29 /* xsts_token_service.cpp */; }; + 9B97B7641BE1981C00CF1E29 /* xtitle_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B5FE1BE1981900CF1E29 /* xtitle_service.cpp */; }; + 9B97B7651BE1981C00CF1E29 /* auth_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B6001BE1981900CF1E29 /* auth_config.cpp */; }; + 9B97B7661BE1981C00CF1E29 /* token_and_signature_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B6031BE1981900CF1E29 /* token_and_signature_result.cpp */; }; + 9B97B7671BE1981C00CF1E29 /* user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B6041BE1981900CF1E29 /* user.cpp */; }; + 9B97B7681BE1981C00CF1E29 /* user_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B6051BE1981900CF1E29 /* user_impl.cpp */; }; + 9B97B76D1BE1981C00CF1E29 /* xbox_live_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B6101BE1981900CF1E29 /* xbox_live_mutex.cpp */; }; + 9B97B9AD1BE19DFD00CF1E29 /* xbox_live_context_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97B7BB1BE19DFC00CF1E29 /* xbox_live_context_impl.cpp */; }; + 9BAEFDE91D3019A300ABBA82 /* multiplayer_match_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAEFDE81D3019A300ABBA82 /* multiplayer_match_client.cpp */; }; + 9BAEFDEC1D3019B300ABBA82 /* multiplayer_search_handle_details.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAEFDEA1D3019B300ABBA82 /* multiplayer_search_handle_details.cpp */; }; + 9BAEFDED1D3019B300ABBA82 /* multiplayer_search_handle_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAEFDEB1D3019B300ABBA82 /* multiplayer_search_handle_request.cpp */; }; + 9BAEFDF01D30263F00ABBA82 /* initiator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAEFDEE1D30263F00ABBA82 /* initiator.cpp */; }; + 9BBAB7781CBDE09000A75EDF /* local_config_u.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BBAB7771CBDE09000A75EDF /* local_config_u.cpp */; }; + 9BBAB79D1CC0408200A75EDF /* local_config_i.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BBAB79C1CC0408200A75EDF /* local_config_i.mm */; }; + 9BEB14FA1DCD01BF001E5DD5 /* multiplayer_member_initialization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BEB14F91DCD01BF001E5DD5 /* multiplayer_member_initialization.cpp */; }; + 9BF11AD11C12076E00D111C9 /* big_num.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF11ACC1C12076E00D111C9 /* big_num.cpp */; }; + 9BF11AD21C12076E00D111C9 /* request_signer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF11ACE1C12076E00D111C9 /* request_signer.cpp */; }; + 9BF11AD31C12076E00D111C9 /* sha256.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF11ACF1C12076E00D111C9 /* sha256.cpp */; }; + 9BF11ADF1C120C2900D111C9 /* ip_address_desktop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF11AD91C120C2900D111C9 /* ip_address_desktop.cpp */; }; + 9BF132431C3C48230048204E /* device_token_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF132411C3C48230048204E /* device_token_service.cpp */; }; + 9BF639381D492C3300BDF02B /* contextual_search_game_clip_stat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF639331D492C3300BDF02B /* contextual_search_game_clip_stat.cpp */; }; + 9BF639391D492C3300BDF02B /* contextual_search_game_clip_thumbnail.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF639341D492C3300BDF02B /* contextual_search_game_clip_thumbnail.cpp */; }; + 9BF6393A1D492C3300BDF02B /* contextual_search_game_clip_uri_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF639351D492C3300BDF02B /* contextual_search_game_clip_uri_info.cpp */; }; + 9BF6393B1D492C3300BDF02B /* contextual_search_game_clip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF639361D492C3300BDF02B /* contextual_search_game_clip.cpp */; }; + 9BF6393C1D492C3300BDF02B /* contextual_search_game_clips_result.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BF639371D492C3300BDF02B /* contextual_search_game_clips_result.cpp */; }; + 9C063B121D774C28009C3E3C /* mem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9C063B111D774C28009C3E3C /* mem.cpp */; }; + 9CB56C061DA359BB00C92F44 /* multiplayer_query_search_handle_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CB56C051DA359BB00C92F44 /* multiplayer_query_search_handle_request.cpp */; }; + 9CB56C081DA35A4500C92F44 /* xbox_live_services_settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CB56C071DA35A4500C92F44 /* xbox_live_services_settings.cpp */; }; + 9CB56C0B1DA35AA800C92F44 /* custom_output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CB56C091DA35AA800C92F44 /* custom_output.cpp */; }; + 9CC36FE31DB6DE89007142EE /* xbox_user_id_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CC36FE21DB6DE89007142EE /* xbox_user_id_container.cpp */; }; + 9CDF0D361DA2E8860046C721 /* internal_social_event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D291DA2E8860046C721 /* internal_social_event.cpp */; }; + 9CDF0D371DA2E8860046C721 /* peoplehub_service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D2A1DA2E8860046C721 /* peoplehub_service.cpp */; }; + 9CDF0D381DA2E8860046C721 /* preferred_color.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D2B1DA2E8860046C721 /* preferred_color.cpp */; }; + 9CDF0D391DA2E8860046C721 /* social_event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D2C1DA2E8860046C721 /* social_event.cpp */; }; + 9CDF0D3A1DA2E8860046C721 /* social_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D2D1DA2E8860046C721 /* social_graph.cpp */; }; + 9CDF0D3B1DA2E8860046C721 /* social_manager_presence_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D2F1DA2E8860046C721 /* social_manager_presence_record.cpp */; }; + 9CDF0D3C1DA2E8860046C721 /* social_manager_presence_title_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D301DA2E8860046C721 /* social_manager_presence_title_record.cpp */; }; + 9CDF0D3D1DA2E8860046C721 /* social_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D311DA2E8860046C721 /* social_manager.cpp */; }; + 9CDF0D3E1DA2E8860046C721 /* social_user_group_loaded_event_args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D321DA2E8860046C721 /* social_user_group_loaded_event_args.cpp */; }; + 9CDF0D3F1DA2E8860046C721 /* title_history.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D331DA2E8860046C721 /* title_history.cpp */; }; + 9CDF0D401DA2E8860046C721 /* xbox_social_user_group.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D341DA2E8860046C721 /* xbox_social_user_group.cpp */; }; + 9CDF0D411DA2E8860046C721 /* xbox_social_user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CDF0D351DA2E8860046C721 /* xbox_social_user.cpp */; }; + B71305821CC7477A00A4E71E /* XLSCll.mm in Sources */ = {isa = PBXBuildFile; fileRef = B71305811CC7477A00A4E71E /* XLSCll.mm */; }; + B7E5C76D1CEED3E5003B2B08 /* UTCIDPNames.mm in Sources */ = {isa = PBXBuildFile; fileRef = B7E5C76C1CEED3E5003B2B08 /* UTCIDPNames.mm */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 671121B61CBD960100F49259 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6718F1881CB731EF0000BF6E /* XSAPITCUI.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 6718F1741CB730BD0000BF6E; + remoteInfo = XSAPITCUI; + }; + 6781BDB21CBC702100264EAF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6718F1881CB731EF0000BF6E /* XSAPITCUI.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 6718F1751CB730BD0000BF6E; + remoteInfo = XSAPITCUI; + }; + 9B66D2D01BE85B5C00E53086 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9B66D2CC1BE85B5C00E53086 /* Casablanca.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9B97BAE11BE29EAF00CF1E29; + remoteInfo = Casablanca; + }; + 9B82502F1C1A46B7002C8F30 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9B66D2CC1BE85B5C00E53086 /* Casablanca.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 9B97BAE01BE29EAF00CF1E29; + remoteInfo = Casablanca; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9B97B3591BE18B2600CF1E29 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = include/$PRODUCT_NAME; + dstSubfolderSpec = 16; + files = ( + 671F66DB1CD43A0000119106 /* multiplayer.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 251DBDD61CE6DE41003AF56B /* utils_locales_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = utils_locales_ios.mm; path = i/utils_locales_ios.mm; sourceTree = ""; }; + 255A36A61CD8353B00D3AD8E /* find_match_completed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = find_match_completed_event_args.cpp; path = Manager/find_match_completed_event_args.cpp; sourceTree = ""; }; + 255A36A71CD8353B00D3AD8E /* host_changed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = host_changed_event_args.cpp; path = Manager/host_changed_event_args.cpp; sourceTree = ""; }; + 255A36A81CD8353B00D3AD8E /* join_lobby_completed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = join_lobby_completed_event_args.cpp; path = Manager/join_lobby_completed_event_args.cpp; sourceTree = ""; }; + 255A36AA1CD8353B00D3AD8E /* member_joined_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = member_joined_event_args.cpp; path = Manager/member_joined_event_args.cpp; sourceTree = ""; }; + 255A36AB1CD8353B00D3AD8E /* member_left_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = member_left_event_args.cpp; path = Manager/member_left_event_args.cpp; sourceTree = ""; }; + 255A36AC1CD8353B00D3AD8E /* member_property_changed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = member_property_changed_event_args.cpp; path = Manager/member_property_changed_event_args.cpp; sourceTree = ""; }; + 255A36AD1CD8353B00D3AD8E /* multiplayer_client_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_client_manager.cpp; path = Manager/multiplayer_client_manager.cpp; sourceTree = ""; }; + 255A36AE1CD8353B00D3AD8E /* multiplayer_client_pending_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_client_pending_reader.cpp; path = Manager/multiplayer_client_pending_reader.cpp; sourceTree = ""; }; + 255A36AF1CD8353B00D3AD8E /* multiplayer_client_pending_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_client_pending_request.cpp; path = Manager/multiplayer_client_pending_request.cpp; sourceTree = ""; }; + 255A36B01CD8353B00D3AD8E /* multiplayer_event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_event.cpp; path = Manager/multiplayer_event.cpp; sourceTree = ""; }; + 255A36B11CD8353B00D3AD8E /* multiplayer_game_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_game_client.cpp; path = Manager/multiplayer_game_client.cpp; sourceTree = ""; }; + 255A36B21CD8353B00D3AD8E /* multiplayer_game_session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_game_session.cpp; path = Manager/multiplayer_game_session.cpp; sourceTree = ""; }; + 255A36B31CD8353B00D3AD8E /* multiplayer_lobby_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_lobby_client.cpp; path = Manager/multiplayer_lobby_client.cpp; sourceTree = ""; }; + 255A36B41CD8353B00D3AD8E /* multiplayer_lobby_session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_lobby_session.cpp; path = Manager/multiplayer_lobby_session.cpp; sourceTree = ""; }; + 255A36B51CD8353B00D3AD8E /* multiplayer_local_user_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_local_user_manager.cpp; path = Manager/multiplayer_local_user_manager.cpp; sourceTree = ""; }; + 255A36B61CD8353B00D3AD8E /* multiplayer_local_user.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_local_user.cpp; path = Manager/multiplayer_local_user.cpp; sourceTree = ""; }; + 255A36B71CD8353B00D3AD8E /* multiplayer_manager_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = multiplayer_manager_internal.h; path = Manager/multiplayer_manager_internal.h; sourceTree = ""; }; + 255A36B81CD8353B00D3AD8E /* multiplayer_manager_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_manager_utils.cpp; path = Manager/multiplayer_manager_utils.cpp; sourceTree = ""; }; + 255A36B91CD8353B00D3AD8E /* multiplayer_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_manager.cpp; path = Manager/multiplayer_manager.cpp; sourceTree = ""; }; + 255A36BA1CD8353B00D3AD8E /* multiplayer_member.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_member.cpp; path = Manager/multiplayer_member.cpp; sourceTree = ""; }; + 255A36BB1CD8353B00D3AD8E /* multiplayer_session_writer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_session_writer.cpp; path = Manager/multiplayer_session_writer.cpp; sourceTree = ""; }; + 255A36BC1CD8353B00D3AD8E /* perform_qos_measurements_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = perform_qos_measurements_event_args.cpp; path = Manager/perform_qos_measurements_event_args.cpp; sourceTree = ""; }; + 255A36BD1CD8353B00D3AD8E /* session_property_changed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = session_property_changed_event_args.cpp; path = Manager/session_property_changed_event_args.cpp; sourceTree = ""; }; + 255A36BE1CD8353B00D3AD8E /* tournament_game_session_ready_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tournament_game_session_ready_event_args.cpp; path = Manager/tournament_game_session_ready_event_args.cpp; sourceTree = ""; }; + 255A36BF1CD8353B00D3AD8E /* tournament_registration_state_changed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tournament_registration_state_changed_event_args.cpp; path = Manager/tournament_registration_state_changed_event_args.cpp; sourceTree = ""; }; + 255A36C01CD8353B00D3AD8E /* user_added_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = user_added_event_args.cpp; path = Manager/user_added_event_args.cpp; sourceTree = ""; }; + 255A36C11CD8353B00D3AD8E /* user_removed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = user_removed_event_args.cpp; path = Manager/user_removed_event_args.cpp; sourceTree = ""; }; + 255A36C21CD8353B00D3AD8E /* WinRT */ = {isa = PBXFileReference; lastKnownFileType = folder; name = WinRT; path = Manager/WinRT; sourceTree = ""; }; + 32F5FBBE1CE7DB1D008A5E09 /* title_callable_ui.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = title_callable_ui.mm; path = iOS/title_callable_ui.mm; sourceTree = ""; }; + 670AA2F51C7657D300B3FB9A /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 6718D8AE1C865AD0007FD4F6 /* XboxProviderBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XboxProviderBridge.cpp; sourceTree = ""; }; + 6718D8AF1C865AD0007FD4F6 /* XboxProviderBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XboxProviderBridge.h; sourceTree = ""; }; + 6718D8B51C86605E007FD4F6 /* XBLSignInHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBLSignInHandler.h; sourceTree = ""; }; + 6718D8B61C86605E007FD4F6 /* XBLSignInHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = XBLSignInHandler.mm; sourceTree = ""; }; + 6718D9151C9F69CA007FD4F6 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; + 6718F1881CB731EF0000BF6E /* XSAPITCUI.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = XSAPITCUI.xcodeproj; path = ../../External/TCUI/iOS/XSAPITCUI.xcodeproj; sourceTree = ""; }; + 6718F1BF1CB76BF50000BF6E /* XBLServiceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBLServiceManager.h; sourceTree = ""; }; + 6718F1C01CB76BF50000BF6E /* XBLServiceManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = XBLServiceManager.mm; sourceTree = ""; }; + 6718F1E31CB77FEB0000BF6E /* XBLDictionaryToJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBLDictionaryToJSON.h; sourceTree = ""; }; + 6718F1E41CB77FEB0000BF6E /* XBLDictionaryToJSON.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = XBLDictionaryToJSON.mm; sourceTree = ""; }; + 671F66D21CD439BC00119106 /* marketplace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = marketplace.h; sourceTree = ""; }; + 671F66D41CD439BC00119106 /* social_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = social_manager.h; sourceTree = ""; }; + 671F66D51CD439BC00119106 /* xbox_live_app_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_live_app_config.h; sourceTree = ""; }; + 67210E241C6479E20008FFDB /* NSError+XSAPIExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+XSAPIExtensions.h"; sourceTree = ""; }; + 67210E251C6479E20008FFDB /* NSError+XSAPIExtensions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSError+XSAPIExtensions.mm"; sourceTree = ""; }; + 67210E261C6479E20008FFDB /* XboxProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XboxProvider.h; sourceTree = ""; }; + 67210E271C6479E20008FFDB /* XboxProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = XboxProvider.mm; sourceTree = ""; }; + 677B9FCB1CD90F2900A28F96 /* XBLiOSGlobalState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBLiOSGlobalState.h; sourceTree = ""; }; + 677B9FCC1CD90F2900A28F96 /* XBLiOSGlobalState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = XBLiOSGlobalState.mm; sourceTree = ""; }; + 67A963871C5FE4250066184E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 67F503A31CD98D8E00198DEA /* xbox_live_app_config_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = xbox_live_app_config_ios.mm; sourceTree = ""; }; + 9B118A921D4BFF070068B268 /* multiplayer_role_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_role_info.cpp; sourceTree = ""; }; + 9B118A931D4BFF070068B268 /* multiplayer_role_type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_role_type.cpp; sourceTree = ""; }; + 9B118A941D4BFF070068B268 /* multiplayer_session_role_types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_role_types.cpp; sourceTree = ""; }; + 9B118ABC1D6BC12E0068B268 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; + 9B118ABD1D6D0AFF0068B268 /* debug_output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_output.h; sourceTree = ""; }; + 9B118AC11D6D0B460068B268 /* debug_output_ios.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = debug_output_ios.cpp; path = iOS/debug_output_ios.cpp; sourceTree = ""; }; + 9B118AD91D885FA80068B268 /* user_auth_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = user_auth_ios.h; path = auth/user_auth_ios.h; sourceTree = ""; }; + 9B118ADA1D885FA80068B268 /* user_auth_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = user_auth_ios.mm; path = auth/user_auth_ios.mm; sourceTree = ""; }; + 9B118ADF1D8B35230068B268 /* user_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_impl_ios.h; sourceTree = ""; }; + 9B118AE01D8B35230068B268 /* user_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = user_impl_ios.mm; sourceTree = ""; }; + 9B2956101CE244CD0026A41C /* xbox_cll.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = xbox_cll.mm; sourceTree = ""; }; + 9B2956111CE244CD0026A41C /* xbox_cll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_cll.h; sourceTree = ""; }; + 9B2956141CE247490026A41C /* events_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = events_service.cpp; sourceTree = ""; }; + 9B46ED441BED41D600076704 /* ecdsa_unix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ecdsa_unix.cpp; sourceTree = ""; }; + 9B46ED451BED41D600076704 /* ip_address_unix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ip_address_unix.cpp; sourceTree = ""; }; + 9B46ED4D1BED720E00076704 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 9B46ED501BF105A000076704 /* xbox_system_factory_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = xbox_system_factory_ios.mm; sourceTree = ""; }; + 9B46ED541BF14AFA00076704 /* user_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = user_ios.mm; sourceTree = ""; }; + 9B4933F91CE8F29E00E7CE0B /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 9B4934761CEE1C0A00E7CE0B /* notification_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notification_helper.h; sourceTree = ""; }; + 9B4934781CEE1C1800E7CE0B /* notification_helper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = notification_helper.mm; path = iOS/notification_helper.mm; sourceTree = ""; }; + 9B4B449F1D2F22C30060F1C5 /* real_time_activity_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = real_time_activity_internal.h; sourceTree = ""; }; + 9B4B44A01D2F22C30060F1C5 /* real_time_activity_service_factory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = real_time_activity_service_factory.cpp; sourceTree = ""; }; + 9B4B44A91D2F2D4C0060F1C5 /* log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cpp; sourceTree = ""; }; + 9B4B44AB1D2F2D4C0060F1C5 /* log_entry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log_entry.cpp; sourceTree = ""; }; + 9B4B44AC1D2F2D4C0060F1C5 /* log_output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log_output.cpp; sourceTree = ""; }; + 9B4B44D11D2FFE850060F1C5 /* multiplayer_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multiplayer_manager.h; sourceTree = ""; }; + 9B5A0FB61BFA603A00BE12FD /* achievement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement.cpp; sourceTree = ""; }; + 9B5A0FB71BFA603A00BE12FD /* achievement_media_asset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_media_asset.cpp; sourceTree = ""; }; + 9B5A0FB81BFA603A00BE12FD /* achievement_progression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_progression.cpp; sourceTree = ""; }; + 9B5A0FB91BFA603A00BE12FD /* achievement_requirement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_requirement.cpp; sourceTree = ""; }; + 9B5A0FBA1BFA603A00BE12FD /* achievement_reward.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_reward.cpp; sourceTree = ""; }; + 9B5A0FBB1BFA603A00BE12FD /* achievement_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_service.cpp; sourceTree = ""; }; + 9B5A0FBC1BFA603A00BE12FD /* achievement_time_window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_time_window.cpp; sourceTree = ""; }; + 9B5A0FBD1BFA603A00BE12FD /* achievement_title_association.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievement_title_association.cpp; sourceTree = ""; }; + 9B5A0FBE1BFA603A00BE12FD /* achievements_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = achievements_result.cpp; sourceTree = ""; }; + 9B5A0FE81BFA60E000BE12FD /* entertainment_profile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = entertainment_profile.cpp; sourceTree = ""; }; + 9B5A0FE91BFA60E000BE12FD /* entertainment_profile_list_contains_item_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = entertainment_profile_list_contains_item_result.cpp; sourceTree = ""; }; + 9B5A0FEA1BFA60E000BE12FD /* entertainment_profile_list_xbox_one_pins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = entertainment_profile_list_xbox_one_pins.cpp; sourceTree = ""; }; + 9B5A0FEC1BFA60E000BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EntertainmentProfileListContainsItemResult_WinRT.cpp; sourceTree = ""; }; + 9B5A0FED1BFA60E000BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EntertainmentProfileListContainsItemResult_WinRT.h; sourceTree = ""; }; + 9B5A0FEE1BFA60E000BE12FD /* EntertainmentProfileListService_WinRT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EntertainmentProfileListService_WinRT.cpp; sourceTree = ""; }; + 9B5A0FEF1BFA60E000BE12FD /* EntertainmentProfileListService_WinRT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EntertainmentProfileListService_WinRT.h; sourceTree = ""; }; + 9B5A0FF01BFA60E000BE12FD /* EntertainmentProfileListVideoQueue_WinRT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EntertainmentProfileListVideoQueue_WinRT.cpp; sourceTree = ""; }; + 9B5A0FF11BFA60E000BE12FD /* EntertainmentProfileListVideoQueue_WinRT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EntertainmentProfileListVideoQueue_WinRT.h; sourceTree = ""; }; + 9B5A0FF81BFA60E000BE12FD /* allocation_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = allocation_result.cpp; sourceTree = ""; }; + 9B5A0FF91BFA60E000BE12FD /* cluster_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cluster_result.cpp; sourceTree = ""; }; + 9B5A0FFA1BFA60E000BE12FD /* game_server_image_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_server_image_set.cpp; sourceTree = ""; }; + 9B5A0FFB1BFA60E000BE12FD /* game_server_metadata_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_server_metadata_result.cpp; sourceTree = ""; }; + 9B5A0FFC1BFA60E000BE12FD /* game_server_platform_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_server_platform_service.cpp; sourceTree = ""; }; + 9B5A0FFD1BFA60E000BE12FD /* game_server_port_mapping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_server_port_mapping.cpp; sourceTree = ""; }; + 9B5A0FFE1BFA60E000BE12FD /* game_server_ticket_status.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_server_ticket_status.cpp; sourceTree = ""; }; + 9B5A0FFF1BFA60E000BE12FD /* game_variant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_variant.cpp; sourceTree = ""; }; + 9B5A10001BFA60E000BE12FD /* game_variant_schema.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_variant_schema.cpp; sourceTree = ""; }; + 9B5A10011BFA60E000BE12FD /* quality_of_service_server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = quality_of_service_server.cpp; sourceTree = ""; }; + 9B5A101A1BFA60E000BE12FD /* leaderboard_column.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leaderboard_column.cpp; sourceTree = ""; }; + 9B5A101B1BFA60E000BE12FD /* leaderboard_query.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaderboard_query.h; sourceTree = ""; }; + 9B5A101C1BFA60E000BE12FD /* leaderboard_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leaderboard_result.cpp; sourceTree = ""; }; + 9B5A101D1BFA60E000BE12FD /* leaderboard_row.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leaderboard_row.cpp; sourceTree = ""; }; + 9B5A101E1BFA60E000BE12FD /* leaderboard_serializers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leaderboard_serializers.cpp; sourceTree = ""; }; + 9B5A101F1BFA60E000BE12FD /* leaderboard_serializers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaderboard_serializers.h; sourceTree = ""; }; + 9B5A10201BFA60E000BE12FD /* leaderboard_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leaderboard_service.cpp; sourceTree = ""; }; + 9B5A10541BFA60E000BE12FD /* create_match_ticket_response.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = create_match_ticket_response.cpp; sourceTree = ""; }; + 9B5A10551BFA60E000BE12FD /* hopper_statistics_response.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hopper_statistics_response.cpp; sourceTree = ""; }; + 9B5A10561BFA60E000BE12FD /* match_ticket_details_response.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = match_ticket_details_response.cpp; sourceTree = ""; }; + 9B5A10571BFA60E000BE12FD /* matchmaking_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = matchmaking_service.cpp; sourceTree = ""; }; + 9B5A10621BFA60E000BE12FD /* contextual_config_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_config_result.cpp; sourceTree = ""; }; + 9B5A10631BFA60E000BE12FD /* contextual_config_result.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = contextual_config_result.h; sourceTree = ""; }; + 9B5A10641BFA60E000BE12FD /* contextual_search_broadcast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_broadcast.cpp; sourceTree = ""; }; + 9B5A10651BFA60E000BE12FD /* contextual_search_configured_stat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_configured_stat.cpp; sourceTree = ""; }; + 9B5A10661BFA60E000BE12FD /* contextual_search_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_service.cpp; sourceTree = ""; }; + 9B5A10691BFA60E000BE12FD /* string_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = string_service.cpp; sourceTree = ""; }; + 9B5A106B1BFA60E000BE12FD /* verify_string_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = verify_string_result.cpp; sourceTree = ""; }; + 9B5A10BE1BFA60E000BE12FD /* multiplayer_activity_details.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_activity_details.cpp; sourceTree = ""; }; + 9B5A10BF1BFA60E000BE12FD /* multiplayer_activity_handle_post_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_activity_handle_post_request.cpp; sourceTree = ""; }; + 9B5A10C01BFA60E000BE12FD /* multiplayer_activity_query_post_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_activity_query_post_request.cpp; sourceTree = ""; }; + 9B5A10C11BFA60E000BE12FD /* multiplayer_get_sessions_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_get_sessions_request.cpp; sourceTree = ""; }; + 9B5A10C21BFA60E000BE12FD /* multiplayer_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multiplayer_internal.h; sourceTree = ""; }; + 9B5A10C31BFA60E000BE12FD /* multiplayer_invite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_invite.cpp; sourceTree = ""; }; + 9B5A10C41BFA60E000BE12FD /* multiplayer_invite_handle_post_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_invite_handle_post_request.cpp; sourceTree = ""; }; + 9B5A10C51BFA60E000BE12FD /* multiplayer_managed_initialization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_managed_initialization.cpp; sourceTree = ""; }; + 9B5A10C61BFA60E000BE12FD /* multiplayer_peer_to_host_requirements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_peer_to_host_requirements.cpp; sourceTree = ""; }; + 9B5A10C71BFA60E000BE12FD /* multiplayer_peer_to_peer_requirements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_peer_to_peer_requirements.cpp; sourceTree = ""; }; + 9B5A10C81BFA60E000BE12FD /* multiplayer_quality_of_service_measurement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_quality_of_service_measurement.cpp; sourceTree = ""; }; + 9B5A10C91BFA60E000BE12FD /* multiplayer_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_service.cpp; sourceTree = ""; }; + 9B5A10CA1BFA60E000BE12FD /* multiplayer_service_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_service_impl.cpp; sourceTree = ""; }; + 9B5A10CB1BFA60E000BE12FD /* multiplayer_session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session.cpp; sourceTree = ""; }; + 9B5A10CC1BFA60E000BE12FD /* multiplayer_session_capabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_capabilities.cpp; sourceTree = ""; }; + 9B5A10CD1BFA60E000BE12FD /* multiplayer_session_change_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_change_event_args.cpp; sourceTree = ""; }; + 9B5A10CE1BFA60E000BE12FD /* multiplayer_session_constants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_constants.cpp; sourceTree = ""; }; + 9B5A10CF1BFA60E000BE12FD /* multiplayer_session_matchmaking_server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_matchmaking_server.cpp; sourceTree = ""; }; + 9B5A10D01BFA60E000BE12FD /* multiplayer_session_member.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_member.cpp; sourceTree = ""; }; + 9B5A10D11BFA60E000BE12FD /* multiplayer_session_member_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_member_request.cpp; sourceTree = ""; }; + 9B5A10D21BFA60E000BE12FD /* multiplayer_session_properties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_properties.cpp; sourceTree = ""; }; + 9B5A10D31BFA60E000BE12FD /* multiplayer_session_reference.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_reference.cpp; sourceTree = ""; }; + 9B5A10D41BFA60E000BE12FD /* multiplayer_session_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_request.cpp; sourceTree = ""; }; + 9B5A10D51BFA60E000BE12FD /* multiplayer_session_states.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_states.cpp; sourceTree = ""; }; + 9B5A10D61BFA60E000BE12FD /* multiplayer_subscription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_subscription.cpp; sourceTree = ""; }; + 9B5A10D71BFA60E000BE12FD /* multiplayer_transfer_handle_post_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_transfer_handle_post_request.cpp; sourceTree = ""; }; + 9B5A110A1BFA60E000BE12FD /* device_presence_change_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = device_presence_change_event_args.cpp; sourceTree = ""; }; + 9B5A110B1BFA60E000BE12FD /* device_presence_change_subscription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = device_presence_change_subscription.cpp; sourceTree = ""; }; + 9B5A110C1BFA60E000BE12FD /* media_presence_data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = media_presence_data.cpp; sourceTree = ""; }; + 9B5A110D1BFA60E000BE12FD /* presence_activity_data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_activity_data.cpp; sourceTree = ""; }; + 9B5A110E1BFA60E000BE12FD /* presence_broadcast_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_broadcast_record.cpp; sourceTree = ""; }; + 9B5A110F1BFA60E000BE12FD /* presence_data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_data.cpp; sourceTree = ""; }; + 9B5A11101BFA60E000BE12FD /* presence_device_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_device_record.cpp; sourceTree = ""; }; + 9B5A11111BFA60E000BE12FD /* presence_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = presence_internal.h; sourceTree = ""; }; + 9B5A11121BFA60E000BE12FD /* presence_media_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_media_record.cpp; sourceTree = ""; }; + 9B5A11131BFA60E000BE12FD /* presence_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_record.cpp; sourceTree = ""; }; + 9B5A11141BFA60E000BE12FD /* presence_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_service.cpp; sourceTree = ""; }; + 9B5A11151BFA60E000BE12FD /* presence_service_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_service_impl.cpp; sourceTree = ""; }; + 9B5A11161BFA60E000BE12FD /* presence_title_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_title_record.cpp; sourceTree = ""; }; + 9B5A11171BFA60E000BE12FD /* presence_title_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_title_request.cpp; sourceTree = ""; }; + 9B5A11181BFA60E000BE12FD /* presence_user_batch_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_user_batch_request.cpp; sourceTree = ""; }; + 9B5A11191BFA60E000BE12FD /* presence_writer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = presence_writer.cpp; sourceTree = ""; }; + 9B5A111A1BFA60E000BE12FD /* title_presence_change_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_presence_change_event_args.cpp; sourceTree = ""; }; + 9B5A111B1BFA60E000BE12FD /* title_presence_change_subscription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_presence_change_subscription.cpp; sourceTree = ""; }; + 9B5A113A1BFA60E000BE12FD /* multiple_permissions_check_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiple_permissions_check_result.cpp; sourceTree = ""; }; + 9B5A113B1BFA60E000BE12FD /* permission_check_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = permission_check_result.cpp; sourceTree = ""; }; + 9B5A113C1BFA60E000BE12FD /* permission_deny_reason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = permission_deny_reason.cpp; sourceTree = ""; }; + 9B5A113D1BFA60E000BE12FD /* privacy_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = privacy_service.cpp; sourceTree = ""; }; + 9B5A114A1BFA60E000BE12FD /* real_time_activity_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = real_time_activity_service.cpp; sourceTree = ""; }; + 9B5A114B1BFA60E000BE12FD /* real_time_activity_subscription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = real_time_activity_subscription.cpp; sourceTree = ""; }; + 9B5A114C1BFA60E000BE12FD /* real_time_activity_subscription_error_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = real_time_activity_subscription_error_event_args.cpp; sourceTree = ""; }; + 9B5A11711BFA60E000BE12FD /* profile_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profile_service.cpp; sourceTree = ""; }; + 9B5A11721BFA60E000BE12FD /* reputation_feedback_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reputation_feedback_request.cpp; sourceTree = ""; }; + 9B5A11731BFA60E000BE12FD /* reputation_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reputation_service.cpp; sourceTree = ""; }; + 9B5A11741BFA60E000BE12FD /* social_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = social_internal.h; sourceTree = ""; }; + 9B5A11751BFA60E000BE12FD /* social_relationship_change_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = social_relationship_change_event_args.cpp; sourceTree = ""; }; + 9B5A11761BFA60E000BE12FD /* social_relationship_change_subscription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = social_relationship_change_subscription.cpp; sourceTree = ""; }; + 9B5A11771BFA60E000BE12FD /* social_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = social_service.cpp; sourceTree = ""; }; + 9B5A11781BFA60E000BE12FD /* social_service_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = social_service_impl.cpp; sourceTree = ""; }; + 9B5A11911BFA60E000BE12FD /* xbox_social_relationship.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_social_relationship.cpp; sourceTree = ""; }; + 9B5A11921BFA60E000BE12FD /* xbox_social_relationship_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_social_relationship_result.cpp; sourceTree = ""; }; + 9B5A11931BFA60E000BE12FD /* xbox_user_profile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_user_profile.cpp; sourceTree = ""; }; + 9B5A11951BFA60E000BE12FD /* requested_statistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = requested_statistics.cpp; sourceTree = ""; }; + 9B5A11961BFA60E000BE12FD /* service_configuration_statistic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = service_configuration_statistic.cpp; sourceTree = ""; }; + 9B5A11971BFA60E100BE12FD /* statistic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = statistic.cpp; sourceTree = ""; }; + 9B5A11981BFA60E100BE12FD /* statistic_change_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = statistic_change_event_args.cpp; sourceTree = ""; }; + 9B5A11991BFA60E100BE12FD /* statistic_change_subscription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = statistic_change_subscription.cpp; sourceTree = ""; }; + 9B5A119A1BFA60E100BE12FD /* user_statistics_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_statistics_internal.h; sourceTree = ""; }; + 9B5A119B1BFA60E100BE12FD /* user_statistics_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_statistics_result.cpp; sourceTree = ""; }; + 9B5A119C1BFA60E100BE12FD /* user_statistics_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_statistics_service.cpp; sourceTree = ""; }; + 9B5A119D1BFA60E100BE12FD /* user_statistics_service_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_statistics_service_impl.cpp; sourceTree = ""; }; + 9B5A11AE1BFA60E100BE12FD /* title_storage_blob_metadata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_storage_blob_metadata.cpp; sourceTree = ""; }; + 9B5A11AF1BFA60E100BE12FD /* title_storage_blob_metadata_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_storage_blob_metadata_result.cpp; sourceTree = ""; }; + 9B5A11B01BFA60E100BE12FD /* title_storage_blob_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_storage_blob_result.cpp; sourceTree = ""; }; + 9B5A11B11BFA60E100BE12FD /* title_storage_quota.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_storage_quota.cpp; sourceTree = ""; }; + 9B5A11B21BFA60E100BE12FD /* title_storage_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_storage_service.cpp; sourceTree = ""; }; + 9B5A12C91BFBF63600BE12FD /* pch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pch.cpp; sourceTree = ""; }; + 9B5A12CA1BFBF63600BE12FD /* pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch.h; sourceTree = ""; }; + 9B5A12D31BFD2BF200BE12FD /* tournament_team_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tournament_team_result.cpp; sourceTree = ""; }; + 9B66D2CC1BE85B5C00E53086 /* Casablanca.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Casablanca.xcodeproj; path = ../../Casablanca/Build_iOS/Casablanca.xcodeproj; sourceTree = ""; }; + 9B82502C1C1A397F002C8F30 /* multiplayer_session_arbitration_server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_arbitration_server.cpp; sourceTree = ""; }; + 9B8250311C1A4A8F002C8F30 /* multiplayer_session_tournaments_server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_session_tournaments_server.cpp; sourceTree = ""; }; + 9B8250331C1A4B34002C8F30 /* tournament_reference.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tournament_reference.cpp; sourceTree = ""; }; + 9B847EAD1CDD27A1004E04B0 /* notification_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notification_service.h; sourceTree = ""; }; + 9B847EB11CDD2823004E04B0 /* notification_service_i.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = notification_service_i.mm; sourceTree = ""; }; + 9B847EB51CDD6928004E04B0 /* notification_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = notification_service.cpp; sourceTree = ""; }; + 9B8A00AF1BF2778B000337EA /* sign_in_delegate_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sign_in_delegate_ios.h; sourceTree = ""; }; + 9B8A00B01BF2778B000337EA /* sign_in_delegate_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = sign_in_delegate_ios.mm; sourceTree = ""; }; + 9B9615E21BEA86FE00E79527 /* XboxLiveContext_Desktop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XboxLiveContext_Desktop.cpp; sourceTree = ""; }; + 9B9615E91BEA962600E79527 /* pch_unix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch_unix.h; sourceTree = ""; }; + 9B97B35B1BE18B2600CF1E29 /* libXboxLiveServices.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libXboxLiveServices.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 9B97B5941BE1981900CF1E29 /* build_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = build_version.h; sourceTree = ""; }; + 9B97B5971BE1981900CF1E29 /* errors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = errors.cpp; sourceTree = ""; }; + 9B97B5981BE1981900CF1E29 /* http_call_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_call_impl.cpp; sourceTree = ""; }; + 9B97B5991BE1981900CF1E29 /* http_call_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_call_impl.h; sourceTree = ""; }; + 9B97B59A1BE1981900CF1E29 /* http_call_request_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_call_request_message.cpp; sourceTree = ""; }; + 9B97B59B1BE1981900CF1E29 /* http_call_response.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_call_response.cpp; sourceTree = ""; }; + 9B97B59C1BE1981900CF1E29 /* http_call_response.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_call_response.h; sourceTree = ""; }; + 9B97B59D1BE1981900CF1E29 /* http_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_client.cpp; sourceTree = ""; }; + 9B97B59E1BE1981900CF1E29 /* http_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_client.h; sourceTree = ""; }; + 9B97B59F1BE1981900CF1E29 /* local_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = local_config.cpp; sourceTree = ""; }; + 9B97B5A01BE1981900CF1E29 /* local_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = local_config.h; sourceTree = ""; }; + 9B97B5A11BE1981900CF1E29 /* service_call_logger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = service_call_logger.cpp; sourceTree = ""; }; + 9B97B5A21BE1981900CF1E29 /* service_call_logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service_call_logger.h; sourceTree = ""; }; + 9B97B5A31BE1981900CF1E29 /* service_call_logger_data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = service_call_logger_data.cpp; sourceTree = ""; }; + 9B97B5A41BE1981900CF1E29 /* service_call_logger_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service_call_logger_data.h; sourceTree = ""; }; + 9B97B5A71BE1981900CF1E29 /* service_call_logging_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = service_call_logging_config.cpp; sourceTree = ""; }; + 9B97B5A81BE1981900CF1E29 /* shared_macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_macros.h; sourceTree = ""; }; + 9B97B5A91BE1981900CF1E29 /* telemetry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = telemetry.cpp; sourceTree = ""; }; + 9B97B5AA1BE1981900CF1E29 /* telemetry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = telemetry.h; sourceTree = ""; }; + 9B97B5AB1BE1981900CF1E29 /* user_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_context.cpp; sourceTree = ""; }; + 9B97B5AC1BE1981900CF1E29 /* user_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_context.h; sourceTree = ""; }; + 9B97B5AD1BE1981900CF1E29 /* utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cpp; sourceTree = ""; }; + 9B97B5AE1BE1981900CF1E29 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + 9B97B5AF1BE1981900CF1E29 /* utils_locales.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utils_locales.cpp; sourceTree = ""; }; + 9B97B5B01BE1981900CF1E29 /* web_socket_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = web_socket_client.cpp; sourceTree = ""; }; + 9B97B5B11BE1981900CF1E29 /* web_socket_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = web_socket_client.h; sourceTree = ""; }; + 9B97B5B21BE1981900CF1E29 /* web_socket_connection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = web_socket_connection.cpp; sourceTree = ""; }; + 9B97B5B31BE1981900CF1E29 /* web_socket_connection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = web_socket_connection.h; sourceTree = ""; }; + 9B97B5B41BE1981900CF1E29 /* web_socket_connection_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = web_socket_connection_state.h; sourceTree = ""; }; + 9B97B5C81BE1981900CF1E29 /* xbox_live_app_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_live_app_config.cpp; sourceTree = ""; }; + 9B97B5C91BE1981900CF1E29 /* xbox_live_context_settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_live_context_settings.cpp; sourceTree = ""; }; + 9B97B5CA1BE1981900CF1E29 /* xbox_service_call_routed_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_service_call_routed_event_args.cpp; sourceTree = ""; }; + 9B97B5CB1BE1981900CF1E29 /* xbox_system_factory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_system_factory.cpp; sourceTree = ""; }; + 9B97B5CC1BE1981900CF1E29 /* xbox_system_factory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_system_factory.h; sourceTree = ""; }; + 9B97B5CF1BE1981900CF1E29 /* auth_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = auth_manager.cpp; sourceTree = ""; }; + 9B97B5D01BE1981900CF1E29 /* auth_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auth_manager.h; sourceTree = ""; }; + 9B97B5D11BE1981900CF1E29 /* cidr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cidr.cpp; sourceTree = ""; }; + 9B97B5D21BE1981900CF1E29 /* cidr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cidr.h; sourceTree = ""; }; + 9B97B5DB1BE1981900CF1E29 /* ecdsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ecdsa.h; sourceTree = ""; }; + 9B97B5DC1BE1981900CF1E29 /* ip_address.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ip_address.cpp; sourceTree = ""; }; + 9B97B5DD1BE1981900CF1E29 /* ip_address.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ip_address.h; sourceTree = ""; }; + 9B97B5DE1BE1981900CF1E29 /* json_web_key.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_web_key.cpp; sourceTree = ""; }; + 9B97B5DF1BE1981900CF1E29 /* json_web_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_web_key.h; sourceTree = ""; }; + 9B97B5E01BE1981900CF1E29 /* nsal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nsal.cpp; sourceTree = ""; }; + 9B97B5E11BE1981900CF1E29 /* nsal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nsal.h; sourceTree = ""; }; + 9B97B5E21BE1981900CF1E29 /* nsal_endpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nsal_endpoint.cpp; sourceTree = ""; }; + 9B97B5E31BE1981900CF1E29 /* nsal_endpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nsal_endpoint.h; sourceTree = ""; }; + 9B97B5E41BE1981900CF1E29 /* request_signer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = request_signer.h; sourceTree = ""; }; + 9B97B5E51BE1981900CF1E29 /* request_signer_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = request_signer_helpers.cpp; sourceTree = ""; }; + 9B97B5E61BE1981900CF1E29 /* request_signer_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = request_signer_helpers.h; sourceTree = ""; }; + 9B97B5E91BE1981900CF1E29 /* signature_policy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = signature_policy.cpp; sourceTree = ""; }; + 9B97B5EA1BE1981900CF1E29 /* signature_policy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = signature_policy.h; sourceTree = ""; }; + 9B97B5EB1BE1981900CF1E29 /* title_token_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = title_token_service.cpp; sourceTree = ""; }; + 9B97B5EC1BE1981900CF1E29 /* title_token_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = title_token_service.h; sourceTree = ""; }; + 9B97B5ED1BE1981900CF1E29 /* token_error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token_error.cpp; sourceTree = ""; }; + 9B97B5EE1BE1981900CF1E29 /* token_error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = token_error.h; sourceTree = ""; }; + 9B97B5EF1BE1981900CF1E29 /* token_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token_manager.cpp; sourceTree = ""; }; + 9B97B5F01BE1981900CF1E29 /* token_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = token_manager.h; sourceTree = ""; }; + 9B97B5F11BE1981900CF1E29 /* token_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token_request.cpp; sourceTree = ""; }; + 9B97B5F21BE1981900CF1E29 /* token_request.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = token_request.h; sourceTree = ""; }; + 9B97B5F31BE1981900CF1E29 /* token_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token_result.cpp; sourceTree = ""; }; + 9B97B5F41BE1981900CF1E29 /* token_result.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = token_result.h; sourceTree = ""; }; + 9B97B5F51BE1981900CF1E29 /* trie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trie.cpp; sourceTree = ""; }; + 9B97B5F61BE1981900CF1E29 /* trie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trie.h; sourceTree = ""; }; + 9B97B5F71BE1981900CF1E29 /* user_token_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_token_service.cpp; sourceTree = ""; }; + 9B97B5F81BE1981900CF1E29 /* user_token_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_token_service.h; sourceTree = ""; }; + 9B97B5FC1BE1981900CF1E29 /* xsts_token_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xsts_token_service.cpp; sourceTree = ""; }; + 9B97B5FD1BE1981900CF1E29 /* xsts_token_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xsts_token_service.h; sourceTree = ""; }; + 9B97B5FE1BE1981900CF1E29 /* xtitle_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xtitle_service.cpp; sourceTree = ""; }; + 9B97B5FF1BE1981900CF1E29 /* xtitle_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xtitle_service.h; sourceTree = ""; }; + 9B97B6001BE1981900CF1E29 /* auth_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = auth_config.cpp; sourceTree = ""; }; + 9B97B6011BE1981900CF1E29 /* auth_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auth_config.h; sourceTree = ""; }; + 9B97B6021BE1981900CF1E29 /* system_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = system_internal.h; sourceTree = ""; }; + 9B97B6031BE1981900CF1E29 /* token_and_signature_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token_and_signature_result.cpp; sourceTree = ""; }; + 9B97B6041BE1981900CF1E29 /* user.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user.cpp; sourceTree = ""; }; + 9B97B6051BE1981900CF1E29 /* user_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_impl.cpp; sourceTree = ""; }; + 9B97B6061BE1981900CF1E29 /* user_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_impl.h; sourceTree = ""; }; + 9B97B6101BE1981900CF1E29 /* xbox_live_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_live_mutex.cpp; sourceTree = ""; }; + 9B97B7B21BE19DFC00CF1E29 /* pch_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch_common.h; sourceTree = ""; }; + 9B97B7BB1BE19DFC00CF1E29 /* xbox_live_context_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_live_context_impl.cpp; sourceTree = ""; }; + 9B97B7BC1BE19DFC00CF1E29 /* xbox_live_context_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_live_context_impl.h; sourceTree = ""; }; + 9B97BABA1BE1A1B000CF1E29 /* achievements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = achievements.h; sourceTree = ""; }; + 9B97BABB1BE1A1B000CF1E29 /* contextual_search_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = contextual_search_service.h; sourceTree = ""; }; + 9B97BABC1BE1A1B000CF1E29 /* entertainment_profile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = entertainment_profile.h; sourceTree = ""; }; + 9B97BABD1BE1A1B000CF1E29 /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = errors.h; sourceTree = ""; }; + 9B97BABE1BE1A1B000CF1E29 /* events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = events.h; sourceTree = ""; }; + 9B97BABF1BE1A1B000CF1E29 /* game_server_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = game_server_platform.h; sourceTree = ""; }; + 9B97BAC01BE1A1B000CF1E29 /* http_call.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_call.h; sourceTree = ""; }; + 9B97BAC11BE1A1B000CF1E29 /* http_call_request_message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_call_request_message.h; sourceTree = ""; }; + 9B97BAC21BE1A1B000CF1E29 /* leaderboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaderboard.h; sourceTree = ""; }; + 9B97BAC41BE1A1B000CF1E29 /* matchmaking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matchmaking.h; sourceTree = ""; }; + 9B97BAC71BE1A1B000CF1E29 /* presence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = presence.h; sourceTree = ""; }; + 9B97BAC81BE1A1B000CF1E29 /* privacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = privacy.h; sourceTree = ""; }; + 9B97BAC91BE1A1B000CF1E29 /* profile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profile.h; sourceTree = ""; }; + 9B97BACA1BE1A1B000CF1E29 /* real_time_activity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = real_time_activity.h; sourceTree = ""; }; + 9B97BACB1BE1A1B000CF1E29 /* service_call_logging_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service_call_logging_config.h; sourceTree = ""; }; + 9B97BACC1BE1A1B000CF1E29 /* services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = services.h; sourceTree = ""; }; + 9B97BACD1BE1A1B000CF1E29 /* social.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = social.h; sourceTree = ""; }; + 9B97BACF1BE1A1B000CF1E29 /* system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = system.h; sourceTree = ""; }; + 9B97BAD01BE1A1B000CF1E29 /* title_callable_ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = title_callable_ui.h; sourceTree = ""; }; + 9B97BAD11BE1A1B000CF1E29 /* title_storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = title_storage.h; sourceTree = ""; }; + 9B97BAD21BE1A1B000CF1E29 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; + 9B97BAD31BE1A1B000CF1E29 /* user_statistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_statistics.h; sourceTree = ""; }; + 9B97BAD51BE1A1B000CF1E29 /* xbox_live_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_live_context.h; sourceTree = ""; }; + 9B97BAD61BE1A1B000CF1E29 /* xbox_live_context_settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_live_context_settings.h; sourceTree = ""; }; + 9B97BAD71BE1A1B000CF1E29 /* xbox_service_call_routed_event_args.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbox_service_call_routed_event_args.h; sourceTree = ""; }; + 9BA63DBD1BE43C8900BFC445 /* presence_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = presence_internal.h; path = ../../Source/Services/Presence/presence_internal.h; sourceTree = ""; }; + 9BAEFDE81D3019A300ABBA82 /* multiplayer_match_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multiplayer_match_client.cpp; path = Manager/multiplayer_match_client.cpp; sourceTree = ""; }; + 9BAEFDEA1D3019B300ABBA82 /* multiplayer_search_handle_details.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_search_handle_details.cpp; sourceTree = ""; }; + 9BAEFDEB1D3019B300ABBA82 /* multiplayer_search_handle_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_search_handle_request.cpp; sourceTree = ""; }; + 9BAEFDEE1D30263F00ABBA82 /* initiator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = initiator.cpp; sourceTree = ""; }; + 9BAEFDEF1D30263F00ABBA82 /* initiator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = initiator.h; sourceTree = ""; }; + 9BBAB7771CBDE09000A75EDF /* local_config_u.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = local_config_u.cpp; path = u/local_config_u.cpp; sourceTree = ""; }; + 9BBAB79C1CC0408200A75EDF /* local_config_i.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = local_config_i.mm; path = i/local_config_i.mm; sourceTree = ""; }; + 9BEB14F91DCD01BF001E5DD5 /* multiplayer_member_initialization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_member_initialization.cpp; sourceTree = ""; }; + 9BF11ACC1C12076E00D111C9 /* big_num.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = big_num.cpp; sourceTree = ""; }; + 9BF11ACD1C12076E00D111C9 /* big_num.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = big_num.h; sourceTree = ""; }; + 9BF11ACE1C12076E00D111C9 /* request_signer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = request_signer.cpp; sourceTree = ""; }; + 9BF11ACF1C12076E00D111C9 /* sha256.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sha256.cpp; sourceTree = ""; }; + 9BF11AD01C12076E00D111C9 /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha256.h; sourceTree = ""; }; + 9BF11AD91C120C2900D111C9 /* ip_address_desktop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ip_address_desktop.cpp; sourceTree = ""; }; + 9BF11AE61C17ABA400D111C9 /* multiplayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multiplayer.h; sourceTree = ""; }; + 9BF132411C3C48230048204E /* device_token_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = device_token_service.cpp; sourceTree = ""; }; + 9BF132421C3C48230048204E /* device_token_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = device_token_service.h; sourceTree = ""; }; + 9BF639331D492C3300BDF02B /* contextual_search_game_clip_stat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_game_clip_stat.cpp; sourceTree = ""; }; + 9BF639341D492C3300BDF02B /* contextual_search_game_clip_thumbnail.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_game_clip_thumbnail.cpp; sourceTree = ""; }; + 9BF639351D492C3300BDF02B /* contextual_search_game_clip_uri_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_game_clip_uri_info.cpp; sourceTree = ""; }; + 9BF639361D492C3300BDF02B /* contextual_search_game_clip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_game_clip.cpp; sourceTree = ""; }; + 9BF639371D492C3300BDF02B /* contextual_search_game_clips_result.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextual_search_game_clips_result.cpp; sourceTree = ""; }; + 9C063B111D774C28009C3E3C /* mem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mem.cpp; sourceTree = ""; }; + 9C063B131D774FD7009C3E3C /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = ""; }; + 9C4DF1B01DA32E6A00224A7C /* ppltasks_extra_unix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ppltasks_extra_unix.h; sourceTree = ""; }; + 9CB56C051DA359BB00C92F44 /* multiplayer_query_search_handle_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayer_query_search_handle_request.cpp; sourceTree = ""; }; + 9CB56C071DA35A4500C92F44 /* xbox_live_services_settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbox_live_services_settings.cpp; sourceTree = ""; }; + 9CB56C091DA35AA800C92F44 /* custom_output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = custom_output.cpp; sourceTree = ""; }; + 9CB56C0A1DA35AA800C92F44 /* custom_output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = custom_output.h; sourceTree = ""; }; + 9CC36FE21DB6DE89007142EE /* xbox_user_id_container.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xbox_user_id_container.cpp; path = Manager/xbox_user_id_container.cpp; sourceTree = ""; }; + 9CDF0D291DA2E8860046C721 /* internal_social_event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = internal_social_event.cpp; path = Manager/internal_social_event.cpp; sourceTree = ""; }; + 9CDF0D2A1DA2E8860046C721 /* peoplehub_service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = peoplehub_service.cpp; path = Manager/peoplehub_service.cpp; sourceTree = ""; }; + 9CDF0D2B1DA2E8860046C721 /* preferred_color.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = preferred_color.cpp; path = Manager/preferred_color.cpp; sourceTree = ""; }; + 9CDF0D2C1DA2E8860046C721 /* social_event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = social_event.cpp; path = Manager/social_event.cpp; sourceTree = ""; }; + 9CDF0D2D1DA2E8860046C721 /* social_graph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = social_graph.cpp; path = Manager/social_graph.cpp; sourceTree = ""; }; + 9CDF0D2E1DA2E8860046C721 /* social_manager_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = social_manager_internal.h; path = Manager/social_manager_internal.h; sourceTree = ""; }; + 9CDF0D2F1DA2E8860046C721 /* social_manager_presence_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = social_manager_presence_record.cpp; path = Manager/social_manager_presence_record.cpp; sourceTree = ""; }; + 9CDF0D301DA2E8860046C721 /* social_manager_presence_title_record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = social_manager_presence_title_record.cpp; path = Manager/social_manager_presence_title_record.cpp; sourceTree = ""; }; + 9CDF0D311DA2E8860046C721 /* social_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = social_manager.cpp; path = Manager/social_manager.cpp; sourceTree = ""; }; + 9CDF0D321DA2E8860046C721 /* social_user_group_loaded_event_args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = social_user_group_loaded_event_args.cpp; path = Manager/social_user_group_loaded_event_args.cpp; sourceTree = ""; }; + 9CDF0D331DA2E8860046C721 /* title_history.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = title_history.cpp; path = Manager/title_history.cpp; sourceTree = ""; }; + 9CDF0D341DA2E8860046C721 /* xbox_social_user_group.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xbox_social_user_group.cpp; path = Manager/xbox_social_user_group.cpp; sourceTree = ""; }; + 9CDF0D351DA2E8860046C721 /* xbox_social_user.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xbox_social_user.cpp; path = Manager/xbox_social_user.cpp; sourceTree = ""; }; + B71305811CC7477A00A4E71E /* XLSCll.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = XLSCll.mm; path = ../XboxTelemetry/XLSCll.mm; sourceTree = ""; }; + B71305831CC747AD00A4E71E /* XLSCll.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = XLSCll.h; path = ../XboxTelemetry/XLSCll.h; sourceTree = ""; }; + B7E5C76B1CEED3E5003B2B08 /* UTCIDPNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UTCIDPNames.h; path = ../XboxTelemetry/UTCIDPNames.h; sourceTree = ""; }; + B7E5C76C1CEED3E5003B2B08 /* UTCIDPNames.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UTCIDPNames.mm; path = ../XboxTelemetry/UTCIDPNames.mm; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9B97B3581BE18B2600CF1E29 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B4933FA1CE8F29E00E7CE0B /* WebKit.framework in Frameworks */, + 6718D9161C9F69CA007FD4F6 /* CoreText.framework in Frameworks */, + 670AA2F61C7657D300B3FB9A /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 255A36A21CD834F400D3AD8E /* Manager */ = { + isa = PBXGroup; + children = ( + 9BAEFDE81D3019A300ABBA82 /* multiplayer_match_client.cpp */, + 255A36A61CD8353B00D3AD8E /* find_match_completed_event_args.cpp */, + 255A36A71CD8353B00D3AD8E /* host_changed_event_args.cpp */, + 255A36A81CD8353B00D3AD8E /* join_lobby_completed_event_args.cpp */, + 255A36AA1CD8353B00D3AD8E /* member_joined_event_args.cpp */, + 255A36AB1CD8353B00D3AD8E /* member_left_event_args.cpp */, + 255A36AC1CD8353B00D3AD8E /* member_property_changed_event_args.cpp */, + 255A36AD1CD8353B00D3AD8E /* multiplayer_client_manager.cpp */, + 255A36AE1CD8353B00D3AD8E /* multiplayer_client_pending_reader.cpp */, + 255A36AF1CD8353B00D3AD8E /* multiplayer_client_pending_request.cpp */, + 255A36B01CD8353B00D3AD8E /* multiplayer_event.cpp */, + 255A36B11CD8353B00D3AD8E /* multiplayer_game_client.cpp */, + 255A36B21CD8353B00D3AD8E /* multiplayer_game_session.cpp */, + 255A36B31CD8353B00D3AD8E /* multiplayer_lobby_client.cpp */, + 255A36B41CD8353B00D3AD8E /* multiplayer_lobby_session.cpp */, + 255A36B51CD8353B00D3AD8E /* multiplayer_local_user_manager.cpp */, + 255A36B61CD8353B00D3AD8E /* multiplayer_local_user.cpp */, + 255A36B71CD8353B00D3AD8E /* multiplayer_manager_internal.h */, + 255A36B81CD8353B00D3AD8E /* multiplayer_manager_utils.cpp */, + 255A36B91CD8353B00D3AD8E /* multiplayer_manager.cpp */, + 255A36BA1CD8353B00D3AD8E /* multiplayer_member.cpp */, + 255A36BB1CD8353B00D3AD8E /* multiplayer_session_writer.cpp */, + 255A36BC1CD8353B00D3AD8E /* perform_qos_measurements_event_args.cpp */, + 255A36BD1CD8353B00D3AD8E /* session_property_changed_event_args.cpp */, + 255A36BE1CD8353B00D3AD8E /* tournament_game_session_ready_event_args.cpp */, + 255A36BF1CD8353B00D3AD8E /* tournament_registration_state_changed_event_args.cpp */, + 255A36C01CD8353B00D3AD8E /* user_added_event_args.cpp */, + 255A36C11CD8353B00D3AD8E /* user_removed_event_args.cpp */, + 255A36C21CD8353B00D3AD8E /* WinRT */, + ); + name = Manager; + sourceTree = ""; + }; + 32F5FBBD1CE7DB0F008A5E09 /* iOS */ = { + isa = PBXGroup; + children = ( + 9B4934781CEE1C1800E7CE0B /* notification_helper.mm */, + 32F5FBBE1CE7DB1D008A5E09 /* title_callable_ui.mm */, + ); + name = iOS; + sourceTree = ""; + }; + 6718D8B11C865E23007FD4F6 /* Xbox UI Delegates */ = { + isa = PBXGroup; + children = ( + 9B8A00AF1BF2778B000337EA /* sign_in_delegate_ios.h */, + 9B8A00B01BF2778B000337EA /* sign_in_delegate_ios.mm */, + 6718D8B51C86605E007FD4F6 /* XBLSignInHandler.h */, + 6718D8B61C86605E007FD4F6 /* XBLSignInHandler.mm */, + ); + name = "Xbox UI Delegates"; + path = XboxUIDelegates; + sourceTree = ""; + }; + 67210E181C6479E20008FFDB /* Xbox Sign In UI */ = { + isa = PBXGroup; + children = ( + 67210E211C6479E20008FFDB /* Bridge */, + ); + name = "Xbox Sign In UI"; + path = XboxSignInUI; + sourceTree = ""; + }; + 67210E211C6479E20008FFDB /* Bridge */ = { + isa = PBXGroup; + children = ( + 67210E241C6479E20008FFDB /* NSError+XSAPIExtensions.h */, + 67210E251C6479E20008FFDB /* NSError+XSAPIExtensions.mm */, + 67210E261C6479E20008FFDB /* XboxProvider.h */, + 67210E271C6479E20008FFDB /* XboxProvider.mm */, + 6718D8AF1C865AD0007FD4F6 /* XboxProviderBridge.h */, + 6718D8AE1C865AD0007FD4F6 /* XboxProviderBridge.cpp */, + ); + path = Bridge; + sourceTree = ""; + }; + 6781BDAE1CBC702100264EAF /* Products */ = { + isa = PBXGroup; + children = ( + 6781BDB31CBC702100264EAF /* XSAPITCUI.framework */, + ); + name = Products; + sourceTree = ""; + }; + 67A963861C5FE4250066184E /* XboxLiveServicesResources */ = { + isa = PBXGroup; + children = ( + 67A963871C5FE4250066184E /* Info.plist */, + ); + path = XboxLiveServicesResources; + sourceTree = ""; + }; + 9B118AC01D6D0B3A0068B268 /* iOS */ = { + isa = PBXGroup; + children = ( + 9B118AC11D6D0B460068B268 /* debug_output_ios.cpp */, + ); + name = iOS; + sourceTree = ""; + }; + 9B118AD81D885F960068B268 /* auth */ = { + isa = PBXGroup; + children = ( + 9B118AD91D885FA80068B268 /* user_auth_ios.h */, + 9B118ADA1D885FA80068B268 /* user_auth_ios.mm */, + ); + name = auth; + sourceTree = ""; + }; + 9B46ED431BED41D600076704 /* Unix */ = { + isa = PBXGroup; + children = ( + 9BF11ACC1C12076E00D111C9 /* big_num.cpp */, + 9BF11ACD1C12076E00D111C9 /* big_num.h */, + 9BF11ACE1C12076E00D111C9 /* request_signer.cpp */, + 9BF11ACF1C12076E00D111C9 /* sha256.cpp */, + 9BF11AD01C12076E00D111C9 /* sha256.h */, + 9B46ED441BED41D600076704 /* ecdsa_unix.cpp */, + 9B46ED451BED41D600076704 /* ip_address_unix.cpp */, + ); + path = Unix; + sourceTree = ""; + }; + 9B4B44A41D2F2D4C0060F1C5 /* Logger */ = { + isa = PBXGroup; + children = ( + 9CB56C091DA35AA800C92F44 /* custom_output.cpp */, + 9CB56C0A1DA35AA800C92F44 /* custom_output.h */, + 9B118AC01D6D0B3A0068B268 /* iOS */, + 9B118ABD1D6D0AFF0068B268 /* debug_output.h */, + 9B118ABC1D6BC12E0068B268 /* log.h */, + 9B4B44A91D2F2D4C0060F1C5 /* log.cpp */, + 9B4B44AB1D2F2D4C0060F1C5 /* log_entry.cpp */, + 9B4B44AC1D2F2D4C0060F1C5 /* log_output.cpp */, + ); + path = Logger; + sourceTree = ""; + }; + 9B5A0FB51BFA603A00BE12FD /* Achievements */ = { + isa = PBXGroup; + children = ( + 9B5A0FB61BFA603A00BE12FD /* achievement.cpp */, + 9B5A0FB71BFA603A00BE12FD /* achievement_media_asset.cpp */, + 9B5A0FB81BFA603A00BE12FD /* achievement_progression.cpp */, + 9B5A0FB91BFA603A00BE12FD /* achievement_requirement.cpp */, + 9B5A0FBA1BFA603A00BE12FD /* achievement_reward.cpp */, + 9B5A0FBB1BFA603A00BE12FD /* achievement_service.cpp */, + 9B5A0FBC1BFA603A00BE12FD /* achievement_time_window.cpp */, + 9B5A0FBD1BFA603A00BE12FD /* achievement_title_association.cpp */, + 9B5A0FBE1BFA603A00BE12FD /* achievements_result.cpp */, + ); + path = Achievements; + sourceTree = ""; + }; + 9B5A0FE71BFA60E000BE12FD /* EntertainmentProfile */ = { + isa = PBXGroup; + children = ( + 9B5A0FE81BFA60E000BE12FD /* entertainment_profile.cpp */, + 9B5A0FE91BFA60E000BE12FD /* entertainment_profile_list_contains_item_result.cpp */, + 9B5A0FEA1BFA60E000BE12FD /* entertainment_profile_list_xbox_one_pins.cpp */, + 9B5A0FEB1BFA60E000BE12FD /* WinRT */, + ); + path = EntertainmentProfile; + sourceTree = ""; + }; + 9B5A0FEB1BFA60E000BE12FD /* WinRT */ = { + isa = PBXGroup; + children = ( + 9B5A0FEC1BFA60E000BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.cpp */, + 9B5A0FED1BFA60E000BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.h */, + 9B5A0FEE1BFA60E000BE12FD /* EntertainmentProfileListService_WinRT.cpp */, + 9B5A0FEF1BFA60E000BE12FD /* EntertainmentProfileListService_WinRT.h */, + 9B5A0FF01BFA60E000BE12FD /* EntertainmentProfileListVideoQueue_WinRT.cpp */, + 9B5A0FF11BFA60E000BE12FD /* EntertainmentProfileListVideoQueue_WinRT.h */, + ); + path = WinRT; + sourceTree = ""; + }; + 9B5A0FF21BFA60E000BE12FD /* Events */ = { + isa = PBXGroup; + children = ( + 9B2956141CE247490026A41C /* events_service.cpp */, + ); + path = Events; + sourceTree = ""; + }; + 9B5A0FF71BFA60E000BE12FD /* GameServerPlatform */ = { + isa = PBXGroup; + children = ( + 9B5A0FF81BFA60E000BE12FD /* allocation_result.cpp */, + 9B5A0FF91BFA60E000BE12FD /* cluster_result.cpp */, + 9B5A0FFA1BFA60E000BE12FD /* game_server_image_set.cpp */, + 9B5A0FFB1BFA60E000BE12FD /* game_server_metadata_result.cpp */, + 9B5A0FFC1BFA60E000BE12FD /* game_server_platform_service.cpp */, + 9B5A0FFD1BFA60E000BE12FD /* game_server_port_mapping.cpp */, + 9B5A0FFE1BFA60E000BE12FD /* game_server_ticket_status.cpp */, + 9B5A0FFF1BFA60E000BE12FD /* game_variant.cpp */, + 9B5A10001BFA60E000BE12FD /* game_variant_schema.cpp */, + 9B5A10011BFA60E000BE12FD /* quality_of_service_server.cpp */, + ); + path = GameServerPlatform; + sourceTree = ""; + }; + 9B5A10191BFA60E000BE12FD /* Leaderboard */ = { + isa = PBXGroup; + children = ( + 9B5A101A1BFA60E000BE12FD /* leaderboard_column.cpp */, + 9B5A101B1BFA60E000BE12FD /* leaderboard_query.h */, + 9B5A101C1BFA60E000BE12FD /* leaderboard_result.cpp */, + 9B5A101D1BFA60E000BE12FD /* leaderboard_row.cpp */, + 9B5A101E1BFA60E000BE12FD /* leaderboard_serializers.cpp */, + 9B5A101F1BFA60E000BE12FD /* leaderboard_serializers.h */, + 9B5A10201BFA60E000BE12FD /* leaderboard_service.cpp */, + ); + path = Leaderboard; + sourceTree = ""; + }; + 9B5A10531BFA60E000BE12FD /* Matchmaking */ = { + isa = PBXGroup; + children = ( + 9B5A10541BFA60E000BE12FD /* create_match_ticket_response.cpp */, + 9B5A10551BFA60E000BE12FD /* hopper_statistics_response.cpp */, + 9B5A10561BFA60E000BE12FD /* match_ticket_details_response.cpp */, + 9B5A10571BFA60E000BE12FD /* matchmaking_service.cpp */, + ); + path = Matchmaking; + sourceTree = ""; + }; + 9B5A10611BFA60E000BE12FD /* Misc */ = { + isa = PBXGroup; + children = ( + 9BF639331D492C3300BDF02B /* contextual_search_game_clip_stat.cpp */, + 9BF639341D492C3300BDF02B /* contextual_search_game_clip_thumbnail.cpp */, + 9BF639351D492C3300BDF02B /* contextual_search_game_clip_uri_info.cpp */, + 9BF639361D492C3300BDF02B /* contextual_search_game_clip.cpp */, + 9BF639371D492C3300BDF02B /* contextual_search_game_clips_result.cpp */, + 32F5FBBD1CE7DB0F008A5E09 /* iOS */, + 9B847EB51CDD6928004E04B0 /* notification_service.cpp */, + 9B847EAD1CDD27A1004E04B0 /* notification_service.h */, + 9B847EAF1CDD2823004E04B0 /* Unix */, + 9B5A10621BFA60E000BE12FD /* contextual_config_result.cpp */, + 9B5A10631BFA60E000BE12FD /* contextual_config_result.h */, + 9B5A10641BFA60E000BE12FD /* contextual_search_broadcast.cpp */, + 9B5A10651BFA60E000BE12FD /* contextual_search_configured_stat.cpp */, + 9B5A10661BFA60E000BE12FD /* contextual_search_service.cpp */, + 9B5A10691BFA60E000BE12FD /* string_service.cpp */, + 9B5A106B1BFA60E000BE12FD /* verify_string_result.cpp */, + ); + path = Misc; + sourceTree = ""; + }; + 9B5A107E1BFA60E000BE12FD /* Multiplayer */ = { + isa = PBXGroup; + children = ( + 9BEB14F91DCD01BF001E5DD5 /* multiplayer_member_initialization.cpp */, + 9CB56C051DA359BB00C92F44 /* multiplayer_query_search_handle_request.cpp */, + 9B118A921D4BFF070068B268 /* multiplayer_role_info.cpp */, + 9B118A931D4BFF070068B268 /* multiplayer_role_type.cpp */, + 9B118A941D4BFF070068B268 /* multiplayer_session_role_types.cpp */, + 9BAEFDEA1D3019B300ABBA82 /* multiplayer_search_handle_details.cpp */, + 9BAEFDEB1D3019B300ABBA82 /* multiplayer_search_handle_request.cpp */, + 255A36A21CD834F400D3AD8E /* Manager */, + 9B8250311C1A4A8F002C8F30 /* multiplayer_session_tournaments_server.cpp */, + 9B82502C1C1A397F002C8F30 /* multiplayer_session_arbitration_server.cpp */, + 9B5A10BE1BFA60E000BE12FD /* multiplayer_activity_details.cpp */, + 9B5A10BF1BFA60E000BE12FD /* multiplayer_activity_handle_post_request.cpp */, + 9B5A10C01BFA60E000BE12FD /* multiplayer_activity_query_post_request.cpp */, + 9B5A10C11BFA60E000BE12FD /* multiplayer_get_sessions_request.cpp */, + 9B5A10C21BFA60E000BE12FD /* multiplayer_internal.h */, + 9B5A10C31BFA60E000BE12FD /* multiplayer_invite.cpp */, + 9B5A10C41BFA60E000BE12FD /* multiplayer_invite_handle_post_request.cpp */, + 9B5A10C51BFA60E000BE12FD /* multiplayer_managed_initialization.cpp */, + 9B5A10C61BFA60E000BE12FD /* multiplayer_peer_to_host_requirements.cpp */, + 9B5A10C71BFA60E000BE12FD /* multiplayer_peer_to_peer_requirements.cpp */, + 9B5A10C81BFA60E000BE12FD /* multiplayer_quality_of_service_measurement.cpp */, + 9B5A10C91BFA60E000BE12FD /* multiplayer_service.cpp */, + 9B5A10CA1BFA60E000BE12FD /* multiplayer_service_impl.cpp */, + 9B5A10CB1BFA60E000BE12FD /* multiplayer_session.cpp */, + 9B5A10CC1BFA60E000BE12FD /* multiplayer_session_capabilities.cpp */, + 9B5A10CD1BFA60E000BE12FD /* multiplayer_session_change_event_args.cpp */, + 9B5A10CE1BFA60E000BE12FD /* multiplayer_session_constants.cpp */, + 9B5A10CF1BFA60E000BE12FD /* multiplayer_session_matchmaking_server.cpp */, + 9B5A10D01BFA60E000BE12FD /* multiplayer_session_member.cpp */, + 9B5A10D11BFA60E000BE12FD /* multiplayer_session_member_request.cpp */, + 9B5A10D21BFA60E000BE12FD /* multiplayer_session_properties.cpp */, + 9B5A10D31BFA60E000BE12FD /* multiplayer_session_reference.cpp */, + 9B5A10D41BFA60E000BE12FD /* multiplayer_session_request.cpp */, + 9B5A10D51BFA60E000BE12FD /* multiplayer_session_states.cpp */, + 9B5A10D61BFA60E000BE12FD /* multiplayer_subscription.cpp */, + 9B5A10D71BFA60E000BE12FD /* multiplayer_transfer_handle_post_request.cpp */, + ); + path = Multiplayer; + sourceTree = ""; + }; + 9B5A11091BFA60E000BE12FD /* Presence */ = { + isa = PBXGroup; + children = ( + 9B5A110A1BFA60E000BE12FD /* device_presence_change_event_args.cpp */, + 9B5A110B1BFA60E000BE12FD /* device_presence_change_subscription.cpp */, + 9B5A110C1BFA60E000BE12FD /* media_presence_data.cpp */, + 9B5A110D1BFA60E000BE12FD /* presence_activity_data.cpp */, + 9B5A110E1BFA60E000BE12FD /* presence_broadcast_record.cpp */, + 9B5A110F1BFA60E000BE12FD /* presence_data.cpp */, + 9B5A11101BFA60E000BE12FD /* presence_device_record.cpp */, + 9B5A11111BFA60E000BE12FD /* presence_internal.h */, + 9B5A11121BFA60E000BE12FD /* presence_media_record.cpp */, + 9B5A11131BFA60E000BE12FD /* presence_record.cpp */, + 9B5A11141BFA60E000BE12FD /* presence_service.cpp */, + 9B5A11151BFA60E000BE12FD /* presence_service_impl.cpp */, + 9B5A11161BFA60E000BE12FD /* presence_title_record.cpp */, + 9B5A11171BFA60E000BE12FD /* presence_title_request.cpp */, + 9B5A11181BFA60E000BE12FD /* presence_user_batch_request.cpp */, + 9B5A11191BFA60E000BE12FD /* presence_writer.cpp */, + 9B5A111A1BFA60E000BE12FD /* title_presence_change_event_args.cpp */, + 9B5A111B1BFA60E000BE12FD /* title_presence_change_subscription.cpp */, + ); + path = Presence; + sourceTree = ""; + }; + 9B5A11391BFA60E000BE12FD /* Privacy */ = { + isa = PBXGroup; + children = ( + 9B5A113A1BFA60E000BE12FD /* multiple_permissions_check_result.cpp */, + 9B5A113B1BFA60E000BE12FD /* permission_check_result.cpp */, + 9B5A113C1BFA60E000BE12FD /* permission_deny_reason.cpp */, + 9B5A113D1BFA60E000BE12FD /* privacy_service.cpp */, + ); + path = Privacy; + sourceTree = ""; + }; + 9B5A11491BFA60E000BE12FD /* RealTimeActivity */ = { + isa = PBXGroup; + children = ( + 9B4B449F1D2F22C30060F1C5 /* real_time_activity_internal.h */, + 9B4B44A01D2F22C30060F1C5 /* real_time_activity_service_factory.cpp */, + 9B5A114A1BFA60E000BE12FD /* real_time_activity_service.cpp */, + 9B5A114B1BFA60E000BE12FD /* real_time_activity_subscription.cpp */, + 9B5A114C1BFA60E000BE12FD /* real_time_activity_subscription_error_event_args.cpp */, + ); + path = RealTimeActivity; + sourceTree = ""; + }; + 9B5A11571BFA60E000BE12FD /* Social */ = { + isa = PBXGroup; + children = ( + 9CDF0D281DA2E85B0046C721 /* Manager */, + 9B5A11711BFA60E000BE12FD /* profile_service.cpp */, + 9B5A11721BFA60E000BE12FD /* reputation_feedback_request.cpp */, + 9B5A11731BFA60E000BE12FD /* reputation_service.cpp */, + 9B5A11741BFA60E000BE12FD /* social_internal.h */, + 9B5A11751BFA60E000BE12FD /* social_relationship_change_event_args.cpp */, + 9B5A11761BFA60E000BE12FD /* social_relationship_change_subscription.cpp */, + 9B5A11771BFA60E000BE12FD /* social_service.cpp */, + 9B5A11781BFA60E000BE12FD /* social_service_impl.cpp */, + 9B5A11911BFA60E000BE12FD /* xbox_social_relationship.cpp */, + 9B5A11921BFA60E000BE12FD /* xbox_social_relationship_result.cpp */, + 9B5A11931BFA60E000BE12FD /* xbox_user_profile.cpp */, + ); + path = Social; + sourceTree = ""; + }; + 9B5A11941BFA60E000BE12FD /* Stats */ = { + isa = PBXGroup; + children = ( + 9B5A11951BFA60E000BE12FD /* requested_statistics.cpp */, + 9B5A11961BFA60E000BE12FD /* service_configuration_statistic.cpp */, + 9B5A11971BFA60E100BE12FD /* statistic.cpp */, + 9B5A11981BFA60E100BE12FD /* statistic_change_event_args.cpp */, + 9B5A11991BFA60E100BE12FD /* statistic_change_subscription.cpp */, + 9B5A119A1BFA60E100BE12FD /* user_statistics_internal.h */, + 9B5A119B1BFA60E100BE12FD /* user_statistics_result.cpp */, + 9B5A119C1BFA60E100BE12FD /* user_statistics_service.cpp */, + 9B5A119D1BFA60E100BE12FD /* user_statistics_service_impl.cpp */, + ); + path = Stats; + sourceTree = ""; + }; + 9B5A11AD1BFA60E100BE12FD /* TitleStorage */ = { + isa = PBXGroup; + children = ( + 9B5A11AE1BFA60E100BE12FD /* title_storage_blob_metadata.cpp */, + 9B5A11AF1BFA60E100BE12FD /* title_storage_blob_metadata_result.cpp */, + 9B5A11B01BFA60E100BE12FD /* title_storage_blob_result.cpp */, + 9B5A11B11BFA60E100BE12FD /* title_storage_quota.cpp */, + 9B5A11B21BFA60E100BE12FD /* title_storage_service.cpp */, + ); + path = TitleStorage; + sourceTree = ""; + }; + 9B5A12C81BFBF63600BE12FD /* iOS */ = { + isa = PBXGroup; + children = ( + 9B5A12C91BFBF63600BE12FD /* pch.cpp */, + 9B5A12CA1BFBF63600BE12FD /* pch.h */, + ); + path = iOS; + sourceTree = ""; + }; + 9B5A12CD1BFD2BF200BE12FD /* Tournaments */ = { + isa = PBXGroup; + children = ( + 9B8250331C1A4B34002C8F30 /* tournament_reference.cpp */, + 9B5A12D31BFD2BF200BE12FD /* tournament_team_result.cpp */, + ); + path = Tournaments; + sourceTree = ""; + }; + 9B66D2CD1BE85B5C00E53086 /* Products */ = { + isa = PBXGroup; + children = ( + 9B66D2D11BE85B5C00E53086 /* libCasablanca.a */, + ); + name = Products; + sourceTree = ""; + }; + 9B847EAF1CDD2823004E04B0 /* Unix */ = { + isa = PBXGroup; + children = ( + 9B847EB11CDD2823004E04B0 /* notification_service_i.mm */, + ); + path = Unix; + sourceTree = ""; + }; + 9B8A00AE1BF2778B000337EA /* iOS */ = { + isa = PBXGroup; + children = ( + 9B118AD81D885F960068B268 /* auth */, + 9B2956101CE244CD0026A41C /* xbox_cll.mm */, + B71305621CC7465D00A4E71E /* XboxTelemetry */, + 6718D8B11C865E23007FD4F6 /* Xbox UI Delegates */, + 67210E181C6479E20008FFDB /* Xbox Sign In UI */, + 6718F1BF1CB76BF50000BF6E /* XBLServiceManager.h */, + 6718F1C01CB76BF50000BF6E /* XBLServiceManager.mm */, + 6718F1E31CB77FEB0000BF6E /* XBLDictionaryToJSON.h */, + 6718F1E41CB77FEB0000BF6E /* XBLDictionaryToJSON.mm */, + 677B9FCB1CD90F2900A28F96 /* XBLiOSGlobalState.h */, + 677B9FCC1CD90F2900A28F96 /* XBLiOSGlobalState.mm */, + 67F503A31CD98D8E00198DEA /* xbox_live_app_config_ios.mm */, + ); + path = iOS; + sourceTree = ""; + }; + 9B9615DE1BEA86FE00E79527 /* Desktop */ = { + isa = PBXGroup; + children = ( + 9B9615E21BEA86FE00E79527 /* XboxLiveContext_Desktop.cpp */, + ); + path = Desktop; + sourceTree = ""; + }; + 9B9615E71BEA962600E79527 /* Unix */ = { + isa = PBXGroup; + children = ( + 9B9615E91BEA962600E79527 /* pch_unix.h */, + ); + path = Unix; + sourceTree = ""; + }; + 9B97B3521BE18B2500CF1E29 = { + isa = PBXGroup; + children = ( + 9B4933F91CE8F29E00E7CE0B /* WebKit.framework */, + 6718D9151C9F69CA007FD4F6 /* CoreText.framework */, + 670AA2F51C7657D300B3FB9A /* SystemConfiguration.framework */, + 9B46ED4D1BED720E00076704 /* UIKit.framework */, + 6718F1881CB731EF0000BF6E /* XSAPITCUI.xcodeproj */, + 9B66D2CC1BE85B5C00E53086 /* Casablanca.xcodeproj */, + 9B97BAB91BE1A1B000CF1E29 /* xsapi */, + 9B97B3831BE1981800CF1E29 /* Source */, + 67A963861C5FE4250066184E /* XboxLiveServicesResources */, + 9B97B35C1BE18B2600CF1E29 /* Products */, + ); + sourceTree = ""; + }; + 9B97B35C1BE18B2600CF1E29 /* Products */ = { + isa = PBXGroup; + children = ( + 9B97B35B1BE18B2600CF1E29 /* libXboxLiveServices.a */, + ); + name = Products; + sourceTree = ""; + }; + 9B97B3831BE1981800CF1E29 /* Source */ = { + isa = PBXGroup; + children = ( + 9B97B7881BE19DFC00CF1E29 /* Services */, + 9B97B5931BE1981900CF1E29 /* Shared */, + 9B97B5CD1BE1981900CF1E29 /* System */, + ); + name = Source; + path = ../../Source; + sourceTree = ""; + }; + 9B97B5931BE1981900CF1E29 /* Shared */ = { + isa = PBXGroup; + children = ( + 9CB56C071DA35A4500C92F44 /* xbox_live_services_settings.cpp */, + 9C063B111D774C28009C3E3C /* mem.cpp */, + 9BAEFDEE1D30263F00ABBA82 /* initiator.cpp */, + 9BAEFDEF1D30263F00ABBA82 /* initiator.h */, + 9B4B44A41D2F2D4C0060F1C5 /* Logger */, + 9BBAB79B1CC0405100A75EDF /* i */, + 9BBAB7761CBDE08500A75EDF /* u */, + 9B46ED501BF105A000076704 /* xbox_system_factory_ios.mm */, + 9B97B5941BE1981900CF1E29 /* build_version.h */, + 9B97B5971BE1981900CF1E29 /* errors.cpp */, + 9B97B5981BE1981900CF1E29 /* http_call_impl.cpp */, + 9B97B5991BE1981900CF1E29 /* http_call_impl.h */, + 9B97B59A1BE1981900CF1E29 /* http_call_request_message.cpp */, + 9B97B59B1BE1981900CF1E29 /* http_call_response.cpp */, + 9B97B59C1BE1981900CF1E29 /* http_call_response.h */, + 9B97B59D1BE1981900CF1E29 /* http_client.cpp */, + 9B97B59E1BE1981900CF1E29 /* http_client.h */, + 9B97B59F1BE1981900CF1E29 /* local_config.cpp */, + 9B97B5A01BE1981900CF1E29 /* local_config.h */, + 9B97B5A11BE1981900CF1E29 /* service_call_logger.cpp */, + 9B97B5A21BE1981900CF1E29 /* service_call_logger.h */, + 9B97B5A31BE1981900CF1E29 /* service_call_logger_data.cpp */, + 9B97B5A41BE1981900CF1E29 /* service_call_logger_data.h */, + 9B97B5A71BE1981900CF1E29 /* service_call_logging_config.cpp */, + 9B97B5A81BE1981900CF1E29 /* shared_macros.h */, + 9B97B5A91BE1981900CF1E29 /* telemetry.cpp */, + 9B97B5AA1BE1981900CF1E29 /* telemetry.h */, + 9B97B5AB1BE1981900CF1E29 /* user_context.cpp */, + 9B97B5AC1BE1981900CF1E29 /* user_context.h */, + 9B97B5AD1BE1981900CF1E29 /* utils.cpp */, + 9B97B5AE1BE1981900CF1E29 /* utils.h */, + 9B97B5AF1BE1981900CF1E29 /* utils_locales.cpp */, + 9B97B5B01BE1981900CF1E29 /* web_socket_client.cpp */, + 9B97B5B11BE1981900CF1E29 /* web_socket_client.h */, + 9B97B5B21BE1981900CF1E29 /* web_socket_connection.cpp */, + 9B97B5B31BE1981900CF1E29 /* web_socket_connection.h */, + 9B97B5B41BE1981900CF1E29 /* web_socket_connection_state.h */, + 9B97B5C81BE1981900CF1E29 /* xbox_live_app_config.cpp */, + 9B97B5C91BE1981900CF1E29 /* xbox_live_context_settings.cpp */, + 9B97B5CA1BE1981900CF1E29 /* xbox_service_call_routed_event_args.cpp */, + 9B97B5CB1BE1981900CF1E29 /* xbox_system_factory.cpp */, + 9B97B5CC1BE1981900CF1E29 /* xbox_system_factory.h */, + ); + path = Shared; + sourceTree = ""; + }; + 9B97B5CD1BE1981900CF1E29 /* System */ = { + isa = PBXGroup; + children = ( + 9C4DF1B01DA32E6A00224A7C /* ppltasks_extra_unix.h */, + 9B118ADF1D8B35230068B268 /* user_impl_ios.h */, + 9B118AE01D8B35230068B268 /* user_impl_ios.mm */, + 9B8A00AE1BF2778B000337EA /* iOS */, + 9B46ED541BF14AFA00076704 /* user_ios.mm */, + 9B97B5CE1BE1981900CF1E29 /* auth */, + 9B97B6001BE1981900CF1E29 /* auth_config.cpp */, + 9B97B6011BE1981900CF1E29 /* auth_config.h */, + 9B97B6021BE1981900CF1E29 /* system_internal.h */, + 9B97B6031BE1981900CF1E29 /* token_and_signature_result.cpp */, + 9B97B6041BE1981900CF1E29 /* user.cpp */, + 9B97B6051BE1981900CF1E29 /* user_impl.cpp */, + 9B97B6061BE1981900CF1E29 /* user_impl.h */, + 9B97B6101BE1981900CF1E29 /* xbox_live_mutex.cpp */, + ); + path = System; + sourceTree = ""; + }; + 9B97B5CE1BE1981900CF1E29 /* auth */ = { + isa = PBXGroup; + children = ( + 9BF132411C3C48230048204E /* device_token_service.cpp */, + 9BF132421C3C48230048204E /* device_token_service.h */, + 9BF11AD51C120C2900D111C9 /* Desktop */, + 9B46ED431BED41D600076704 /* Unix */, + 9B97B5CF1BE1981900CF1E29 /* auth_manager.cpp */, + 9B97B5D01BE1981900CF1E29 /* auth_manager.h */, + 9B97B5D11BE1981900CF1E29 /* cidr.cpp */, + 9B97B5D21BE1981900CF1E29 /* cidr.h */, + 9B97B5DB1BE1981900CF1E29 /* ecdsa.h */, + 9B97B5DC1BE1981900CF1E29 /* ip_address.cpp */, + 9B97B5DD1BE1981900CF1E29 /* ip_address.h */, + 9B97B5DE1BE1981900CF1E29 /* json_web_key.cpp */, + 9B97B5DF1BE1981900CF1E29 /* json_web_key.h */, + 9B97B5E01BE1981900CF1E29 /* nsal.cpp */, + 9B97B5E11BE1981900CF1E29 /* nsal.h */, + 9B97B5E21BE1981900CF1E29 /* nsal_endpoint.cpp */, + 9B97B5E31BE1981900CF1E29 /* nsal_endpoint.h */, + 9B97B5E41BE1981900CF1E29 /* request_signer.h */, + 9B97B5E51BE1981900CF1E29 /* request_signer_helpers.cpp */, + 9B97B5E61BE1981900CF1E29 /* request_signer_helpers.h */, + 9B97B5E91BE1981900CF1E29 /* signature_policy.cpp */, + 9B97B5EA1BE1981900CF1E29 /* signature_policy.h */, + 9B97B5EB1BE1981900CF1E29 /* title_token_service.cpp */, + 9B97B5EC1BE1981900CF1E29 /* title_token_service.h */, + 9B97B5ED1BE1981900CF1E29 /* token_error.cpp */, + 9B97B5EE1BE1981900CF1E29 /* token_error.h */, + 9B97B5EF1BE1981900CF1E29 /* token_manager.cpp */, + 9B97B5F01BE1981900CF1E29 /* token_manager.h */, + 9B97B5F11BE1981900CF1E29 /* token_request.cpp */, + 9B97B5F21BE1981900CF1E29 /* token_request.h */, + 9B97B5F31BE1981900CF1E29 /* token_result.cpp */, + 9B97B5F41BE1981900CF1E29 /* token_result.h */, + 9B97B5F51BE1981900CF1E29 /* trie.cpp */, + 9B97B5F61BE1981900CF1E29 /* trie.h */, + 9B97B5F71BE1981900CF1E29 /* user_token_service.cpp */, + 9B97B5F81BE1981900CF1E29 /* user_token_service.h */, + 9B97B5FC1BE1981900CF1E29 /* xsts_token_service.cpp */, + 9B97B5FD1BE1981900CF1E29 /* xsts_token_service.h */, + 9B97B5FE1BE1981900CF1E29 /* xtitle_service.cpp */, + 9B97B5FF1BE1981900CF1E29 /* xtitle_service.h */, + ); + path = auth; + sourceTree = ""; + }; + 9B97B7881BE19DFC00CF1E29 /* Services */ = { + isa = PBXGroup; + children = ( + 9B5A12CD1BFD2BF200BE12FD /* Tournaments */, + 9B5A0FE71BFA60E000BE12FD /* EntertainmentProfile */, + 9B5A0FF21BFA60E000BE12FD /* Events */, + 9B5A0FF71BFA60E000BE12FD /* GameServerPlatform */, + 9B5A10191BFA60E000BE12FD /* Leaderboard */, + 9B5A10531BFA60E000BE12FD /* Matchmaking */, + 9B5A10611BFA60E000BE12FD /* Misc */, + 9B5A107E1BFA60E000BE12FD /* Multiplayer */, + 9B5A11091BFA60E000BE12FD /* Presence */, + 9B5A11391BFA60E000BE12FD /* Privacy */, + 9B5A11491BFA60E000BE12FD /* RealTimeActivity */, + 9B5A11571BFA60E000BE12FD /* Social */, + 9B5A11941BFA60E000BE12FD /* Stats */, + 9B5A11AD1BFA60E100BE12FD /* TitleStorage */, + 9B5A0FB51BFA603A00BE12FD /* Achievements */, + 9B97B7AA1BE19DFC00CF1E29 /* Common */, + ); + path = Services; + sourceTree = ""; + }; + 9B97B7AA1BE19DFC00CF1E29 /* Common */ = { + isa = PBXGroup; + children = ( + 9B5A12C81BFBF63600BE12FD /* iOS */, + 9B9615E71BEA962600E79527 /* Unix */, + 9B9615DE1BEA86FE00E79527 /* Desktop */, + 9B97B7B21BE19DFC00CF1E29 /* pch_common.h */, + 9B97B7BB1BE19DFC00CF1E29 /* xbox_live_context_impl.cpp */, + 9B97B7BC1BE19DFC00CF1E29 /* xbox_live_context_impl.h */, + ); + path = Common; + sourceTree = ""; + }; + 9B97BAB91BE1A1B000CF1E29 /* xsapi */ = { + isa = PBXGroup; + children = ( + 9C063B131D774FD7009C3E3C /* mem.h */, + 9B4B44D11D2FFE850060F1C5 /* multiplayer_manager.h */, + 9B4934761CEE1C0A00E7CE0B /* notification_helper.h */, + 9BA103321CB72BEA0012374B /* i */, + 9BF11AE61C17ABA400D111C9 /* multiplayer.h */, + 9BA63DBD1BE43C8900BFC445 /* presence_internal.h */, + 9B97BABA1BE1A1B000CF1E29 /* achievements.h */, + 9B97BABB1BE1A1B000CF1E29 /* contextual_search_service.h */, + 9B97BABC1BE1A1B000CF1E29 /* entertainment_profile.h */, + 9B97BABD1BE1A1B000CF1E29 /* errors.h */, + 9B97BABE1BE1A1B000CF1E29 /* events.h */, + 9B97BABF1BE1A1B000CF1E29 /* game_server_platform.h */, + 9B97BAC01BE1A1B000CF1E29 /* http_call.h */, + 9B97BAC11BE1A1B000CF1E29 /* http_call_request_message.h */, + 9B97BAC21BE1A1B000CF1E29 /* leaderboard.h */, + 9B97BAC41BE1A1B000CF1E29 /* matchmaking.h */, + 9B97BAC71BE1A1B000CF1E29 /* presence.h */, + 9B97BAC81BE1A1B000CF1E29 /* privacy.h */, + 9B97BAC91BE1A1B000CF1E29 /* profile.h */, + 9B97BACA1BE1A1B000CF1E29 /* real_time_activity.h */, + 9B97BACB1BE1A1B000CF1E29 /* service_call_logging_config.h */, + 9B97BACC1BE1A1B000CF1E29 /* services.h */, + 9B97BACD1BE1A1B000CF1E29 /* social.h */, + 9B97BACF1BE1A1B000CF1E29 /* system.h */, + 9B97BAD01BE1A1B000CF1E29 /* title_callable_ui.h */, + 9B97BAD11BE1A1B000CF1E29 /* title_storage.h */, + 9B97BAD21BE1A1B000CF1E29 /* types.h */, + 9B97BAD31BE1A1B000CF1E29 /* user_statistics.h */, + 671F66D51CD439BC00119106 /* xbox_live_app_config.h */, + 9B97BAD51BE1A1B000CF1E29 /* xbox_live_context.h */, + 9B97BAD61BE1A1B000CF1E29 /* xbox_live_context_settings.h */, + 9B97BAD71BE1A1B000CF1E29 /* xbox_service_call_routed_event_args.h */, + 671F66D21CD439BC00119106 /* marketplace.h */, + 671F66D41CD439BC00119106 /* social_manager.h */, + 9B2956111CE244CD0026A41C /* xbox_cll.h */, + ); + name = xsapi; + path = ../../Include/xsapi; + sourceTree = ""; + }; + 9BA103321CB72BEA0012374B /* i */ = { + isa = PBXGroup; + children = ( + ); + name = i; + sourceTree = ""; + }; + 9BBAB7761CBDE08500A75EDF /* u */ = { + isa = PBXGroup; + children = ( + 9BBAB7771CBDE09000A75EDF /* local_config_u.cpp */, + ); + name = u; + sourceTree = ""; + }; + 9BBAB79B1CC0405100A75EDF /* i */ = { + isa = PBXGroup; + children = ( + 9BBAB79C1CC0408200A75EDF /* local_config_i.mm */, + 251DBDD61CE6DE41003AF56B /* utils_locales_ios.mm */, + ); + name = i; + sourceTree = ""; + }; + 9BF11AD51C120C2900D111C9 /* Desktop */ = { + isa = PBXGroup; + children = ( + 9BF11AD91C120C2900D111C9 /* ip_address_desktop.cpp */, + ); + path = Desktop; + sourceTree = ""; + }; + 9CDF0D281DA2E85B0046C721 /* Manager */ = { + isa = PBXGroup; + children = ( + 9CC36FE21DB6DE89007142EE /* xbox_user_id_container.cpp */, + 9CDF0D291DA2E8860046C721 /* internal_social_event.cpp */, + 9CDF0D2A1DA2E8860046C721 /* peoplehub_service.cpp */, + 9CDF0D2B1DA2E8860046C721 /* preferred_color.cpp */, + 9CDF0D2C1DA2E8860046C721 /* social_event.cpp */, + 9CDF0D2D1DA2E8860046C721 /* social_graph.cpp */, + 9CDF0D2E1DA2E8860046C721 /* social_manager_internal.h */, + 9CDF0D2F1DA2E8860046C721 /* social_manager_presence_record.cpp */, + 9CDF0D301DA2E8860046C721 /* social_manager_presence_title_record.cpp */, + 9CDF0D311DA2E8860046C721 /* social_manager.cpp */, + 9CDF0D321DA2E8860046C721 /* social_user_group_loaded_event_args.cpp */, + 9CDF0D331DA2E8860046C721 /* title_history.cpp */, + 9CDF0D341DA2E8860046C721 /* xbox_social_user_group.cpp */, + 9CDF0D351DA2E8860046C721 /* xbox_social_user.cpp */, + ); + name = Manager; + sourceTree = ""; + }; + B71305621CC7465D00A4E71E /* XboxTelemetry */ = { + isa = PBXGroup; + children = ( + B7E5C76B1CEED3E5003B2B08 /* UTCIDPNames.h */, + B7E5C76C1CEED3E5003B2B08 /* UTCIDPNames.mm */, + B71305831CC747AD00A4E71E /* XLSCll.h */, + B71305811CC7477A00A4E71E /* XLSCll.mm */, + ); + name = XboxTelemetry; + path = XboxSignInUI; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9B97B35A1BE18B2600CF1E29 /* XboxLiveServices */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9B97B3641BE18B2600CF1E29 /* Build configuration list for PBXNativeTarget "XboxLiveServices" */; + buildPhases = ( + 9B97B3571BE18B2600CF1E29 /* Sources */, + 9B97B3581BE18B2600CF1E29 /* Frameworks */, + 9B97B3591BE18B2600CF1E29 /* CopyFiles */, + 6715CBF21C5BD28800F00C03 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 671121B71CBD960100F49259 /* PBXTargetDependency */, + 9B8250301C1A46B7002C8F30 /* PBXTargetDependency */, + ); + name = XboxLiveServices; + productName = XboxLiveServices; + productReference = 9B97B35B1BE18B2600CF1E29 /* libXboxLiveServices.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9B97B3531BE18B2500CF1E29 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = "Microsoft Corporation"; + TargetAttributes = { + 9B97B35A1BE18B2600CF1E29 = { + CreatedOnToolsVersion = 7.1; + }; + }; + }; + buildConfigurationList = 9B97B3561BE18B2500CF1E29 /* Build configuration list for PBXProject "XboxLiveServices" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9B97B3521BE18B2500CF1E29; + productRefGroup = 9B97B35C1BE18B2600CF1E29 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 9B66D2CD1BE85B5C00E53086 /* Products */; + ProjectRef = 9B66D2CC1BE85B5C00E53086 /* Casablanca.xcodeproj */; + }, + { + ProductGroup = 6781BDAE1CBC702100264EAF /* Products */; + ProjectRef = 6718F1881CB731EF0000BF6E /* XSAPITCUI.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 9B97B35A1BE18B2600CF1E29 /* XboxLiveServices */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 6781BDB31CBC702100264EAF /* XSAPITCUI.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = XSAPITCUI.framework; + remoteRef = 6781BDB21CBC702100264EAF /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 9B66D2D11BE85B5C00E53086 /* libCasablanca.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libCasablanca.a; + remoteRef = 9B66D2D01BE85B5C00E53086 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 6715CBF21C5BD28800F00C03 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 255A36DE1CD8353B00D3AD8E /* WinRT in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9B97B3571BE18B2600CF1E29 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B82502E1C1A40DF002C8F30 /* multiplayer_session_arbitration_server.cpp in Sources */, + 9B97B75B1BE1981B00CF1E29 /* token_error.cpp in Sources */, + 9B5A12BF1BFA60E100BE12FD /* title_storage_blob_metadata_result.cpp in Sources */, + 9B97B7571BE1981B00CF1E29 /* request_signer_helpers.cpp in Sources */, + 9B97B7331BE1981B00CF1E29 /* http_call_response.cpp in Sources */, + 9B97B7541BE1981B00CF1E29 /* json_web_key.cpp in Sources */, + 9B5A12421BFA60E100BE12FD /* multiplayer_quality_of_service_measurement.cpp in Sources */, + 9B5A12821BFA60E100BE12FD /* permission_deny_reason.cpp in Sources */, + 255A36DD1CD8353B00D3AD8E /* user_removed_event_args.cpp in Sources */, + 9B97B73D1BE1981B00CF1E29 /* utils_locales.cpp in Sources */, + 9B97B7641BE1981C00CF1E29 /* xtitle_service.cpp in Sources */, + 255A36D31CD8353B00D3AD8E /* multiplayer_local_user.cpp in Sources */, + 9B97B74D1BE1981B00CF1E29 /* cidr.cpp in Sources */, + 255A36CA1CD8353B00D3AD8E /* multiplayer_client_manager.cpp in Sources */, + 9B8250321C1A4A8F002C8F30 /* multiplayer_session_tournaments_server.cpp in Sources */, + 9B5A12F11BFD2BF200BE12FD /* tournament_game.cpp in Sources */, + 9B5A12CB1BFBF63600BE12FD /* pch.cpp in Sources */, + 255A36D41CD8353B00D3AD8E /* multiplayer_manager_utils.cpp in Sources */, + 9BAEFDED1D3019B300ABBA82 /* multiplayer_search_handle_request.cpp in Sources */, + 9B5A12C11BFA60E100BE12FD /* title_storage_quota.cpp in Sources */, + 9B97B9AD1BE19DFD00CF1E29 /* xbox_live_context_impl.cpp in Sources */, + 9B5A12A31BFA60E100BE12FD /* social_service_impl.cpp in Sources */, + 9BAEFDEC1D3019B300ABBA82 /* multiplayer_search_handle_details.cpp in Sources */, + 9B5A126F1BFA60E100BE12FD /* presence_title_record.cpp in Sources */, + 9B2956151CE247490026A41C /* events_service.cpp in Sources */, + 255A36C51CD8353B00D3AD8E /* join_lobby_completed_event_args.cpp in Sources */, + 9B97B7531BE1981B00CF1E29 /* ip_address.cpp in Sources */, + 9B5A129E1BFA60E100BE12FD /* reputation_feedback_request.cpp in Sources */, + 9BEB14FA1DCD01BF001E5DD5 /* multiplayer_member_initialization.cpp in Sources */, + 9B5A12A21BFA60E100BE12FD /* social_service.cpp in Sources */, + 9B5A0FDB1BFA603A00BE12FD /* achievement_service.cpp in Sources */, + 9CDF0D3E1DA2E8860046C721 /* social_user_group_loaded_event_args.cpp in Sources */, + 9B5A12671BFA60E100BE12FD /* presence_activity_data.cpp in Sources */, + 9B5A0FDE1BFA603A00BE12FD /* achievements_result.cpp in Sources */, + 9B97B73A1BE1981B00CF1E29 /* telemetry.cpp in Sources */, + 9B118AC21D6D0B460068B268 /* debug_output_ios.cpp in Sources */, + 9B5A12051BFA60E100BE12FD /* contextual_search_configured_stat.cpp in Sources */, + 9BF639391D492C3300BDF02B /* contextual_search_game_clip_thumbnail.cpp in Sources */, + 9B5A0FDD1BFA603A00BE12FD /* achievement_title_association.cpp in Sources */, + 9B97B7321BE1981B00CF1E29 /* http_call_request_message.cpp in Sources */, + 9B4934791CEE1C1800E7CE0B /* notification_helper.mm in Sources */, + 9CC36FE31DB6DE89007142EE /* xbox_user_id_container.cpp in Sources */, + 9B97B7361BE1981B00CF1E29 /* service_call_logger.cpp in Sources */, + 9CDF0D411DA2E8860046C721 /* xbox_social_user.cpp in Sources */, + 9B5A123B1BFA60E100BE12FD /* multiplayer_activity_query_post_request.cpp in Sources */, + 9CDF0D361DA2E8860046C721 /* internal_social_event.cpp in Sources */, + 9B5A12641BFA60E100BE12FD /* device_presence_change_event_args.cpp in Sources */, + 9B97B7481BE1981B00CF1E29 /* xbox_live_app_config.cpp in Sources */, + 9B5A11D01BFA60E100BE12FD /* game_variant.cpp in Sources */, + 9B5A12001BFA60E100BE12FD /* matchmaking_service.cpp in Sources */, + 9B97B73E1BE1981B00CF1E29 /* web_socket_client.cpp in Sources */, + 9B5A12661BFA60E100BE12FD /* media_presence_data.cpp in Sources */, + 9B5A123F1BFA60E100BE12FD /* multiplayer_managed_initialization.cpp in Sources */, + 9CDF0D3B1DA2E8860046C721 /* social_manager_presence_record.cpp in Sources */, + 9B8250341C1A4B34002C8F30 /* tournament_reference.cpp in Sources */, + 9B5A12501BFA60E100BE12FD /* multiplayer_subscription.cpp in Sources */, + 9B5A0FD61BFA603A00BE12FD /* achievement.cpp in Sources */, + 9CDF0D391DA2E8860046C721 /* social_event.cpp in Sources */, + 9B97B7661BE1981C00CF1E29 /* token_and_signature_result.cpp in Sources */, + 9B5A123A1BFA60E100BE12FD /* multiplayer_activity_handle_post_request.cpp in Sources */, + 9B5A12B11BFA60E100BE12FD /* statistic.cpp in Sources */, + 6718F1C11CB76BF50000BF6E /* XBLServiceManager.mm in Sources */, + 9B4B44B01D2F2D4C0060F1C5 /* log_entry.cpp in Sources */, + 9B2956121CE244CD0026A41C /* xbox_cll.mm in Sources */, + 9B5A12AE1BFA60E100BE12FD /* xbox_user_profile.cpp in Sources */, + 9BAEFDF01D30263F00ABBA82 /* initiator.cpp in Sources */, + 9B118ADB1D885FA80068B268 /* user_auth_ios.mm in Sources */, + 9B5A12F61BFD2BF200BE12FD /* tournament_teams.cpp in Sources */, + 6718D8B01C865AD0007FD4F6 /* XboxProviderBridge.cpp in Sources */, + 9B5A12A11BFA60E100BE12FD /* social_relationship_change_subscription.cpp in Sources */, + 255A36C71CD8353B00D3AD8E /* member_joined_event_args.cpp in Sources */, + 9B118A971D4BFF070068B268 /* multiplayer_session_role_types.cpp in Sources */, + 9B5A12F31BFD2BF200BE12FD /* tournament_stage.cpp in Sources */, + 9B97B75E1BE1981B00CF1E29 /* token_result.cpp in Sources */, + 9B5A12041BFA60E100BE12FD /* contextual_search_broadcast.cpp in Sources */, + 67F503A41CD98D8E00198DEA /* xbox_live_app_config_ios.mm in Sources */, + 9B4B44AF1D2F2D4C0060F1C5 /* log.cpp in Sources */, + 9BF639381D492C3300BDF02B /* contextual_search_game_clip_stat.cpp in Sources */, + 9B5A12711BFA60E100BE12FD /* presence_user_batch_request.cpp in Sources */, + 9B5A11D21BFA60E100BE12FD /* quality_of_service_server.cpp in Sources */, + 9B97B7301BE1981B00CF1E29 /* errors.cpp in Sources */, + 9B5A12891BFA60E100BE12FD /* real_time_activity_service.cpp in Sources */, + 9CB56C0B1DA35AA800C92F44 /* custom_output.cpp in Sources */, + 9B5A126D1BFA60E100BE12FD /* presence_service.cpp in Sources */, + 255A36CD1CD8353B00D3AD8E /* multiplayer_event.cpp in Sources */, + 9B5A11DE1BFA60E100BE12FD /* leaderboard_result.cpp in Sources */, + 9B5A124A1BFA60E100BE12FD /* multiplayer_session_member.cpp in Sources */, + 9BBAB79D1CC0408200A75EDF /* local_config_i.mm in Sources */, + 9B4B44A11D2F22C30060F1C5 /* real_time_activity_service_factory.cpp in Sources */, + 9BF11AD11C12076E00D111C9 /* big_num.cpp in Sources */, + 9B5A12411BFA60E100BE12FD /* multiplayer_peer_to_peer_requirements.cpp in Sources */, + 9B5A12B61BFA60E100BE12FD /* user_statistics_service_impl.cpp in Sources */, + 9B5A12481BFA60E100BE12FD /* multiplayer_session_constants.cpp in Sources */, + 9B5A12031BFA60E100BE12FD /* contextual_config_result.cpp in Sources */, + 9B8A00B11BF2778B000337EA /* sign_in_delegate_ios.mm in Sources */, + 9B5A12691BFA60E100BE12FD /* presence_data.cpp in Sources */, + 9B5A12801BFA60E100BE12FD /* multiple_permissions_check_result.cpp in Sources */, + 255A36C41CD8353B00D3AD8E /* host_changed_event_args.cpp in Sources */, + 9B4B44B11D2F2D4C0060F1C5 /* log_output.cpp in Sources */, + 255A36D21CD8353B00D3AD8E /* multiplayer_local_user_manager.cpp in Sources */, + 9B97B73B1BE1981B00CF1E29 /* user_context.cpp in Sources */, + 9B5A126A1BFA60E100BE12FD /* presence_device_record.cpp in Sources */, + 9B5A12431BFA60E100BE12FD /* multiplayer_service.cpp in Sources */, + 9B5A11FF1BFA60E100BE12FD /* match_ticket_details_response.cpp in Sources */, + 9B5A12C01BFA60E100BE12FD /* title_storage_blob_result.cpp in Sources */, + 9B5A12B21BFA60E100BE12FD /* statistic_change_event_args.cpp in Sources */, + 9B97B75F1BE1981B00CF1E29 /* trie.cpp in Sources */, + 9B5A123E1BFA60E100BE12FD /* multiplayer_invite_handle_post_request.cpp in Sources */, + 9B97B73F1BE1981B00CF1E29 /* web_socket_connection.cpp in Sources */, + 9B5A12681BFA60E100BE12FD /* presence_broadcast_record.cpp in Sources */, + 9B5A0FD71BFA603A00BE12FD /* achievement_media_asset.cpp in Sources */, + 9B5A0FDC1BFA603A00BE12FD /* achievement_time_window.cpp in Sources */, + 9B5A12F41BFD2BF200BE12FD /* tournament_team.cpp in Sources */, + 9B5A12A01BFA60E100BE12FD /* social_relationship_change_event_args.cpp in Sources */, + 9B5A12461BFA60E100BE12FD /* multiplayer_session_capabilities.cpp in Sources */, + 9CDF0D381DA2E8860046C721 /* preferred_color.cpp in Sources */, + 9B5A123D1BFA60E100BE12FD /* multiplayer_invite.cpp in Sources */, + 9B5A12491BFA60E100BE12FD /* multiplayer_session_matchmaking_server.cpp in Sources */, + 255A36D91CD8353B00D3AD8E /* session_property_changed_event_args.cpp in Sources */, + 9B5A11D11BFA60E100BE12FD /* game_variant_schema.cpp in Sources */, + 9B5A12B01BFA60E100BE12FD /* service_configuration_statistic.cpp in Sources */, + 9B5A12B31BFA60E100BE12FD /* statistic_change_subscription.cpp in Sources */, + 9B97B7561BE1981B00CF1E29 /* nsal_endpoint.cpp in Sources */, + 9B46ED471BED41D600076704 /* ip_address_unix.cpp in Sources */, + 255A36C81CD8353B00D3AD8E /* member_left_event_args.cpp in Sources */, + 9B97B73C1BE1981B00CF1E29 /* utils.cpp in Sources */, + 9B5A11C61BFA60E100BE12FD /* EntertainmentProfileListVideoQueue_WinRT.cpp in Sources */, + 255A36D51CD8353B00D3AD8E /* multiplayer_manager.cpp in Sources */, + 9B5A11DF1BFA60E100BE12FD /* leaderboard_row.cpp in Sources */, + 9CB56C081DA35A4500C92F44 /* xbox_live_services_settings.cpp in Sources */, + 9B5A11CC1BFA60E100BE12FD /* game_server_metadata_result.cpp in Sources */, + 9B5A129F1BFA60E100BE12FD /* reputation_service.cpp in Sources */, + 9B5A12B51BFA60E100BE12FD /* user_statistics_service.cpp in Sources */, + 9B46ED511BF105A000076704 /* xbox_system_factory_ios.mm in Sources */, + 9B97B76D1BE1981C00CF1E29 /* xbox_live_mutex.cpp in Sources */, + 255A36DB1CD8353B00D3AD8E /* tournament_registration_state_changed_event_args.cpp in Sources */, + 9B5A128A1BFA60E100BE12FD /* real_time_activity_subscription.cpp in Sources */, + 9B5A12441BFA60E100BE12FD /* multiplayer_service_impl.cpp in Sources */, + 9CDF0D3A1DA2E8860046C721 /* social_graph.cpp in Sources */, + 9B5A129D1BFA60E100BE12FD /* profile_service.cpp in Sources */, + 9BF6393B1D492C3300BDF02B /* contextual_search_game_clip.cpp in Sources */, + 9B5A12701BFA60E100BE12FD /* presence_title_request.cpp in Sources */, + 9B118A961D4BFF070068B268 /* multiplayer_role_type.cpp in Sources */, + 9B97B7671BE1981C00CF1E29 /* user.cpp in Sources */, + 9B97B7491BE1981B00CF1E29 /* xbox_live_context_settings.cpp in Sources */, + 255A36D61CD8353B00D3AD8E /* multiplayer_member.cpp in Sources */, + 9B5A12731BFA60E100BE12FD /* title_presence_change_event_args.cpp in Sources */, + 9BF6393A1D492C3300BDF02B /* contextual_search_game_clip_uri_info.cpp in Sources */, + 9B5A0FD81BFA603A00BE12FD /* achievement_progression.cpp in Sources */, + 9B9615E51BEA86FE00E79527 /* XboxLiveContext_Desktop.cpp in Sources */, + 9B5A12811BFA60E100BE12FD /* permission_check_result.cpp in Sources */, + 9B97B7631BE1981C00CF1E29 /* xsts_token_service.cpp in Sources */, + B71305821CC7477A00A4E71E /* XLSCll.mm in Sources */, + 9B5A12B41BFA60E100BE12FD /* user_statistics_result.cpp in Sources */, + 9B5A128B1BFA60E100BE12FD /* real_time_activity_subscription_error_event_args.cpp in Sources */, + 9B847EB61CDD6928004E04B0 /* notification_service.cpp in Sources */, + 9B5A124E1BFA60E100BE12FD /* multiplayer_session_request.cpp in Sources */, + 6718F1E51CB77FEB0000BF6E /* XBLDictionaryToJSON.mm in Sources */, + 9B5A11CD1BFA60E100BE12FD /* game_server_platform_service.cpp in Sources */, + 9B5A12BE1BFA60E100BE12FD /* title_storage_blob_metadata.cpp in Sources */, + 255A36D11CD8353B00D3AD8E /* multiplayer_lobby_session.cpp in Sources */, + 9B5A12391BFA60E100BE12FD /* multiplayer_activity_details.cpp in Sources */, + 9BAEFDE91D3019A300ABBA82 /* multiplayer_match_client.cpp in Sources */, + 9CDF0D371DA2E8860046C721 /* peoplehub_service.cpp in Sources */, + 9C063B121D774C28009C3E3C /* mem.cpp in Sources */, + 9B5A12651BFA60E100BE12FD /* device_presence_change_subscription.cpp in Sources */, + 9B847EB31CDD2823004E04B0 /* notification_service_i.mm in Sources */, + 9B5A11CE1BFA60E100BE12FD /* game_server_port_mapping.cpp in Sources */, + 9B5A124B1BFA60E100BE12FD /* multiplayer_session_member_request.cpp in Sources */, + 9B5A0FD91BFA603A00BE12FD /* achievement_requirement.cpp in Sources */, + 9B5A120A1BFA60E100BE12FD /* verify_string_result.cpp in Sources */, + 255A36DC1CD8353B00D3AD8E /* user_added_event_args.cpp in Sources */, + 9BF132431C3C48230048204E /* device_token_service.cpp in Sources */, + 9B5A11C91BFA60E100BE12FD /* allocation_result.cpp in Sources */, + 9B5A0FDA1BFA603A00BE12FD /* achievement_reward.cpp in Sources */, + 9BF11ADF1C120C2900D111C9 /* ip_address_desktop.cpp in Sources */, + 251DBDD71CE6DE41003AF56B /* utils_locales_ios.mm in Sources */, + 9B5A11C51BFA60E100BE12FD /* EntertainmentProfileListService_WinRT.cpp in Sources */, + B7E5C76D1CEED3E5003B2B08 /* UTCIDPNames.mm in Sources */, + 9B5A126B1BFA60E100BE12FD /* presence_media_record.cpp in Sources */, + 9B5A12C21BFA60E100BE12FD /* title_storage_service.cpp in Sources */, + 9B5A12F21BFD2BF200BE12FD /* tournament_service.cpp in Sources */, + 9B5A12471BFA60E100BE12FD /* multiplayer_session_change_event_args.cpp in Sources */, + 255A36CF1CD8353B00D3AD8E /* multiplayer_game_session.cpp in Sources */, + 9B97B7371BE1981B00CF1E29 /* service_call_logger_data.cpp in Sources */, + 255A36DA1CD8353B00D3AD8E /* tournament_game_session_ready_event_args.cpp in Sources */, + 9B5A12741BFA60E100BE12FD /* title_presence_change_subscription.cpp in Sources */, + 9B5A11C31BFA60E100BE12FD /* entertainment_profile_list_xbox_one_pins.cpp in Sources */, + 255A36C31CD8353B00D3AD8E /* find_match_completed_event_args.cpp in Sources */, + 9BF11AD31C12076E00D111C9 /* sha256.cpp in Sources */, + 9B5A126E1BFA60E100BE12FD /* presence_service_impl.cpp in Sources */, + 9B5A12061BFA60E100BE12FD /* contextual_search_service.cpp in Sources */, + 9B5A11CA1BFA60E100BE12FD /* cluster_result.cpp in Sources */, + 9B118AE11D8B35230068B268 /* user_impl_ios.mm in Sources */, + 9B5A12F51BFD2BF200BE12FD /* tournament_team_result.cpp in Sources */, + 9B5A12AD1BFA60E100BE12FD /* xbox_social_relationship_result.cpp in Sources */, + 255A36D71CD8353B00D3AD8E /* multiplayer_session_writer.cpp in Sources */, + 9B97B74C1BE1981B00CF1E29 /* auth_manager.cpp in Sources */, + 9B5A11FE1BFA60E100BE12FD /* hopper_statistics_response.cpp in Sources */, + 9B5A12F71BFD2BF200BE12FD /* tournaments_result.cpp in Sources */, + 255A36D81CD8353B00D3AD8E /* perform_qos_measurements_event_args.cpp in Sources */, + 9B5A11E01BFA60E100BE12FD /* leaderboard_serializers.cpp in Sources */, + 9B5A11CF1BFA60E100BE12FD /* game_server_ticket_status.cpp in Sources */, + 9B97B75D1BE1981B00CF1E29 /* token_request.cpp in Sources */, + 9B5A12511BFA60E100BE12FD /* multiplayer_transfer_handle_post_request.cpp in Sources */, + 9B5A12721BFA60E100BE12FD /* presence_writer.cpp in Sources */, + 9B97B7391BE1981B00CF1E29 /* service_call_logging_config.cpp in Sources */, + 9B5A11C41BFA60E100BE12FD /* EntertainmentProfileListContainsItemResult_WinRT.cpp in Sources */, + 9B97B75A1BE1981B00CF1E29 /* title_token_service.cpp in Sources */, + 9B97B7311BE1981B00CF1E29 /* http_call_impl.cpp in Sources */, + 9B46ED461BED41D600076704 /* ecdsa_unix.cpp in Sources */, + 255A36CC1CD8353B00D3AD8E /* multiplayer_client_pending_request.cpp in Sources */, + 9CDF0D3D1DA2E8860046C721 /* social_manager.cpp in Sources */, + 9B97B7341BE1981B00CF1E29 /* http_client.cpp in Sources */, + 9B5A12F01BFD2BF200BE12FD /* tournament.cpp in Sources */, + 9B5A124C1BFA60E100BE12FD /* multiplayer_session_properties.cpp in Sources */, + 9B5A12AC1BFA60E100BE12FD /* xbox_social_relationship.cpp in Sources */, + 9B97B7651BE1981C00CF1E29 /* auth_config.cpp in Sources */, + 9B5A11FD1BFA60E100BE12FD /* create_match_ticket_response.cpp in Sources */, + 9B5A124D1BFA60E100BE12FD /* multiplayer_session_reference.cpp in Sources */, + 255A36CB1CD8353B00D3AD8E /* multiplayer_client_pending_reader.cpp in Sources */, + 9B5A12451BFA60E100BE12FD /* multiplayer_session.cpp in Sources */, + 9B5A11E11BFA60E100BE12FD /* leaderboard_service.cpp in Sources */, + 9B5A11C21BFA60E100BE12FD /* entertainment_profile_list_contains_item_result.cpp in Sources */, + 255A36CE1CD8353B00D3AD8E /* multiplayer_game_client.cpp in Sources */, + 9B5A12081BFA60E100BE12FD /* string_service.cpp in Sources */, + 9BBAB7781CBDE09000A75EDF /* local_config_u.cpp in Sources */, + 9BF11AD21C12076E00D111C9 /* request_signer.cpp in Sources */, + 677B9FCD1CD90F2900A28F96 /* XBLiOSGlobalState.mm in Sources */, + 9B5A124F1BFA60E100BE12FD /* multiplayer_session_states.cpp in Sources */, + 9B5A12AF1BFA60E100BE12FD /* requested_statistics.cpp in Sources */, + 6718D8B71C86605E007FD4F6 /* XBLSignInHandler.mm in Sources */, + 9B5A12401BFA60E100BE12FD /* multiplayer_peer_to_host_requirements.cpp in Sources */, + 9B97B7551BE1981B00CF1E29 /* nsal.cpp in Sources */, + 32F5FBBF1CE7DB1D008A5E09 /* title_callable_ui.mm in Sources */, + 9B5A126C1BFA60E100BE12FD /* presence_record.cpp in Sources */, + 9B97B7351BE1981B00CF1E29 /* local_config.cpp in Sources */, + 9B97B7601BE1981C00CF1E29 /* user_token_service.cpp in Sources */, + 9B97B7681BE1981C00CF1E29 /* user_impl.cpp in Sources */, + 9B118A951D4BFF070068B268 /* multiplayer_role_info.cpp in Sources */, + 9B5A123C1BFA60E100BE12FD /* multiplayer_get_sessions_request.cpp in Sources */, + 9B46ED551BF14AFA00076704 /* user_ios.mm in Sources */, + 9BF6393C1D492C3300BDF02B /* contextual_search_game_clips_result.cpp in Sources */, + 9CB56C061DA359BB00C92F44 /* multiplayer_query_search_handle_request.cpp in Sources */, + 9B5A11DD1BFA60E100BE12FD /* leaderboard_column.cpp in Sources */, + 9B97B74B1BE1981B00CF1E29 /* xbox_system_factory.cpp in Sources */, + 9B5A11C11BFA60E100BE12FD /* entertainment_profile.cpp in Sources */, + 9B5A12831BFA60E100BE12FD /* privacy_service.cpp in Sources */, + 9B97B75C1BE1981B00CF1E29 /* token_manager.cpp in Sources */, + 255A36D01CD8353B00D3AD8E /* multiplayer_lobby_client.cpp in Sources */, + 67210E731C6479E20008FFDB /* XboxProvider.mm in Sources */, + 9B5A11CB1BFA60E100BE12FD /* game_server_image_set.cpp in Sources */, + 9B97B74A1BE1981B00CF1E29 /* xbox_service_call_routed_event_args.cpp in Sources */, + 255A36C91CD8353B00D3AD8E /* member_property_changed_event_args.cpp in Sources */, + 9CDF0D401DA2E8860046C721 /* xbox_social_user_group.cpp in Sources */, + 67210E721C6479E20008FFDB /* NSError+XSAPIExtensions.mm in Sources */, + 9CDF0D3F1DA2E8860046C721 /* title_history.cpp in Sources */, + 9CDF0D3C1DA2E8860046C721 /* social_manager_presence_title_record.cpp in Sources */, + 9B97B7591BE1981B00CF1E29 /* signature_policy.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 671121B71CBD960100F49259 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XSAPITCUI; + targetProxy = 671121B61CBD960100F49259 /* PBXContainerItemProxy */; + }; + 9B8250301C1A46B7002C8F30 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Casablanca; + targetProxy = 9B82502F1C1A46B7002C8F30 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 9B97B3621BE18B2600CF1E29 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 9B97B3631BE18B2600CF1E29 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9B97B3651BE18B2600CF1E29 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + EMBEDDED_CONTENT_CONTAINS_SWIFT = NO; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ../../Source/Services/Common/iOS/pch.cpp; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "XSAPI_U=1", + "XSAPI_CPP=1", + "XSAPI_I=1", + ); + HEADER_SEARCH_PATHS = ( + "$(SRCROOT)/../../External/OpenSSL/include/", + "$(SRCROOT)/../../Include/", + "$(SRCROOT)/../../Casablanca/Release/include/", + "$(SRCROOT)/../../External/MSAAuthentication/iOS/include/", + "$(SRCROOT)/XboxSignInUI/**", + "$(SRCROOT)/../../External/Boost/include/", + "$(SRCROOT)/../../External/CLL/iOS/include/", + "$(SRCROOT)/../../External/CLL/iOS/include/cll", + "$(SRCROOT)/../../External/CLL/iOS/include/bond_schema_inc", + "$(SRCROOT)/../../External/CLL/iOS/include/cll_schema_inc", + "$(SRCROOT)/../../External/CLL/iOS/include/onlineID_schema_inc", + "$(SRCROOT)/../../Source/Shared/", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/MSAAuthentication", + "$(PROJECT_DIR)", + "$(SRCROOT)/../../External/Boost/iOS/lib", + "$(SRCROOT)/../../External/MSAAuthentication/iOS/lib", + "$(SRCROOT)/../../External/OpenSSL/iOS/lib", + "$(SRCROOT)/../../Samples/Social/iOS", + "$(SRCROOT)/../../TAEF/Library/Debug/arm", + "$(SRCROOT)/../../TAEF/Library/Debug/x64", + "$(SRCROOT)/../../TAEF/Library/Debug/x86", + "$(SRCROOT)/../../TAEF/Library/Release/arm", + "$(SRCROOT)/../../TAEF/Library/Release/x64", + "$(SRCROOT)/../../TAEF/Library/Release/x86", + "$(SRCROOT)/../../External/CLL/iOS/lib", + ); + ONLY_ACTIVE_ARCH = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + VALID_ARCHS = "arm64 armv7 armv7s"; + }; + name = Debug; + }; + 9B97B3661BE18B2600CF1E29 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + EMBEDDED_CONTENT_CONTAINS_SWIFT = NO; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ../../Source/Services/Common/iOS/pch.cpp; + GCC_PREPROCESSOR_DEFINITIONS = ( + "XSAPI_U=1", + "XSAPI_CPP=1", + "XSAPI_I=1", + ); + HEADER_SEARCH_PATHS = ( + "$(SRCROOT)/../../External/OpenSSL/include/", + "$(SRCROOT)/../../Include/", + "$(SRCROOT)/../../Casablanca/Release/include/", + "$(SRCROOT)/../../External/MSAAuthentication/iOS/include/", + "$(SRCROOT)/XboxSignInUI/**", + "$(SRCROOT)/../../External/Boost/include/", + "$(SRCROOT)/../../External/CLL/iOS/include/", + "$(SRCROOT)/../../External/CLL/iOS/include/cll", + "$(SRCROOT)/../../External/CLL/iOS/include/bond_schema_inc", + "$(SRCROOT)/../../External/CLL/iOS/include/cll_schema_inc", + "$(SRCROOT)/../../External/CLL/iOS/include/onlineID_schema_inc", + "$(SRCROOT)/../../Source/Shared/", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/MSAAuthentication", + "$(PROJECT_DIR)", + "$(SRCROOT)/../../External/Boost/iOS/lib", + "$(SRCROOT)/../../External/MSAAuthentication/iOS/lib", + "$(SRCROOT)/../../External/OpenSSL/iOS/lib", + "$(SRCROOT)/../../Samples/Social/iOS", + "$(SRCROOT)/../../TAEF/Library/Debug/arm", + "$(SRCROOT)/../../TAEF/Library/Debug/x64", + "$(SRCROOT)/../../TAEF/Library/Debug/x86", + "$(SRCROOT)/../../TAEF/Library/Release/arm", + "$(SRCROOT)/../../TAEF/Library/Release/x64", + "$(SRCROOT)/../../TAEF/Library/Release/x86", + "$(SRCROOT)/../../External/CLL/iOS/lib", + ); + ONLY_ACTIVE_ARCH = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + VALID_ARCHS = "arm64 armv7 armv7s"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9B97B3561BE18B2500CF1E29 /* Build configuration list for PBXProject "XboxLiveServices" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B97B3621BE18B2600CF1E29 /* Debug */, + 9B97B3631BE18B2600CF1E29 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9B97B3641BE18B2600CF1E29 /* Build configuration list for PBXNativeTarget "XboxLiveServices" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B97B3651BE18B2600CF1E29 /* Debug */, + 9B97B3661BE18B2600CF1E29 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9B97B3531BE18B2500CF1E29 /* Project object */; +} diff --git a/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..573aaf1f --- /dev/null +++ b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/xcshareddata/XboxLiveServices.xccheckout b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/xcshareddata/XboxLiveServices.xccheckout new file mode 100644 index 00000000..45fc19b3 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/project.xcworkspace/xcshareddata/XboxLiveServices.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 62B344A9-4EF5-4C0B-B7D2-C92B7CDCF957 + IDESourceControlProjectName + XboxLiveServices + IDESourceControlProjectOriginsDictionary + + BC0693BF3F01AB9B235592905A8C3EF052D5ECC4 + https://microsoft.visualstudio.com/defaultcollection/OS/_git/xbox.services.xboxlivesdk + + IDESourceControlProjectPath + Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + BC0693BF3F01AB9B235592905A8C3EF052D5ECC4 + ../../../.. + + IDESourceControlProjectURL + https://microsoft.visualstudio.com/defaultcollection/OS/_git/xbox.services.xboxlivesdk + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + BC0693BF3F01AB9B235592905A8C3EF052D5ECC4 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + BC0693BF3F01AB9B235592905A8C3EF052D5ECC4 + IDESourceControlWCCName + xbox.services.xboxlivesdk + + + + diff --git a/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServices.xcscheme b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServices.xcscheme new file mode 100644 index 00000000..b1ffab56 --- /dev/null +++ b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServices.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServicesResources.xcscheme b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServicesResources.xcscheme new file mode 100644 index 00000000..6c7ec87c --- /dev/null +++ b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServices.xcodeproj/xcshareddata/xcschemes/XboxLiveServicesResources.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Build/Microsoft.Xbox.Services.iOS/XboxLiveServicesResources/Info.plist b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServicesResources/Info.plist new file mode 100644 index 00000000..a6b8c5cd --- /dev/null +++ b/Build/Microsoft.Xbox.Services.iOS/XboxLiveServicesResources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2016 Microsoft Corporation. All rights reserved. + NSPrincipalClass + + + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..3e17ca11 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,31 @@ +# Contribution Guidelines + +There are many different ways in which you can contribute! Please submit issues, questions, bug reports, feature requests, bug fixes, improvements, and new features. + +### Report bugs and request features + +Issues and feature requests are submitted through the project's [issue tracker](../issues) section on GitHub. Please use the following guidelines when you submit issues and feature requests: + +* Make sure the issue is not already reported by searching through the list of issues +* Provide a detailed description of the issue including the following information: + * Which feature the issue appears in + * Under what circumstances the issue appears + * What is the desired behavior + * What is breaking + * What is the impact (things like loss or corruption of data, compromising security, disruption of service etc.) + * Any code that will be helpful to reproduce the issue + +### Create bug fixes and features + +Please submit any changes as a Pull Request against the development branch. Make sure to write a detailed message describing the changes in the Pull Request. This will help us quickly determine what changes (if any) need to be made for it to be ready for integration. + +_Note: Please keep in mind that not all requests will be approved. Requests are reviewed by the team on a regular basis and will be updated with the status at each review. If your request is accepted you will receive information about the next steps and when the request will be integrated in the development branch. If your request is rejected you will receive information about the reasons why it was rejected._ + +### Contribution guidelines + +Before you start working on bug fixes and features it is good idea to discuss those broadly with the community. You can use the [issue tracker](../issues) for this purpose. Before submitting your changes make sure you followed the guidelines below: + +* You have properly documented any new functionality +* For any new functionality you have written complete unit tests +* You have run all unit tests and they pass +* In order to speed up the process of accepting your contributions, you should try to make your checkins as small as possible, avoid any unnecessary deltas and the need to rebase. \ No newline at end of file diff --git a/External/cpprestsdk/.gitignore b/External/cpprestsdk/.gitignore new file mode 100644 index 00000000..d0ff65b0 --- /dev/null +++ b/External/cpprestsdk/.gitignore @@ -0,0 +1,68 @@ +#Visual Studio files +*.o +*.d +*.so +*.[Oo]bj +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.lib +*.sbr +*.sdf +*.sdf +*.opensdf +*.pdb +*.idb +*.res +*.unsuccessfulbuild +*.lastbuildstate +*.tlog +*.intermediate +*.dll +*.exp +*.exe +*.manifest +*.rc +*~ +ipch/ +obj/ +#OSX files +*.xccheckout +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspective3 +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspective3 +xcuserdata +*.xcuserstate +.DS_Store +.Trashes +*.swp +*.lock +*~.nib +*.resfiles +[Bb]in +Binaries/ +Intermediate/ +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +.vs/ +# Ignore cmake building directories +build.*/ diff --git a/External/cpprestsdk/Build/Build.Durango.Cpp.props b/External/cpprestsdk/Build/Build.Durango.Cpp.props new file mode 100644 index 00000000..343d88d9 --- /dev/null +++ b/External/cpprestsdk/Build/Build.Durango.Cpp.props @@ -0,0 +1,29 @@ + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + + + + + ixmlhttprequest2.lib;combase.lib;kernelx.lib;uuid.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + + + + msxml6.lib;runtimeobject.lib;mincore.lib;mincore_legacy.lib;mincore_obsolete.lib;user32.lib;uuid.lib; + + + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + + + diff --git a/External/cpprestsdk/Build/Common.Build.Traversal.targets b/External/cpprestsdk/Build/Common.Build.Traversal.targets new file mode 100644 index 00000000..db26ed7a --- /dev/null +++ b/External/cpprestsdk/Build/Common.Build.Traversal.targets @@ -0,0 +1,28 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + true + + + + + + + + + + + + + + + + diff --git a/External/cpprestsdk/Build/Common.Build.settings b/External/cpprestsdk/Build/Common.Build.settings new file mode 100644 index 00000000..f06dd390 --- /dev/null +++ b/External/cpprestsdk/Build/Common.Build.settings @@ -0,0 +1,244 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + + Debug + Win32 + + + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) + $(BuildRoot)\Build + $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion@CurrentVersion) + + 140 + 120 + 110 + + $(WindowsSdkDir) + true + true + false + + + + + + $(BuildRoot)\..\Binaries\$(Configuration)\$(Platform)\Casablanca\ + $(OutputPath) + $(BuildRoot)\Intermediate\$(MSBuildProjectName)\$(Platform)\$(Configuration)\ + $(BuildRoot)\Release\Tests + $(BuildRoot)\Release\src + $(BuildRoot)\Release\Resource + $(BuildRoot)\Release\include + $(BuildRoot)\Release\libs\websocketpp + $(BuildRoot)\packages + $(BuildRoot)\..\Tools\packages + $(BuildRoot)\..\External\Packages + $(BuildRoot)\Release\Collateral + + + + + $(OutDir)\ + + + + $(VS110COMNTOOLS)..\IDE + + + + $(VS120COMNTOOLS)..\IDE + + + + $(TargetsPath)\BinaryDependencies + prompt + 4 + + + false + + + false + $(RunCodeAnalysis) + true + + true + + + true + false + false + true + + + + + Level4 + Use + true + $(EnableCPPAnalysis) + true + /d2notypeopt %(AdditionalOptions) + + + /DTARGET_NAME="$(TARGETNAME)" %(AdditionalOptions) + + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + + + true + + + + + + _WIN64;_DEBUG;%(PreprocessorDefinitions) + + + true + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + true + + + + + + _WIN64;NDEBUG;%(PreprocessorDefinitions) + + + true + + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + + + + + true + full + false + DEBUG;TRACE + x86 + + + + true + full + false + DEBUG;TRACE;X64 + + + + pdbonly + true + TRACE + x86 + + + + pdbonly + true + TRACE;X64 + + + + true + full + false + DEBUG;TRACE;ARM + + + + pdbonly + true + TRACE;ARM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ResolvedProjectReferencePaths> + Undefined + + + + + + + + <_ResolvedProjectReferencePaths Condition="'%(CopyToOutputDirectory)' != 'Undefined'" + Remove="@(_ResolvedProjectReferencePaths)" /> + + + + + + + diff --git a/External/cpprestsdk/Build/Config.Definitions.Durango.props b/External/cpprestsdk/Build/Config.Definitions.Durango.props new file mode 100644 index 00000000..899d70a0 --- /dev/null +++ b/External/cpprestsdk/Build/Config.Definitions.Durango.props @@ -0,0 +1,13 @@ + + + + + Debug + Durango + + + Release + Durango + + + \ No newline at end of file diff --git a/External/cpprestsdk/Build/Config.Definitions.props b/External/cpprestsdk/Build/Config.Definitions.props new file mode 100644 index 00000000..9eaabbb2 --- /dev/null +++ b/External/cpprestsdk/Build/Config.Definitions.props @@ -0,0 +1,29 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + \ No newline at end of file diff --git a/External/cpprestsdk/Build/Release.Product.settings b/External/cpprestsdk/Build/Release.Product.settings new file mode 100644 index 00000000..30d0bc9a --- /dev/null +++ b/External/cpprestsdk/Build/Release.Product.settings @@ -0,0 +1,64 @@ + + + + + true + false + + + + false + true + + + + Unicode + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + false + + $(RunCodeAnalysis) + + + + + + $(CasablancaIncludeDir) + + + + + false + + + Windows + false + true + /SAFESEH%(AdditionalOptions) + + + + + + Disabled + + + + + + NDEBUG;%(PreprocessorDefinitions) + MaxSpeed + true + true + + + + diff --git a/External/cpprestsdk/Build/Release.Tests.settings b/External/cpprestsdk/Build/Release.Tests.settings new file mode 100644 index 00000000..2bbff911 --- /dev/null +++ b/External/cpprestsdk/Build/Release.Tests.settings @@ -0,0 +1,27 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + false + + + + + + + $(TestRoot)\Common\utilities\include;$(TestRoot)\Common\UnitTestpp + $(BinariesDirectory)\inc;$(CasablancaIncludeDir) + + + + + + + + diff --git a/External/cpprestsdk/Build/version.props b/External/cpprestsdk/Build/version.props new file mode 100644 index 00000000..b5eb1517 --- /dev/null +++ b/External/cpprestsdk/Build/version.props @@ -0,0 +1,11 @@ + + + + cpprest + 2 + 9 + 0 + $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) + $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) + + diff --git a/External/cpprestsdk/Build_android/boost-for-android-x86.patch b/External/cpprestsdk/Build_android/boost-for-android-x86.patch new file mode 100644 index 00000000..4e24b988 --- /dev/null +++ b/External/cpprestsdk/Build_android/boost-for-android-x86.patch @@ -0,0 +1,173 @@ +diff --git a/build-android.sh b/build-android.sh +index 40453f7..5902fe2 100755 +--- a/build-android.sh ++++ b/build-android.sh +@@ -195,8 +195,12 @@ case "$HOST_OS" in + PlatformOS=linux + esac + ++NDK_SOURCE_PROPERTIES=$AndroidNDKRoot"/source.properties" + NDK_RELEASE_FILE=$AndroidNDKRoot"/RELEASE.TXT" +-if [ -f "${NDK_RELEASE_FILE}" ]; then ++if [ -f "${NDK_SOURCE_PROPERTIES}" ]; then ++ version=$(grep -i '^Pkg.Revision =' $NDK_SOURCE_PROPERTIES | cut -f2- -d=) ++ NDK_RN=$(echo $version | awk -F. '{print $1}') ++elif [ -f "${NDK_RELEASE_FILE}" ]; then + NDK_RN=`cat $NDK_RELEASE_FILE | sed 's/^r\(.*\)$/\1/g'` + elif [ -n "${AndroidSourcesDetected}" ]; then + if [ -f "${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" ]; then +@@ -258,10 +262,20 @@ case "$NDK_RN" in + TOOLSET=gcc-androidR8e + ;; + "10 (64-bit)") +- TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} +- CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/arm-linux-androideabi-g++ +- TOOLSET=gcc-androidR8e ++ TOOLCHAIN=llvm-3.4 ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e ++ ;; ++ "10e-rc4 (64-bit)"|"10e (64-bit)") ++ TOOLCHAIN=llvm-3.6 ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e + ;; ++ 11) ++ TOOLCHAIN=llvm ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e ++ ;; + *) + echo "Undefined or not supported Android NDK version!" + exit 1 +@@ -391,6 +405,7 @@ echo "Building boost for android" + export AndroidBinariesPath=`dirname $CXXPATH` + export PATH=$AndroidBinariesPath:$PATH + export AndroidNDKRoot ++ export PlatformOS + export NO_BZIP2=1 + + cxxflags="" +@@ -405,7 +420,7 @@ echo "Building boost for android" + --layout=versioned \ + --prefix="./../$BUILD_DIR/" \ + $LIBRARIES \ +- install 2>&1 \ ++ release debug install 2>&1 \ + || { dump "ERROR: Failed to build boost for android!" ; exit 1 ; } + } | tee -a $PROGDIR/build.log + +diff --git a/configs/user-config-boost-1_55_0.jam b/configs/user-config-boost-1_55_0.jam +index 666d4c8..93aba68 100644 +--- a/configs/user-config-boost-1_55_0.jam ++++ b/configs/user-config-boost-1_55_0.jam +@@ -39,93 +39,47 @@ + + import os ; + local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; ++local PlatformOS = [ os.environ PlatformOS ] ; + + # -------------------------------------------------------------------- +-# Is same for 8b, 8c and 8d +-using gcc : androidR8b ++using clang : androidR8e + : +-arm-linux-androideabi-g++ ++$(AndroidNDKRoot)/toolchains/llvm/prebuilt/$(PlatformOS)-x86_64/bin/clang++ + : +-arm-linux-androideabi-ar ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.9/prebuilt/$(PlatformOS)-x86_64" + -fexceptions + -frtti + -fpic + -ffunction-sections + -funwind-tables +--D__ARM_ARCH_5__ +--D__ARM_ARCH_5T__ +--D__ARM_ARCH_5E__ +--D__ARM_ARCH_5TE__ +--Wno-psabi +--march=armv5te +--mtune=xscale +--msoft-float +--mthumb ++-fstack-protector ++-no-canonical-prefixes ++--target=i686-none-linux-android ++--sysroot="$(AndroidNDKRoot)/platforms/android-9/arch-x86" + -Os + -fomit-frame-pointer +--fno-strict-aliasing +--finline-limit=64 +--I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include ++-fstrict-aliasing + -Wa,--noexecstack + -DANDROID + -D__ANDROID__ + -DNDEBUG + -O2 + -g +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/x86/include ++--target=i686-none-linux-android ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.9/prebuilt/$(PlatformOS)-x86_64" ++--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-x86 + # @Moss - Above are the 'oficial' android flags +-arm ++i686 + -fvisibility=hidden + -fvisibility-inlines-hidden + -fdata-sections +--D__arm__ + -D_REENTRANT + -D_GLIBCXX__PTHREADS ++-std=c++11 + ; + +-# -------------------------------------------------------------------- +-using gcc : androidR8e +-: +-arm-linux-androideabi-g++ +-: +-arm-linux-androideabi-ar +--fexceptions +--frtti +--fpic +--ffunction-sections +--funwind-tables +--D__ARM_ARCH_5__ +--D__ARM_ARCH_5T__ +--D__ARM_ARCH_5E__ +--D__ARM_ARCH_5TE__ +--Wno-psabi +--march=armv5te +--mtune=xscale +--msoft-float +--mthumb +--Os +--fomit-frame-pointer +--fno-strict-aliasing +--finline-limit=64 +--I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +--Wa,--noexecstack +--DANDROID +--D__ANDROID__ +--DNDEBUG +--O2 +--g +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +-# @Moss - Above are the 'oficial' android flags +-arm +--fvisibility=hidden +--fvisibility-inlines-hidden +--fdata-sections +--D__arm__ +--D_REENTRANT +--D_GLIBCXX__PTHREADS +-; + + + # ------------------ diff --git a/External/cpprestsdk/Build_android/boost-for-android.patch b/External/cpprestsdk/Build_android/boost-for-android.patch new file mode 100644 index 00000000..2b86e8f8 --- /dev/null +++ b/External/cpprestsdk/Build_android/boost-for-android.patch @@ -0,0 +1,175 @@ +diff --git a/build-android.sh b/build-android.sh +index 40453f7..5902fe2 100755 +--- a/build-android.sh ++++ b/build-android.sh +@@ -195,8 +195,12 @@ case "$HOST_OS" in + PlatformOS=linux + esac + ++NDK_SOURCE_PROPERTIES=$AndroidNDKRoot"/source.properties" + NDK_RELEASE_FILE=$AndroidNDKRoot"/RELEASE.TXT" +-if [ -f "${NDK_RELEASE_FILE}" ]; then ++if [ -f "${NDK_SOURCE_PROPERTIES}" ]; then ++ version=$(grep -i '^Pkg.Revision =' $NDK_SOURCE_PROPERTIES | cut -f2- -d=) ++ NDK_RN=$(echo $version | awk -F. '{print $1}') ++elif [ -f "${NDK_RELEASE_FILE}" ]; then + NDK_RN=`cat $NDK_RELEASE_FILE | sed 's/^r\(.*\)$/\1/g'` + elif [ -n "${AndroidSourcesDetected}" ]; then + if [ -f "${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" ]; then +@@ -258,10 +262,20 @@ case "$NDK_RN" in + TOOLSET=gcc-androidR8e + ;; + "10 (64-bit)") +- TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} +- CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/arm-linux-androideabi-g++ +- TOOLSET=gcc-androidR8e ++ TOOLCHAIN=llvm-3.4 ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e ++ ;; ++ "10e-rc4 (64-bit)"|"10e (64-bit)") ++ TOOLCHAIN=llvm-3.6 ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e + ;; ++ 11) ++ TOOLCHAIN=llvm ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e ++ ;; + *) + echo "Undefined or not supported Android NDK version!" + exit 1 +@@ -391,6 +405,7 @@ echo "Building boost for android" + export AndroidBinariesPath=`dirname $CXXPATH` + export PATH=$AndroidBinariesPath:$PATH + export AndroidNDKRoot ++ export PlatformOS + export NO_BZIP2=1 + + cxxflags="" +@@ -405,7 +420,7 @@ echo "Building boost for android" + --layout=versioned \ + --prefix="./../$BUILD_DIR/" \ + $LIBRARIES \ +- install 2>&1 \ ++ release debug install 2>&1 \ + || { dump "ERROR: Failed to build boost for android!" ; exit 1 ; } + } | tee -a $PROGDIR/build.log + +diff --git a/configs/user-config-boost-1_55_0.jam b/configs/user-config-boost-1_55_0.jam +index 666d4c8..cdab118 100644 +--- a/configs/user-config-boost-1_55_0.jam ++++ b/configs/user-config-boost-1_55_0.jam +@@ -39,84 +39,44 @@ + + import os ; + local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; ++local PlatformOS = [ os.environ PlatformOS ] ; + + # -------------------------------------------------------------------- +-# Is same for 8b, 8c and 8d +-using gcc : androidR8b ++using clang : androidR8e + : +-arm-linux-androideabi-g++ ++$(AndroidNDKRoot)/toolchains/llvm/prebuilt/$(PlatformOS)-x86_64/bin/clang++ + : +-arm-linux-androideabi-ar ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.9/prebuilt/$(PlatformOS)-x86_64" + -fexceptions + -frtti + -fpic + -ffunction-sections + -funwind-tables +--D__ARM_ARCH_5__ +--D__ARM_ARCH_5T__ +--D__ARM_ARCH_5E__ +--D__ARM_ARCH_5TE__ +--Wno-psabi +--march=armv5te +--mtune=xscale +--msoft-float ++-no-canonical-prefixes ++--target=armv7-none-linux-androideabi ++-march=armv7-a ++-mfloat-abi=softfp ++-mfpu=vfpv3-d16 + -mthumb +--Os +--fomit-frame-pointer +--fno-strict-aliasing +--finline-limit=64 +--I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +--Wa,--noexecstack +--DANDROID +--D__ANDROID__ +--DNDEBUG +--O2 +--g +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +-# @Moss - Above are the 'oficial' android flags +-arm +--fvisibility=hidden +--fvisibility-inlines-hidden +--fdata-sections +--D__arm__ +--D_REENTRANT +--D_GLIBCXX__PTHREADS +-; +- +-# -------------------------------------------------------------------- +-using gcc : androidR8e +-: +-arm-linux-androideabi-g++ +-: +-arm-linux-androideabi-ar +--fexceptions +--frtti +--fpic +--ffunction-sections +--funwind-tables ++--sysroot="$(AndroidNDKRoot)/platforms/android-9/arch-arm" + -D__ARM_ARCH_5__ + -D__ARM_ARCH_5T__ + -D__ARM_ARCH_5E__ + -D__ARM_ARCH_5TE__ +--Wno-psabi +--march=armv5te +--mtune=xscale +--msoft-float +--mthumb + -Os + -fomit-frame-pointer + -fno-strict-aliasing +--finline-limit=64 +--I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include + -Wa,--noexecstack + -DANDROID + -D__ANDROID__ + -DNDEBUG + -O2 + -g +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +--I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include ++--target=armv7-none-linux-androideabi ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.9/prebuilt/$(PlatformOS)-x86_64" ++--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-arm + # @Moss - Above are the 'oficial' android flags + arm + -fvisibility=hidden +@@ -125,9 +85,11 @@ arm-linux-androideabi-g++ + -D__arm__ + -D_REENTRANT + -D_GLIBCXX__PTHREADS ++-std=c++11 + ; + + ++ + # ------------------ + # GCC configuration. + # ------------------ diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitattributes b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitattributes new file mode 100644 index 00000000..9ba89d8c --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +*.sh eol=lf diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitignore b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitignore new file mode 100644 index 00000000..65b62b5c --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/.gitignore @@ -0,0 +1,7 @@ +boost_* +build +*~ +logs +build.log +*.swp +*.vim diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/README.md b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/README.md new file mode 100644 index 00000000..4c0954b1 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/README.md @@ -0,0 +1,96 @@ +# Boost for Android +Boost for android is a set of tools to compile the main part of the [Boost C++ Libraries](http://www.boost.org/) for the Android platform. + +Currently supported boost versions are 1.45.0, 1.48.0, 1.49.0 and 1.53.0. Boost 1.54.0 and 1.55.0 shall be considered experimental. + +To compile Boost for Android you may use one of the following NDKs: + +| NDK / boost | 1.45 | 1.48 | 1.49 | 1.53 | +| ----------- | ---- | ---- | ---- | ---- | +| r4 customized by [Dmitry Moskalchuk aka CrystaX](http://www.crystax.net/android/ndk.php). | x | | | | +| r5 from the [official android repository](http://developer.android.com). | x | | | | +| r5 customized by [CrystaX](http://www.crystax.net/android/ndk.php). | x | | | | +| r7 customized by [CrystaX](http://www.crystax.net/android/ndk.php). | x | x | x | | +| r8 from the [official android repository](http://developer.android.com). | x | x | x | | +| r8b from the [official android repository](http://developer.android.com). | | x | x | | +| r8c from the [official android repository](http://developer.android.com). | | | x | | +| r8d from the [official android repository](http://developer.android.com). | | | x | x | +| r8e from the [official android repository](http://developer.android.com). | | | x | x | +| r10 from the [official android repository](http://developer.android.com). | | | x | x | + +# Quick Start + +## Dependencies + + * NDK ([official](http://developer.android.com) or [customized by CrystaX](http://www.crystax.net/android/ndk.php)) + * GNU Make + +## Usage + +### Compiling + +Linux. +``` +./build-android.sh $(NDK_ROOT) +``` +Windows: +``` +build-android.bat $(NDK_ROOT) +``` +NOTE: Do not forget to replace backslash with slashes in $(NDK_ROOT). For example set $(NDK_ROOT) to D:/android-ndk-r8e instead of D:\android-ndk-r8e + +On windows you will need MSYS to be able to launch the corresponding bat files (http://www.mingw.org/wiki/MSYS). + +This command will download and build boost against the NDK specified and output the final headers and libs in the `build` folder. Make sure to provide an absolute path the the NDK folder! + +For more info about usage and available commands use `--help`. + +### Including + +Now that you got Boost compiled you must add it to your `Android.mk` file. Locate the `build` folder and copy the `include` and `lib` folders over to your project's `jni` folder. A recommended path inside your project is `/jni/boost/`. + +Add the following to your `Android.mk` (note that here we're using Boost 1.48 and have assumed that Boost resides inside `/jni/boost`): + + LOCAL_CFLAGS += -I$(LOCAL_PATH)/boost/include/boost-1_48 + LOCAL_LDLIBS += -L$(LOCAL_PATH)/boost/lib/ -lboost_system -lboost_... + + LOCAL_CPPFLAGS += -fexceptions + LOCAL_CPPFLAGS += -frtti + +Now use `ndk-build` to build and have fun with it! + +Note that you should build your project and Boost with the same version of NDK as the C++ STL inside NDK r4 and NDK r5 are not compatible in some subtle details. + +## Contribute + +The projects is split into two main branches, the master and devel. The master branch is where the current stable version lies and which should be used in most of the cases, the devel branch in turn is where development occurs. To contribute to the project make sure to use the devel branch which will make it easier to test changes and to merge incoming pull requests (PR). + +## Troubleshooting + +In case you encounter bunch of linker errors when building your app with boost, +this might help: + +### Building from a 64 bit machine (Linux) + +Make sure you have installed the 32 bit libraries. Those are required to be able +to use the NDK. + +To install them just use the following + + $ sudo apt-get install ia32-libs + +### NDK 7 (CrystaX) + +Add `-lgnustl_static` *AFTER* all boost libraries to the LOCAL_LDLIBS line in +Android.mk. Example: + + LOCAL_LDLIBS += lboost_system-gcc-md lboost_thread-gcc-md -lgnustl_static + +### NDK 8 (official) + +Do everything that is in the NDK 7 Crystax section, but also +add full path to the gnustl_static library to the link paths. Example: + + LOCAL_LDLIBS += lboost_system-gcc-md lboost_thread-gcc-md \ + -L$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi \ + -lgnustl_static diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.bat b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.bat new file mode 100644 index 00000000..08882433 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.bat @@ -0,0 +1,10 @@ +@Echo Off + +sh -c "echo MSYS found. Running ./build-android.sh" +If %ERRORLEVEL% EQU 0 GOTO MSYSOK +echo This script requires MSYS installed and path to its bin folder added to PATH variable +echo Read http://www.mingw.org/wiki/MSYS for more information +GOTO:EOF +:MSYSOK + +sh -c "./build-android.sh %*" diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.sh b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.sh new file mode 100644 index 00000000..d4f71c27 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-android.sh @@ -0,0 +1,435 @@ +#!/bin/sh +# Copyright (C) 2010 Mystic Tree Games +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Moritz "Moss" Wundke (b.thax.dcg@gmail.com) +# +# +# +# Build boost for android completly. It will download boost 1.45.0 +# prepare the build system and finally build it for android + +# Add common build methods +. `dirname $0`/build-common.sh + +# ----------------------- +# Command line arguments +# ----------------------- + +BOOST_VER1=1 +BOOST_VER2=53 +BOOST_VER3=0 +register_option "--boost=" boost_version "Boost version to be used, one of {1.55.0, 1.54.0, 1.53.0, 1.49.0, 1.48.0, 1.45.0}, default is 1.53.0." +boost_version() +{ + if [ "$1" = "1.59.0" ]; then + BOOST_VER1=1 + BOOST_VER2=59 + BOOST_VER3=0 + elif [ "$1" = "1.55.0" ]; then + BOOST_VER1=1 + BOOST_VER2=55 + BOOST_VER3=0 + elif [ "$1" = "1.54.0" ]; then + BOOST_VER1=1 + BOOST_VER2=54 + BOOST_VER3=0 + elif [ "$1" = "1.53.0" ]; then + BOOST_VER1=1 + BOOST_VER2=53 + BOOST_VER3=0 + elif [ "$1" = "1.49.0" ]; then + BOOST_VER1=1 + BOOST_VER2=49 + BOOST_VER3=0 + elif [ "$1" = "1.48.0" ]; then + BOOST_VER1=1 + BOOST_VER2=48 + BOOST_VER3=0 + elif [ "$1" = "1.45.0" ]; then + BOOST_VER1=1 + BOOST_VER2=45 + BOOST_VER3=0 + else + echo "Unsupported boost version '$1'." + exit 1 + fi +} + +register_option "--toolchain=" select_toolchain "Select a toolchain. To see available execute ls -l ANDROID_NDK/toolchains." +select_toolchain () { + TOOLCHAIN=$1 +} + +CLEAN=no +register_option "--clean" do_clean "Delete all previously downloaded and built files, then exit." +do_clean () { CLEAN=yes; } + +DOWNLOAD=no +register_option "--download" do_download "Only download required files and clean up previus build. No build will be performed." + +do_download () +{ + DOWNLOAD=yes + # Clean previus stuff too! + CLEAN=yes +} + +#LIBRARIES=--with-libraries=date_time,filesystem,program_options,regex,signals,system,thread,iostreams +LIBRARIES= +register_option "--with-libraries=" do_with_libraries "Comma separated list of libraries to build." +do_with_libraries () { + for lib in $(echo $1 | tr ',' '\n') ; do LIBRARIES="--with-$lib ${LIBRARIES}"; done +} + +register_option "--without-libraries=" do_without_libraries "Comma separated list of libraries to exclude from the build." +do_without_libraries () { LIBRARIES="--without-libraries=$1"; } +do_without_libraries () { + for lib in $(echo $1 | tr ',' '\n') ; do LIBRARIES="--without-$lib ${LIBRARIES}"; done +} + +register_option "--prefix=" do_prefix "Prefix to be used when installing libraries and includes." +do_prefix () { + if [ -d $1 ]; then + PREFIX=$1; + fi +} + +PROGRAM_PARAMETERS="" +PROGRAM_DESCRIPTION=\ +" Boost For Android\n"\ +"Copyright (C) 2010 Mystic Tree Games\n"\ + +extract_parameters $@ + +echo "Building boost version: $BOOST_VER1.$BOOST_VER2.$BOOST_VER3" + +# ----------------------- +# Build constants +# ----------------------- + +BOOST_DOWNLOAD_LINK="http://downloads.sourceforge.net/project/boost/boost/$BOOST_VER1.$BOOST_VER2.$BOOST_VER3/boost_${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3}.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F${BOOST_VER1}.${BOOST_VER2}.${BOOST_VER3}%2F&ts=1291326673&use_mirror=garr" +BOOST_TAR="boost_${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3}.tar.bz2" +BOOST_DIR="boost_${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3}" +BUILD_DIR="./build/" + +# ----------------------- + +if [ $CLEAN = yes ] ; then + echo "Cleaning: $BUILD_DIR" + rm -f -r $PROGDIR/$BUILD_DIR + + echo "Cleaning: $BOOST_DIR" + rm -f -r $PROGDIR/$BOOST_DIR + + echo "Cleaning: $BOOST_TAR" + rm -f $PROGDIR/$BOOST_TAR + + echo "Cleaning: logs" + rm -f -r logs + rm -f build.log + + [ "$DOWNLOAD" = "yes" ] || exit 0 +fi + +# It is almost never desirable to have the boost-X_Y_Z directory from +# previous builds as this script doesn't check in which state it's +# been left (bootstrapped, patched, built, ...). Unless maybe during +# a debug, in which case it's easy for a developer to comment out +# this code. + +if [ -d "$PROGDIR/$BOOST_DIR" ]; then + echo "Cleaning: $BOOST_DIR" + rm -f -r $PROGDIR/$BOOST_DIR +fi + +if [ -d "$PROGDIR/$BUILD_DIR" ]; then + echo "Cleaning: $BUILD_DIR" + rm -f -r $PROGDIR/$BUILD_DIR +fi + + +AndroidNDKRoot=$PARAMETERS +if [ -z "$AndroidNDKRoot" ] ; then + if [ -n "${ANDROID_BUILD_TOP}" ]; then # building from Android sources + AndroidNDKRoot="${ANDROID_BUILD_TOP}/prebuilts/ndk/current" + export AndroidSourcesDetected=1 + elif [ -z "`which ndk-build`" ]; then + dump "ERROR: You need to provide a !" + exit 1 + else + AndroidNDKRoot=`which ndk-build` + AndroidNDKRoot=`dirname $AndroidNDKRoot` + fi + echo "Using AndroidNDKRoot = $AndroidNDKRoot" +else + # User passed the NDK root as a parameter. Make sure the directory + # exists and make it an absolute path. + if [ ! -f "$AndroidNDKRoot/ndk-build" ]; then + dump "ERROR: $AndroidNDKRoot is not a valid NDK root" + exit 1 + fi + AndroidNDKRoot=$(cd $AndroidNDKRoot; pwd -P) +fi +export AndroidNDKRoot + +# Check platform patch +case "$HOST_OS" in + linux) + PlatformOS=linux + ;; + darwin|freebsd) + PlatformOS=darwin + ;; + windows|cygwin) + PlatformOS=windows + ;; + *) # let's play safe here + PlatformOS=linux +esac + +NDK_RELEASE_FILE=$AndroidNDKRoot"/RELEASE.TXT" +if [ -f "${NDK_RELEASE_FILE}" ]; then + NDK_RN=`cat $NDK_RELEASE_FILE | sed 's/^r\(.*\)$/\1/g'` +elif [ -n "${AndroidSourcesDetected}" ]; then + if [ -f "${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" ]; then + NDK_RELEASE_FILE="${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" + NDK_RN=`grep "android-ndk-" "${NDK_RELEASE_FILE}" | head -1 | sed 's/^.*r\(.*\)$/\1/'` + elif [ -f "${ANDROID_BUILD_TOP}/ndk/docs/text/CHANGES.text" ]; then + NDK_RELEASE_FILE="${ANDROID_BUILD_TOP}/ndk/docs/text/CHANGES.text" + NDK_RN=`grep "android-ndk-" "${NDK_RELEASE_FILE}" | head -1 | sed 's/^.*r\(.*\)$/\1/'` + else + dump "ERROR: can not find ndk version" + exit 1 + fi +else + dump "ERROR: can not find ndk version" + exit 1 +fi + +echo "Detected Android NDK version $NDK_RN" + +case "$NDK_RN" in + 4*) + TOOLCHAIN=${TOOLCHAIN:-arm-eabi-4.4.0} + CXXPATH=$AndroidNDKRoot/build/prebuilt/$PlatformOS-x86/${TOOLCHAIN}/bin/arm-eabi-g++ + TOOLSET=gcc-androidR4 + ;; + 5*) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.4.3} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR5 + ;; + 7-crystax-5.beta3) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6.3} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR7crystax5beta3 + ;; + 8) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.4.3} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8 + ;; + 8b|8c|8d) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8b + ;; + 8e|9|9b|9c|9d) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8e + ;; + "8e (64-bit)") + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8e + ;; + "9 (64-bit)"|"9b (64-bit)"|"9c (64-bit)"|"9d (64-bit)") + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8e + ;; + "10 (64-bit)") + TOOLCHAIN=llvm-3.4 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e + ;; + "10e-rc4 (64-bit)") + TOOLCHAIN=llvm-3.6 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e + ;; + *) + echo "Undefined or not supported Android NDK version!" + exit 1 +esac + +if [ -n "${AndroidSourcesDetected}" ]; then # Overwrite CXXPATH if we are building from Android sources + CXXPATH="${ANDROID_TOOLCHAIN}/arm-linux-androideabi-g++" +fi + +echo Building with TOOLSET=$TOOLSET CXXPATH=$CXXPATH CXXFLAGS=$CXXFLAGS | tee $PROGDIR/build.log + +# Check if the ndk is valid or not +if [ ! -f $CXXPATH ] +then + echo "Cannot find C++ compiler at: $CXXPATH" + exit 1 +fi + +# ----------------------- +# Download required files +# ----------------------- + +# Downalod and unzip boost in a temporal folder and +if [ ! -f $BOOST_TAR ] +then + echo "Downloading boost ${BOOST_VER1}.${BOOST_VER2}.${BOOST_VER3} please wait..." + prepare_download + download_file $BOOST_DOWNLOAD_LINK $PROGDIR/$BOOST_TAR +fi + +if [ ! -f $PROGDIR/$BOOST_TAR ] +then + echo "Failed to download boost! Please download boost ${BOOST_VER1}.${BOOST_VER2}.${BOOST_VER3} manually\nand save it in this directory as $BOOST_TAR" + exit 1 +fi + +if [ ! -d $PROGDIR/$BOOST_DIR ] +then + echo "Unpacking boost" + if [ $OPTION_PROGRESS = "yes" ] ; then + pv $PROGDIR/$BOOST_TAR | tar xjf - -C $PROGDIR + else + tar xjf $PROGDIR/$BOOST_TAR + fi +fi + +if [ $DOWNLOAD = yes ] ; then + echo "All required files has been downloaded and unpacked!" + exit 0 +fi + +# --------- +# Bootstrap +# --------- +if [ ! -f ./$BOOST_DIR/bjam ] +then + # Make the initial bootstrap + echo "Performing boost bootstrap" + + cd $BOOST_DIR + case "$HOST_OS" in + windows) + cmd //c "bootstrap.bat" 2>&1 | tee -a $PROGDIR/build.log + ;; + *) # Linux and others + ./bootstrap.sh 2>&1 | tee -a $PROGDIR/build.log + esac + + + if [ $? != 0 ] ; then + dump "ERROR: Could not perform boostrap! See $TMPLOG for more info." + exit 1 + fi + cd $PROGDIR + + # ------------------------------------------------------------- + # Patching will be done only if we had a successfull bootstrap! + # ------------------------------------------------------------- + + # Apply patches to boost + BOOST_VER=${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3} + PATCH_BOOST_DIR=$PROGDIR/patches/boost-${BOOST_VER} + + cp configs/user-config-boost-${BOOST_VER}.jam $BOOST_DIR/tools/build/src/user-config.jam + + #for dir in $PATCH_BOOST_DIR; do + # if [ ! -d "$dir" ]; then + # echo "Could not find directory '$dir' while looking for patches" + # exit 1 + # fi + + # PATCHES=`(cd $dir && ls *.patch | sort) 2> /dev/null` + + # if [ -z "$PATCHES" ]; then + # echo "No patches found in directory '$dir'" + # exit 1 + # fi + + # for PATCH in $PATCHES; do + # PATCH=`echo $PATCH | sed -e s%^\./%%g` + # SRC_DIR=$PROGDIR/$BOOST_DIR + # PATCHDIR=`dirname $PATCH` + # PATCHNAME=`basename $PATCH` + # log "Applying $PATCHNAME into $SRC_DIR/$PATCHDIR" + # cd $SRC_DIR && patch -p1 < $dir/$PATCH && cd $PROGDIR + # if [ $? != 0 ] ; then + # dump "ERROR: Patch failure !! Please check your patches directory!" + # dump " Try to perform a clean build using --clean ." + # dump " Problem patch: $dir/$PATCHNAME" + # exit 1 + # fi + # done + #done +fi + +echo "# ---------------" +echo "# Build using NDK" +echo "# ---------------" + +# Build boost for android +echo "Building boost for android" +( + cd $BOOST_DIR + + echo "Adding pathname: `dirname $CXXPATH`" + # `AndroidBinariesPath` could be used by user-config-boost-*.jam + export AndroidBinariesPath=`dirname $CXXPATH` + export PATH=$AndroidBinariesPath:$PATH + export AndroidNDKRoot + export NO_BZIP2=1 + export ICONV_PATH="`pwd`/../../libiconv/x86" + + cxxflags="" + for flag in $CXXFLAGS; do cxxflags="$cxxflags cxxflags=$flag"; done + + { ./bjam -q \ + target-os=linux \ + toolset=$TOOLSET \ + $cxxflags \ + link=static \ + threading=multi \ + --layout=versioned \ + --prefix="./../$BUILD_DIR/" \ + boost.locale.posix=off \ + boost.locale.std=on \ + boost.locale.iconv=on \ + boost.locale.icu=off \ + $LIBRARIES \ + release debug install 2>&1 \ + || { dump "ERROR: Failed to build boost for android!" ; exit 1 ; } + } | tee -a $PROGDIR/build.log + + # PIPESTATUS variable is defined only in Bash, and we are using /bin/sh, which is not Bash on newer Debian/Ubuntu +) + +dump "Done!" + +if [ $PREFIX ]; then + echo "Prefix set, copying files to $PREFIX" + cp -r $PROGDIR/$BUILD_DIR/lib $PREFIX + cp -r $PROGDIR/$BUILD_DIR/include $PREFIX +fi diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-common.sh b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-common.sh new file mode 100644 index 00000000..3275a9b5 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/build-common.sh @@ -0,0 +1,671 @@ +#!/bin/sh +# +# Copyright (C) 2010 Mystic Tree Games +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Moritz "Moss" Wundke (b.thax.dcg@gmail.com) +# +# +# +# Adapted common build methods from NDK-Common.sh and prebuilt-common.sh +# from the Android NDK +# + +# Current script name into PROGNAME +PROGNAME=`basename $0` +PROGDIR=`pwd` + +## Logging support +## +VERBOSE=${VERBOSE-yes} +VERBOSE2=${VERBOSE2-no} + +TMPLOG= + +# Setup a log file where all log() and log2() output will be sent +# +# $1: log file path (optional) +# +setup_log_file () +{ + if [ -n "$1" ] ; then + TMPLOG="$1" + else + mkdir -p $PROGDIR/logs/ + TMPLOG=$PROGDIR/logs/myst-log-$$.log + fi + rm -f $TMPLOG && touch $TMPLOG + echo "To follow build in another terminal, please use: tail -F $TMPLOG" +} + +dump () +{ + if [ -n "$TMPLOG" ] ; then + echo "$@" >> $TMPLOG + fi + echo "$@" +} + +log () +{ + if [ "$VERBOSE" = "yes" ] ; then + echo "$@" + else + if [ "$TMPLOG" ] ; then + echo "$@" >> $TMPLOG + fi + fi +} + +log2 () +{ + if [ "$VERBOSE2" = "yes" ] ; then + echo "$@" + else + if [ -n "$TMPLOG" ] ; then + echo "$@" >> $TMPLOG + fi + fi +} + +run () +{ + if [ "$VERBOSE" = "yes" ] ; then + echo "##### NEW COMMAND" + echo "$@" + $@ 2>&1 + else + if [ -n "$TMPLOG" ] ; then + echo "##### NEW COMMAND" >> $TMPLOG + echo "$@" >> $TMPLOG + $@ 2>&1 | tee -a $TMPLOG + else + $@ > /dev/null 2>&1 + fi + fi +} + +## Utilities +## + +# Generate a random temp directory +random_temp_directory () +{ + mktemp -d /tmp/myst-dir-XXXXXX +} + +# return the value of a given named variable +# $1: variable name +# +# example: +# FOO=BAR +# BAR=ZOO +# echo `var_value $FOO` +# will print 'ZOO' +# +var_value () +{ + # find a better way to do that ? + eval echo "$`echo $1`" +} + +# convert to uppercase +# assumes tr is installed on the platform ? +# +to_uppercase () +{ + echo $1 | tr "[:lower:]" "[:upper:]" +} + +## Normalize OS and CPU +## +HOST_ARCH=`uname -m` +case "$HOST_ARCH" in + i?86) HOST_ARCH=x86 + ;; + amd64) HOST_ARCH=x86_64 + ;; + powerpc) HOST_ARCH=ppc + ;; +esac + +log2 "HOST_ARCH=$HOST_ARCH" + +# at this point, the supported values for CPU are: +# x86 +# x86_64 +# ppc +# +# other values may be possible but haven't been tested +# +HOST_EXE="" +HOST_OS=`uname -s` +case "$HOST_OS" in + Darwin) + HOST_OS=darwin + ;; + Linux) + # note that building 32-bit binaries on x86_64 is handled later + HOST_OS=linux + ;; + FreeBsd) # note: this is not tested + HOST_OS=freebsd + ;; + CYGWIN*|*_NT-*) + HOST_OS=windows + HOST_EXE=.exe + if [ "x$OSTYPE" = xcygwin ] ; then + HOST_OS=cygwin + fi + ;; +esac + +log2 "HOST_OS=$HOST_OS" +log2 "HOST_EXE=$HOST_EXE" + +# at this point, the value of HOST_OS should be one of the following: +# linux +# darwin +# windows (MSys) +# cygwin +# +# Note that cygwin is treated as a special case because it behaves very differently +# for a few things. Other values may be possible but have not been tested +# + +# define HOST_TAG as a unique tag used to identify both the host OS and CPU +# supported values are: +# +# linux-x86 +# linux-x86_64 +# darwin-x86 +# darwin-ppc +# windows +# +# other values are possible but were not tested. +# +compute_host_tag () +{ + case "$HOST_OS" in + windows|cygwin) + HOST_TAG="windows" + ;; + *) HOST_TAG="${HOST_OS}-${HOST_ARCH}" + esac + log2 "HOST_TAG=$HOST_TAG" +} + +compute_host_tag + +# Compute the number of host CPU cores an HOST_NUM_CPUS +# +case "$HOST_OS" in + linux) + HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l` + ;; + darwin|freebsd) + HOST_NUM_CPUS=`sysctl -n hw.ncpu` + ;; + windows|cygwin) + HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS + ;; + *) # let's play safe here + HOST_NUM_CPUS=1 +esac + +log2 "HOST_NUM_CPUS=$HOST_NUM_CPUS" + +# If BUILD_NUM_CPUS is not already defined in your environment, +# define it as the double of HOST_NUM_CPUS. This is used to +# run Make commends in parralles, as in 'make -j$BUILD_NUM_CPUS' +# +if [ -z "$BUILD_NUM_CPUS" ] ; then + BUILD_NUM_CPUS=`expr $HOST_NUM_CPUS \* 2` +fi + +log2 "BUILD_NUM_CPUS=$BUILD_NUM_CPUS" + +# Various probes are going to need to run a small C program +TMPC=/tmp/myst-$$-test.c +TMPO=/tmp/myst-$$-test.o +TMPE=/tmp/myst-$$-test$EXE +TMPL=/tmp/myst-$$-test.log + +# cleanup temporary files +clean_temp () +{ + rm -f $TMPC $TMPO $TMPL $TMPE +} + +# cleanup temp files then exit with an error +clean_exit () +{ + clean_temp + exit 1 +} + +pattern_match () +{ + echo "$2" | grep -q -E -e "$1" +} + +# Let's check that we have a working md5sum here +check_md5sum () +{ + A_MD5=`echo "A" | md5sum | cut -d' ' -f1` + if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then + echo "Please install md5sum on this machine" + exit 2 + fi +} + +# Find if a given shell program is available. +# We need to take care of the fact that the 'which ' command +# may return either an empty string (Linux) or something like +# "no in ..." (Darwin). Also, we need to redirect stderr +# to /dev/null for Cygwin +# +# $1: variable name +# $2: program name +# +# Result: set $1 to the full path of the corresponding command +# or to the empty/undefined string if not available +# +find_program () +{ + local PROG + PROG=`which $2 2>/dev/null` + if [ -n "$PROG" ] ; then + if pattern_match '^no ' "$PROG"; then + PROG= + fi + fi + eval $1="$PROG" +} + +prepare_download () +{ + find_program CMD_WGET wget + find_program CMD_CURL curl + find_program CMD_SCRP scp +} + +# Download a file with either 'curl', 'wget' or 'scp' +# +# $1: source URL (e.g. http://foo.com, ssh://blah, /some/path) +# $2: target file +download_file () +{ + # Is this HTTP, HTTPS or FTP ? + if pattern_match "^(http|https|ftp):.*" "$1"; then + if [ -n "$CMD_WGET" ] ; then + run $CMD_WGET -O $2 $1 + elif [ -n "$CMD_CURL" ] ; then + run $CMD_CURL -o -L $2 $1 + else + echo "Please install wget or curl on this machine" + exit 1 + fi + return + fi + + # Is this SSH ? + # Accept both ssh:// or : + # + if pattern_match "^(ssh|[^:]+):.*" "$1"; then + if [ -n "$CMD_SCP" ] ; then + scp_src=`echo $1 | sed -e s%ssh://%%g` + run $CMD_SCP $scp_src $2 + else + echo "Please install scp on this machine" + exit 1 + fi + return + fi + + # Is this a file copy ? + # Accept both file:// or / + # + if pattern_match "^(file://|/).*" "$1"; then + cp_src=`echo $1 | sed -e s%^file://%%g` + run cp -f $cp_src $2 + return + fi +} + +# Return the maximum length of a series of strings +# +# Usage: len=`max_length ...` +# +max_length () +{ + echo "$@" | tr ' ' '\n' | awk 'BEGIN {max=0} {len=length($1); if (len > max) max=len} END {print max}' +} + +# Translate dashes to underscores +# Usage: str=`dashes_to_underscores ` +dashes_to_underscores () +{ + echo $@ | tr '-' '_' +} + +# Translate underscores to dashes +# Usage: str=`underscores_to_dashes ` +underscores_to_dashes () +{ + echo $@ | tr '_' '-' +} + +#----------------------------------------------------------------------- +# OPTION PROCESSING +#----------------------------------------------------------------------- + +# We recognize the following option formats: +# +# -f +# --flag +# +# -s +# --setting= +# + +# NOTE: We translate '-' into '_' when storing the options in global +# variables +# + +OPTIONS="" +OPTION_FLAGS="" +OPTION_SETTINGS="" + +# Set a given option attribute +# $1: option name +# $2: option attribute +# $3: attribute value +# +option_set_attr () +{ + eval OPTIONS_$1_$2=\"$3\" +} + +# Get a given option attribute +# $1: option name +# $2: option attribute +# +option_get_attr () +{ + echo `var_value OPTIONS_$1_$2` +} + +# Determine optional variable value +# $1: final variable name +# $2: option variable name +# $3: small description for the option +fix_option () +{ + if [ -n "$2" ] ; then + eval $1="$2" + log "Using specific $3: $2" + else + log "Using default $3: `var_value $1`" + fi +} + +# Register a new option +# $1: option +# $2: name of function that will be called when the option is parsed +# $3: small abstract for the option +# $4: optional. default value +# +register_option () +{ + local optname optvalue opttype optlabel + optlabel= + optname= + optvalue= + opttype= + while [ -n "1" ] ; do + # Check for something like --setting= + echo "$1" | grep -q -E -e '^--[^=]+=<.+>$' + if [ $? = 0 ] ; then + optlabel=`expr -- "$1" : '\(--[^=]*\)=.*'` + optvalue=`expr -- "$1" : '--[^=]*=\(<.*>\)'` + opttype="long_setting" + break + fi + + # Check for something like --flag + echo "$1" | grep -q -E -e '^--[^=]+$' + if [ $? = 0 ] ; then + optlabel="$1" + opttype="long_flag" + break + fi + + # Check for something like -f + echo "$1" | grep -q -E -e '^-[A-Za-z0-9]<.+>$' + if [ $? = 0 ] ; then + optlabel=`expr -- "$1" : '\(-.\).*'` + optvalue=`expr -- "$1" : '-.\(<.+>\)'` + opttype="short_setting" + break + fi + + # Check for something like -f + echo "$1" | grep -q -E -e '^-.$' + if [ $? = 0 ] ; then + optlabel="$1" + opttype="short_flag" + break + fi + + echo "ERROR: Invalid option format: $1" + echo " Check register_option call" + exit 1 + done + + log "new option: type='$opttype' name='$optlabel' value='$optvalue'" + + optname=`dashes_to_underscores $optlabel` + OPTIONS="$OPTIONS $optname" + OPTIONS_TEXT="$OPTIONS_TEXT $1" + option_set_attr $optname label "$optlabel" + option_set_attr $optname otype "$opttype" + option_set_attr $optname value "$optvalue" + option_set_attr $optname text "$1" + option_set_attr $optname funcname "$2" + option_set_attr $optname abstract "$3" + option_set_attr $optname default "$4" +} + +# Print the help, including a list of registered options for this program +# Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and +# correspond to the parameters list and the program description +# +print_help () +{ + local opt text abstract default + + echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS" + echo "" + if [ -n "$PROGRAM_DESCRIPTION" ] ; then + echo "$PROGRAM_DESCRIPTION" + echo "" + fi + echo "Valid options (defaults are in brackets):" + echo "" + + maxw=`max_length "$OPTIONS_TEXT"` + AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"` + for opt in $OPTIONS; do + text=`option_get_attr $opt text | awk "$AWK_SCRIPT"` + abstract=`option_get_attr $opt abstract` + default=`option_get_attr $opt default` + if [ -n "$default" ] ; then + echo " $text $abstract [$default]" + else + echo " $text $abstract" + fi + done + echo "" +} + +option_panic_no_args () +{ + echo "ERROR: Option '$1' does not take arguments. See --help for usage." + exit 1 +} + +option_panic_missing_arg () +{ + echo "ERROR: Option '$1' requires an argument. See --help for usage." + exit 1 +} + +extract_parameters () +{ + local opt optname otype value name fin funcname + PARAMETERS="" + while [ -n "$1" ] ; do + # If the parameter does not begin with a dash + # it is not an option. + param=`expr -- "$1" : '^\([^\-].*\)$'` + if [ -n "$param" ] ; then + if [ -z "$PARAMETERS" ] ; then + PARAMETERS="$1" + else + PARAMETERS="$PARAMETERS $1" + fi + shift + continue + fi + + while [ -n "1" ] ; do + # Try to match a long setting, i.e. --option=value + opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'` + if [ -n "$opt" ] ; then + otype="long_setting" + value=`expr -- "$1" : '^--[^=]*=\(.*\)$'` + break + fi + + # Try to match a long flag, i.e. --option + opt=`expr -- "$1" : '^\(--.*\)$'` + if [ -n "$opt" ] ; then + otype="long_flag" + value= + break + fi + + # Try to match a short setting, i.e. -o + opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'` + if [ -n "$opt" ] ; then + otype="short_setting" + value=`expr -- "$1" : '^-.\(.*\)$'` + break + fi + + # Try to match a short flag, i.e. -o + opt=`expr -- "$1" : '^\(-.\)$'` + if [ -n "$opt" ] ; then + otype="short_flag" + value= + break + fi + + echo "ERROR: Unknown option '$1'. Use --help for list of valid values." + exit 1 + done + + #echo "Found opt='$opt' otype='$otype' value='$value'" + + name=`dashes_to_underscores $opt` + found=0 + for xopt in $OPTIONS; do + if [ "$name" != "$xopt" ] ; then + continue + fi + # Check that the type is correct here + # + # This also allows us to handle -o as -o + # + xotype=`option_get_attr $name otype` + if [ "$otype" != "$xotype" ] ; then + case "$xotype" in + "short_flag") + option_panic_no_args $opt + ;; + "short_setting") + if [ -z "$2" ] ; then + option_panic_missing_arg $opt + fi + value="$2" + shift + ;; + "long_flag") + option_panic_no_args $opt + ;; + "long_setting") + option_panic_missing_arg $opt + ;; + esac + fi + found=1 + break + break + done + if [ "$found" = "0" ] ; then + echo "ERROR: Unknown option '$opt'. See --help for usage." + exit 1 + fi + # Launch option-specific function, value, if any as argument + eval `option_get_attr $name funcname` \"$value\" + shift + done + + # Change log out put if requested + if [ "x$OPTION_OUTPUT" != "x" ] ; then + setup_log_file $OPTION_OUTPUT + else + setup_log_file + fi +} + +do_option_help () +{ + print_help + exit 0 +} + +VERBOSE=no +VERBOSE2=no +do_option_verbose () +{ + if [ $VERBOSE = "yes" ] ; then + VERBOSE2=yes + else + VERBOSE=yes + fi +} + +OPTION_OUTPUT= +do_logpath () { OPTION_OUTPUT=$1; } + +do_progress_bar() +{ + OPTION_PROGRESS="yes" +} + +register_option "--help" do_option_help "Print this help." +register_option "--verbose" do_option_verbose "Enable verbose mode." +register_option "--output=" do_logpath "Specify specific log output path (only terminal output by default)" +register_option "--progress" do_progress_bar "Enable extraction progress bar" diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_45_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_45_0.jam new file mode 100644 index 00000000..1cc43a1f --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_45_0.jam @@ -0,0 +1,269 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference.html#bbv2.reference.init +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# ---------------------- +# Android configurations. +# ---------------------- + +# -------------------------------------------------------------------- + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using gcc : androidR4 +: +arm-eabi-c++ +: +arm-eabi-ar +-I$(AndroidNDKRoot)/build/platforms/android-8/arch-arm/usr/include +-fpic +-mthumb-interwork +-ffunction-sections +-funwind-tables +-fstack-protector +-fno-short-enums +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-DANDROID +-D__ANDROID__ +-Wa,--noexecstack +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR5 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-8/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +-I$(AndroidNDKRoot)/sources/wchar-support/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR7crystax5beta3 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include/4.6.3 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/4.6.3/include +-I$(AndroidNDKRoot)/sources/crystax/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-DBOOST_THREAD_LINUX +-DBOOST_HAS_PTHREADS +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +-DBOOST_HAS_GETTIMEOFDAY +; + +# -------------------------------------------------------------------- +using gcc : androidR8 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_48_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_48_0.jam new file mode 100644 index 00000000..6e5437d5 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_48_0.jam @@ -0,0 +1,231 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ---------------------- +# Android configuration. +# ---------------------- + +# -------------------------------------------------------------------- + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using gcc : androidR7crystax5beta3 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include/4.6.3 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/4.6.3/include +-I$(AndroidNDKRoot)/sources/crystax/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8b +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_49_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_49_0.jam new file mode 100644 index 00000000..4027f2c5 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_49_0.jam @@ -0,0 +1,273 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + +# ------------------ +# Android configurations. +# ------------------ +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using gcc : androidR7crystax5beta3 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include/4.6.3 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/4.6.3/include +-I$(AndroidNDKRoot)/sources/crystax/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +# Is same for 8b, 8c and 8d +using gcc : androidR8b +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8e +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_53_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_53_0.jam new file mode 100644 index 00000000..b9bf10df --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_53_0.jam @@ -0,0 +1,130 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; +local AndroidBinariesPath = [ os.environ AndroidBinariesPath ] ; + +# -------------------------------------------------------------------- +# Is same for 8b, 8c and 8d +using gcc : androidR8b +: +$(AndroidBinariesPath)/arm-linux-androideabi-g++ +: +$(AndroidBinariesPath)/arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8e +: +$(AndroidBinariesPath)/arm-linux-androideabi-g++ +: +$(AndroidBinariesPath)/arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_54_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_54_0.jam new file mode 100644 index 00000000..666d4c86 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_54_0.jam @@ -0,0 +1,186 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +# Is same for 8b, 8c and 8d +using gcc : androidR8b +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8e +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_55_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_55_0.jam new file mode 100644 index 00000000..762753ea --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_55_0.jam @@ -0,0 +1,139 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using clang : androidR8e +: +$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/linux-x86_64/bin/clang++ +: +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/linux-x86_64" +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-fstack-protector +-no-canonical-prefixes +--target=i686-none-linux-android +--sysroot="$(AndroidNDKRoot)/platforms/android-9/arch-x86" +-Os +-fomit-frame-pointer +-fstrict-aliasing +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/include +--target=i686-none-linux-android +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/linux-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-x86 +# @Moss - Above are the 'oficial' android flags +#i686 +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D_REENTRANT +-D_GLIBCXX__PTHREADS +-std=c++11 +; + + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_59_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_59_0.jam new file mode 100644 index 00000000..762753ea --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/configs/user-config-boost-1_59_0.jam @@ -0,0 +1,139 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using clang : androidR8e +: +$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/linux-x86_64/bin/clang++ +: +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/linux-x86_64" +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-fstack-protector +-no-canonical-prefixes +--target=i686-none-linux-android +--sysroot="$(AndroidNDKRoot)/platforms/android-9/arch-x86" +-Os +-fomit-frame-pointer +-fstrict-aliasing +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/include +--target=i686-none-linux-android +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/linux-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-x86 +# @Moss - Above are the 'oficial' android flags +#i686 +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D_REENTRANT +-D_GLIBCXX__PTHREADS +-std=c++11 +; + + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/cpprestsdk.patched.stamp b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/cpprestsdk.patched.stamp new file mode 100644 index 00000000..e69de29b diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/address_v6.ipp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/address_v6.ipp.patch new file mode 100644 index 00000000..034f4af1 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/address_v6.ipp.patch @@ -0,0 +1,26 @@ +--- boost_1_45_0-old/boost/asio/ip/impl/address_v6.ipp 2010-06-09 12:40:46.000000000 +0300 ++++ boost_1_45_0/boost/asio/ip/impl/address_v6.ipp 2011-06-06 15:29:57.777421112 +0300 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.jam.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.jam.patch new file mode 100644 index 00000000..f16acf65 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.jam.patch @@ -0,0 +1,1067 @@ +--- boost_1_45_0-old/tools/build/v2/tools/android.jam 1970-01-01 03:00:00.000000000 +0300 ++++ boost_1_45_0/tools/build/v2/tools/android.jam 2011-06-06 15:29:57.787421112 +0300 +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.py.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.py.patch new file mode 100644 index 00000000..df332750 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/android.py.patch @@ -0,0 +1,801 @@ +--- boost_1_45_0-old/tools/build/v2/tools/android.py 1970-01-01 03:00:00.000000000 +0300 ++++ boost_1_45_0/tools/build/v2/tools/android.py 2011-06-06 15:29:57.787421112 +0300 +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/endian.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/endian.hpp.patch new file mode 100644 index 00000000..0d4d2ed0 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/endian.hpp.patch @@ -0,0 +1,12 @@ +diff -u -r boost_1_45_0-old/boost/detail/endian.hpp boost_1_45_0/boost/detail/endian.hpp +--- boost_1_45_0-old/boost/detail/endian.hpp 2010-11-17 11:51:56.000000000 +0200 ++++ boost_1_45_0/boost/detail/endian.hpp 2011-07-28 13:51:36.988916179 +0300 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/fenced_block.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/fenced_block.hpp.patch new file mode 100644 index 00000000..697816b4 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/fenced_block.hpp.patch @@ -0,0 +1,38 @@ +--- boost_1_45_0-old/boost/asio/detail/fenced_block.hpp 2010-07-12 02:42:34.000000000 +0300 ++++ boost_1_45_0/boost/asio/detail/fenced_block.hpp 2011-06-06 15:29:57.777421112 +0300 +@@ -25,14 +25,15 @@ + # include + #elif defined(__sun) + # include +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + # include + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + # include + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + # include + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + # include +@@ -54,14 +55,15 @@ + typedef macos_fenced_block fenced_block; + #elif defined(__sun) + typedef solaris_fenced_block fenced_block; +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + typedef gcc_arm_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + typedef gcc_hppa_fenced_block fenced_block; + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + typedef gcc_sync_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + typedef gcc_x86_fenced_block fenced_block; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/operations.cpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/operations.cpp.patch new file mode 100644 index 00000000..d34f79ea --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/operations.cpp.patch @@ -0,0 +1,39 @@ +--- boost_1_45_0-old/libs/filesystem/v3/src/operations.cpp 2010-10-16 16:09:25.000000000 +0300 ++++ boost_1_45_0/libs/filesystem/v3/src/operations.cpp 2011-06-06 15:29:57.787421112 +0300 +@@ -66,13 +66,15 @@ + # ifdef BOOST_POSIX_API + + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -201,7 +203,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/socket_types.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/socket_types.hpp.patch new file mode 100644 index 00000000..a11a4a0d --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/socket_types.hpp.patch @@ -0,0 +1,15 @@ +--- boost_1_45_0-old/boost/asio/detail/socket_types.hpp 2010-10-17 15:24:50.000000000 +0300 ++++ boost_1_45_0/boost/asio/detail/socket_types.hpp 2011-06-06 15:29:57.777421112 +0300 +@@ -122,7 +122,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/user.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/user.hpp.patch new file mode 100644 index 00000000..c1e47b3b --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/user.hpp.patch @@ -0,0 +1,18 @@ +--- boost_1_45_0-old/boost/config/user.hpp 2004-01-10 14:10:00.000000000 +0200 ++++ boost_1_45_0/boost/config/user.hpp 2011-06-06 15:29:57.797421112 +0300 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/v2_operations.cpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/v2_operations.cpp.patch new file mode 100644 index 00000000..03c9ebce --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/v2_operations.cpp.patch @@ -0,0 +1,31 @@ +--- boost_1_45_0-old/libs/filesystem/v2/src/v2_operations.cpp 2010-08-10 23:00:09.000000000 +0300 ++++ boost_1_45_0/libs/filesystem/v2/src/v2_operations.cpp 2011-06-06 15:29:57.777421112 +0300 +@@ -58,13 +58,15 @@ + + # else // BOOST_POSIX_API + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + #ifdef __OpenBSD__ + # include ++#elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + #endif + # include + # define BOOST_STATVFS statfs +@@ -1262,7 +1264,11 @@ + if ( max == 0 ) + { + errno = 0; ++# ifdef __ANDROID__ || ANDROID ++ long tmp = 4096; ++# else + long tmp = ::pathconf( "/", _PC_NAME_MAX ); ++# endif + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/workaround.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/workaround.hpp.patch new file mode 100644 index 00000000..7c25a2fe --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_45_0/workaround.hpp.patch @@ -0,0 +1,11 @@ +--- boost_1_45_0-old/boost/interprocess/detail/workaround.hpp 2010-10-12 21:18:42.000000000 +0300 ++++ boost_1_45_0/boost/interprocess/detail/workaround.hpp 2011-06-06 15:29:57.797421112 +0300 +@@ -64,7 +64,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) + # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_48_0/boost-1_48_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_48_0/boost-1_48_0.patch new file mode 100644 index 00000000..ec057ce9 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_48_0/boost-1_48_0.patch @@ -0,0 +1,2069 @@ +diff -ruN boost_1_48_0-boot/boost/asio/detail/fenced_block.hpp boost_1_48_0-patched/boost/asio/detail/fenced_block.hpp +--- boost_1_48_0-boot/boost/asio/detail/fenced_block.hpp 2011-10-09 23:59:57.000000000 +0200 ++++ boost_1_48_0-patched/boost/asio/detail/fenced_block.hpp 2012-06-16 23:59:57.000000000 +0200 +@@ -25,7 +25,7 @@ + # include + #elif defined(__sun) + # include +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + # include + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + # include +@@ -34,7 +34,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + # include + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + # include +@@ -54,7 +55,7 @@ + typedef macos_fenced_block fenced_block; + #elif defined(__sun) + typedef solaris_fenced_block fenced_block; +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + typedef gcc_arm_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + typedef gcc_hppa_fenced_block fenced_block; +@@ -63,7 +64,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + typedef gcc_sync_fenced_block fenced_block; + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + typedef win_fenced_block fenced_block; +diff -ruN boost_1_48_0-boot/boost/asio/detail/socket_types.hpp boost_1_48_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_48_0-boot/boost/asio/detail/socket_types.hpp 2011-06-06 01:21:43.000000000 +0200 ++++ boost_1_48_0-patched/boost/asio/detail/socket_types.hpp 2012-06-16 23:55:05.000000000 +0200 +@@ -123,7 +123,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_48_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_48_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_48_0-boot/boost/asio/ip/impl/address_v6.ipp 2011-06-06 01:21:43.000000000 +0200 ++++ boost_1_48_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-16 23:53:27.000000000 +0200 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_48_0-boot/boost/config/user.hpp boost_1_48_0-patched/boost/config/user.hpp +--- boost_1_48_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100 ++++ boost_1_48_0-patched/boost/config/user.hpp 2012-06-16 23:58:53.000000000 +0200 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_48_0-boot/boost/detail/endian.hpp boost_1_48_0-patched/boost/detail/endian.hpp +--- boost_1_48_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200 ++++ boost_1_48_0-patched/boost/detail/endian.hpp 2012-06-16 23:57:19.000000000 +0200 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN +diff -ruN boost_1_48_0-boot/boost/interprocess/detail/workaround.hpp boost_1_48_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_48_0-boot/boost/interprocess/detail/workaround.hpp 2011-08-30 17:46:15.000000000 +0200 ++++ boost_1_48_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-17 00:05:30.000000000 +0200 +@@ -64,7 +64,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) + # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_48_0-boot/libs/filesystem/v2/src/v2_operations.cpp boost_1_48_0-patched/libs/filesystem/v2/src/v2_operations.cpp +--- boost_1_48_0-boot/libs/filesystem/v2/src/v2_operations.cpp 2011-07-29 21:51:24.000000000 +0200 ++++ boost_1_48_0-patched/libs/filesystem/v2/src/v2_operations.cpp 2012-06-17 00:02:25.000000000 +0200 +@@ -58,13 +58,15 @@ + + # else // BOOST_POSIX_API + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + #ifdef __OpenBSD__ + # include ++#elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + #endif + # include + # define BOOST_STATVFS statfs +@@ -1265,7 +1267,11 @@ + if ( max == 0 ) + { + errno = 0; ++# ifdef __ANDROID__ || ANDROID ++ long tmp = 4096; ++# else + long tmp = ::pathconf( "/", _PC_NAME_MAX ); ++# endif + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate +diff -ruN boost_1_48_0-boot/libs/filesystem/v3/src/operations.cpp boost_1_48_0-patched/libs/filesystem/v3/src/operations.cpp +--- boost_1_48_0-boot/libs/filesystem/v3/src/operations.cpp 2011-10-09 15:54:09.000000000 +0200 ++++ boost_1_48_0-patched/libs/filesystem/v3/src/operations.cpp 2012-06-17 00:04:37.000000000 +0200 +@@ -80,13 +80,15 @@ + const fs::path dot_path("."); + const fs::path dot_dot_path(".."); + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -212,7 +214,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST +diff -ruN boost_1_48_0-boot/tools/build/v2/tools/android.jam boost_1_48_0-patched/tools/build/v2/tools/android.jam +--- boost_1_48_0-boot/tools/build/v2/tools/android.jam 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_48_0-patched/tools/build/v2/tools/android.jam 2012-06-17 00:16:04.000000000 +0200 +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; +diff -ruN boost_1_48_0-boot/tools/build/v2/tools/android.py boost_1_48_0-patched/tools/build/v2/tools/android.py +--- boost_1_48_0-boot/tools/build/v2/tools/android.py 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_48_0-patched/tools/build/v2/tools/android.py 2012-06-17 00:15:47.000000000 +0200 +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_49_0/boost-1_49_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_49_0/boost-1_49_0.patch new file mode 100644 index 00000000..66e90c9c --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_49_0/boost-1_49_0.patch @@ -0,0 +1,2099 @@ +diff -ruN boost_1_49_0-boot/boost/asio/detail/fenced_block.hpp boost_1_49_0-patched/boost/asio/detail/fenced_block.hpp +--- boost_1_49_0-boot/boost/asio/detail/fenced_block.hpp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_49_0-patched/boost/asio/detail/fenced_block.hpp 2012-06-27 19:19:06.069571660 +0200 +@@ -25,7 +25,7 @@ + # include + #elif defined(__sun) + # include +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + # include + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + # include +@@ -34,7 +34,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + # include + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + # include +@@ -54,7 +55,7 @@ + typedef macos_fenced_block fenced_block; + #elif defined(__sun) + typedef solaris_fenced_block fenced_block; +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + typedef gcc_arm_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + typedef gcc_hppa_fenced_block fenced_block; +@@ -63,7 +64,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + typedef gcc_sync_fenced_block fenced_block; + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + typedef win_fenced_block fenced_block; +diff -ruN boost_1_49_0-boot/boost/asio/detail/socket_types.hpp boost_1_49_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_49_0-boot/boost/asio/detail/socket_types.hpp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_49_0-patched/boost/asio/detail/socket_types.hpp 2012-06-27 19:19:01.279562338 +0200 +@@ -123,7 +123,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_49_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_49_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_49_0-boot/boost/asio/ip/impl/address_v6.ipp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_49_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-27 19:19:11.029581297 +0200 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_49_0-boot/boost/config/user.hpp boost_1_49_0-patched/boost/config/user.hpp +--- boost_1_49_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100 ++++ boost_1_49_0-patched/boost/config/user.hpp 2012-06-27 19:18:46.129532736 +0200 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_49_0-boot/boost/detail/endian.hpp boost_1_49_0-patched/boost/detail/endian.hpp +--- boost_1_49_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200 ++++ boost_1_49_0-patched/boost/detail/endian.hpp 2012-06-27 19:18:39.359519453 +0200 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN +diff -ruN boost_1_49_0-boot/boost/interprocess/detail/workaround.hpp boost_1_49_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_49_0-boot/boost/interprocess/detail/workaround.hpp 2011-12-26 18:21:36.000000000 +0100 ++++ boost_1_49_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-27 19:18:52.909546004 +0200 +@@ -64,7 +64,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) + # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_49_0-boot/libs/filesystem/v2/src/v2_operations.cpp boost_1_49_0-patched/libs/filesystem/v2/src/v2_operations.cpp +--- boost_1_49_0-boot/libs/filesystem/v2/src/v2_operations.cpp 2012-01-15 20:22:27.000000000 +0100 ++++ boost_1_49_0-patched/libs/filesystem/v2/src/v2_operations.cpp 2012-06-27 19:19:15.239589462 +0200 +@@ -60,13 +60,15 @@ + + # else // BOOST_POSIX_API + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + #ifdef __OpenBSD__ + # include ++#elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + #endif + # include + # define BOOST_STATVFS statfs +@@ -1267,7 +1269,11 @@ + if ( max == 0 ) + { + errno = 0; ++# ifdef __ANDROID__ || ANDROID ++ long tmp = 4096; ++# else + long tmp = ::pathconf( "/", _PC_NAME_MAX ); ++# endif + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate +diff -ruN boost_1_49_0-boot/libs/filesystem/v3/src/operations.cpp boost_1_49_0-patched/libs/filesystem/v3/src/operations.cpp +--- boost_1_49_0-boot/libs/filesystem/v3/src/operations.cpp 2012-01-28 15:40:16.000000000 +0100 ++++ boost_1_49_0-patched/libs/filesystem/v3/src/operations.cpp 2012-06-27 19:19:19.269597266 +0200 +@@ -81,13 +81,15 @@ + const fs::path dot_path("."); + const fs::path dot_dot_path(".."); + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -214,7 +216,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST +--- boost_1_49_0_vanila/libs/filesystem/v3/src/path.cpp 2012-01-28 15:40:16.000000000 +0100 ++++ boost_1_49_0/libs/filesystem/v3/src/path.cpp 2013-04-19 05:11:40.020270272 +0200 +@@ -35,7 +35,7 @@ + #ifdef BOOST_WINDOWS_API + # include "windows_file_codecvt.hpp" + # include +-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ++#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__ANDROID__) + # include + #endif + +@@ -766,7 +766,7 @@ + codecvt_facet(&std::use_facet > + (path_locale)); + +-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ++#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__ANDROID__) + + // "All BSD system functions expect their string parameters to be in UTF-8 encoding + // and nothing else." See +@@ -822,7 +822,8 @@ + const path::codecvt_type*& path::wchar_t_codecvt_facet() + { + # if defined(BOOST_POSIX_API) && \ +- !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) ++ !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && \ ++ !(defined(__ANDROID__)) + // A local static initialized by calling path::imbue ensures that std::locale(""), + // which may throw, is called only if path_locale and condecvt_facet will actually + // be used. Thus misconfigured environmental variables will only cause an +diff -ruN boost_1_49_0-boot/tools/build/v2/tools/android.jam boost_1_49_0-patched/tools/build/v2/tools/android.jam +--- boost_1_49_0-boot/tools/build/v2/tools/android.jam 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_49_0-patched/tools/build/v2/tools/android.jam 2012-06-27 19:19:24.829608011 +0200 +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; +diff -ruN boost_1_49_0-boot/tools/build/v2/tools/android.py boost_1_49_0-patched/tools/build/v2/tools/android.py +--- boost_1_49_0-boot/tools/build/v2/tools/android.py 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_49_0-patched/tools/build/v2/tools/android.py 2012-06-27 19:19:30.359618678 +0200 +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_53_0/boost-1_53_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_53_0/boost-1_53_0.patch new file mode 100644 index 00000000..3eaca543 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_53_0/boost-1_53_0.patch @@ -0,0 +1,138 @@ +diff -ruN boost_1_54_0/libs/filesystem/src/path.cpp boost_1_54_0_patched/libs/filesystem/src/path.cpp +--- boost_1_54_0/libs/filesystem/src/path.cpp 2012-04-16 15:36:28.000000000 +0200 ++++ boost_1_54_0_patched/libs/filesystem/src/path.cpp 2013-10-28 02:55:32.773380890 +0100 +@@ -902,7 +902,7 @@ + + const path::codecvt_type& path::codecvt() + { +-# if defined(BOOST_POSIX_API) && \ ++# if defined(BOOST_POSIX_API) && !defined(__ANDROID__) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) + // A local static initialized by calling path::imbue ensures that std::locale(""), + // which may throw, is called only if path_locale and condecvt_facet will actually +diff -ruN boost_1_53_0-boot/boost/asio/detail/socket_types.hpp boost_1_53_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_53_0-boot/boost/asio/detail/socket_types.hpp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_53_0-patched/boost/asio/detail/socket_types.hpp 2012-06-27 19:19:01.279562338 +0200 +@@ -123,7 +123,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_53_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_53_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_53_0-boot/boost/asio/ip/impl/address_v6.ipp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_53_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-27 19:19:11.029581297 +0200 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_53_0-boot/boost/config/user.hpp boost_1_53_0-patched/boost/config/user.hpp +--- boost_1_53_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100 ++++ boost_1_53_0-patched/boost/config/user.hpp 2012-06-27 19:18:46.129532736 +0200 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_53_0-boot/boost/detail/endian.hpp boost_1_53_0-patched/boost/detail/endian.hpp +--- boost_1_53_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200 ++++ boost_1_53_0-patched/boost/detail/endian.hpp 2012-06-27 19:18:39.359519453 +0200 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) || defined(__ANDROID__) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN +diff -ruN boost_1_53_0-boot/boost/interprocess/detail/workaround.hpp boost_1_53_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_53_0-boot/boost/interprocess/detail/workaround.hpp 2011-12-26 18:21:36.000000000 +0100 ++++ boost_1_53_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-27 19:18:52.909546004 +0200 +@@ -54,7 +54,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) && !defined(__ANDROID__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_53_0-boot/libs/filesystem/src/operations.cpp boost_1_53_0-patched/libs/filesystem/src/operations.cpp +--- boost_1_53_0-boot/libs/filesystem/src/operations.cpp 2012-01-28 15:40:16.000000000 +0100 ++++ boost_1_53_0-patched/libs/filesystem/src/operations.cpp 2012-06-27 19:19:19.269597266 +0200 +@@ -73,13 +73,15 @@ + const fs::path dot_dot_path(".."); + # include + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -206,7 +208,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_54_0/boost-1_54_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_54_0/boost-1_54_0.patch new file mode 100644 index 00000000..63d66816 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_54_0/boost-1_54_0.patch @@ -0,0 +1,2008 @@ +diff -ruN boost_1_54_0/libs/filesystem/src/path.cpp boost_1_54_0_patched/libs/filesystem/src/path.cpp +--- boost_1_54_0/libs/filesystem/src/path.cpp 2012-04-16 15:36:28.000000000 +0200 ++++ boost_1_54_0_patched/libs/filesystem/src/path.cpp 2013-10-28 02:55:32.773380890 +0100 +@@ -902,7 +902,7 @@ + + const path::codecvt_type& path::codecvt() + { +-# if defined(BOOST_POSIX_API) && \ ++# if defined(BOOST_POSIX_API) && !defined(__ANDROID__) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) + // A local static initialized by calling path::imbue ensures that std::locale(""), + // which may throw, is called only if path_locale and condecvt_facet will actually +diff -ruN boost_1_54_0-boot/boost/asio/detail/socket_types.hpp boost_1_54_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_54_0-boot/boost/asio/detail/socket_types.hpp ++++ boost_1_54_0-patched/boost/asio/detail/socket_types.hpp +@@ -124,7 +124,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_54_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_54_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_54_0-boot/boost/asio/ip/impl/address_v6.ipp ++++ boost_1_54_0-patched/boost/asio/ip/impl/address_v6.ipp +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_54_0-boot/boost/config/user.hpp boost_1_54_0-patched/boost/config/user.hpp +--- boost_1_54_0-boot/boost/config/user.hpp ++++ boost_1_54_0-patched/boost/config/user.hpp +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_54_0-boot/boost/detail/endian.hpp boost_1_54_0-patched/boost/detail/endian.hpp +--- boost_1_54_0-boot/boost/detail/endian.hpp ++++ boost_1_54_0-patched/boost/detail/endian.hpp +@@ -31,7 +31,7 @@ + // + // Special cases come first: + // +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) || defined(__ANDROID__) + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + # include +diff -ruN boost_1_54_0-boot/boost/interprocess/detail/workaround.hpp boost_1_54_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_54_0-boot/boost/interprocess/detail/workaround.hpp ++++ boost_1_54_0-patched/boost/interprocess/detail/workaround.hpp +@@ -56,7 +56,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) && !defined(__ANDROID__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_54_0-boot/libs/filesystem/src/operations.cpp boost_1_54_0-patched/libs/filesystem/src/operations.cpp +--- boost_1_54_0-boot/libs/filesystem/src/operations.cpp ++++ boost_1_54_0-patched/libs/filesystem/src/operations.cpp +@@ -73,13 +73,15 @@ + const fs::path dot_dot_path(".."); + # include + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -206,7 +208,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST +diff -ruN boost_1_54_0-boot/tools/build/v2/tools/android.jam boost_1_54_0-patched/tools/build/v2/tools/android.jam +--- boost_1_54_0-boot/tools/build/v2/tools/android.jam ++++ boost_1_54_0-patched/tools/build/v2/tools/android.jam +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; +diff -ruN boost_1_54_0-boot/tools/build/v2/tools/android.py boost_1_54_0-patched/tools/build/v2/tools/android.py +--- boost_1_54_0-boot/tools/build/v2/tools/android.py ++++ boost_1_54_0-patched/tools/build/v2/tools/android.py +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_55_0/boost-1_55_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_55_0/boost-1_55_0.patch new file mode 100644 index 00000000..8d0ea7df --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android-x86/patches/boost-1_55_0/boost-1_55_0.patch @@ -0,0 +1,125 @@ +diff -u -r boost_1_55_0/boost/asio/detail/socket_types.hpp boost_1_55_0.patched/boost/asio/detail/socket_types.hpp +--- boost_1_55_0/boost/asio/detail/socket_types.hpp ++++ boost_1_55_0.patched/boost/asio/detail/socket_types.hpp +@@ -278,7 +278,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -u -r boost_1_55_0/boost/asio/ip/impl/address_v6.ipp boost_1_55_0.patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_55_0/boost/asio/ip/impl/address_v6.ipp ++++ boost_1_55_0.patched/boost/asio/ip/impl/address_v6.ipp +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -u -r boost_1_55_0/boost/config/user.hpp boost_1_55_0.patched/boost/config/user.hpp +--- boost_1_55_0/boost/config/user.hpp ++++ boost_1_55_0.patched/boost/config/user.hpp +@@ -13,6 +13,14 @@ + // configuration policy: + // + ++// Android defines ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -u -r boost_1_55_0/boost/interprocess/detail/workaround.hpp boost_1_55_0.patched/boost/interprocess/detail/workaround.hpp +--- boost_1_55_0/boost/interprocess/detail/workaround.hpp 2013-09-16 19:01:45.000000000 +0200 ++++ boost_1_55_0.patched/boost/interprocess/detail/workaround.hpp 2013-11-29 17:51:33.111025389 +0100 +@@ -73,7 +73,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) && !defined(__ANDROID__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -u -r boost_1_55_0/boost/predef/other/endian.h boost_1_55_0.patched/boost/predef/other/endian.h +--- boost_1_55_0/boost/predef/other/endian.h ++++ boost_1_55_0.patched/boost/predef/other/endian.h +@@ -53,7 +53,7 @@ + */ + #if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +-# if BOOST_LIB_C_GNU ++# if BOOST_LIB_C_GNU || defined(ANDROID) || defined(__ANDROID__) + # include + # else + # if BOOST_OS_MACOS +diff -u -r boost_1_55_0/libs/filesystem/src/operations.cpp boost_1_55_0.patched/libs/filesystem/src/operations.cpp +--- boost_1_55_0/libs/filesystem/src/operations.cpp ++++ boost_1_55_0.patched/libs/filesystem/src/operations.cpp +@@ -73,14 +73,14 @@ + const fs::path dot_dot_path(".."); + # include + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include +-# elif defined(__ANDROID__) ++# elif defined(__ANDROID__) || defined(ANDROID) + # include + # endif + # include +@@ -208,7 +208,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/.gitattributes b/External/cpprestsdk/Build_android/build/Boost-for-Android/.gitattributes new file mode 100644 index 00000000..9ba89d8c --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +*.sh eol=lf diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/.gitignore b/External/cpprestsdk/Build_android/build/Boost-for-Android/.gitignore new file mode 100644 index 00000000..65b62b5c --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/.gitignore @@ -0,0 +1,7 @@ +boost_* +build +*~ +logs +build.log +*.swp +*.vim diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/README.md b/External/cpprestsdk/Build_android/build/Boost-for-Android/README.md new file mode 100644 index 00000000..4c0954b1 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/README.md @@ -0,0 +1,96 @@ +# Boost for Android +Boost for android is a set of tools to compile the main part of the [Boost C++ Libraries](http://www.boost.org/) for the Android platform. + +Currently supported boost versions are 1.45.0, 1.48.0, 1.49.0 and 1.53.0. Boost 1.54.0 and 1.55.0 shall be considered experimental. + +To compile Boost for Android you may use one of the following NDKs: + +| NDK / boost | 1.45 | 1.48 | 1.49 | 1.53 | +| ----------- | ---- | ---- | ---- | ---- | +| r4 customized by [Dmitry Moskalchuk aka CrystaX](http://www.crystax.net/android/ndk.php). | x | | | | +| r5 from the [official android repository](http://developer.android.com). | x | | | | +| r5 customized by [CrystaX](http://www.crystax.net/android/ndk.php). | x | | | | +| r7 customized by [CrystaX](http://www.crystax.net/android/ndk.php). | x | x | x | | +| r8 from the [official android repository](http://developer.android.com). | x | x | x | | +| r8b from the [official android repository](http://developer.android.com). | | x | x | | +| r8c from the [official android repository](http://developer.android.com). | | | x | | +| r8d from the [official android repository](http://developer.android.com). | | | x | x | +| r8e from the [official android repository](http://developer.android.com). | | | x | x | +| r10 from the [official android repository](http://developer.android.com). | | | x | x | + +# Quick Start + +## Dependencies + + * NDK ([official](http://developer.android.com) or [customized by CrystaX](http://www.crystax.net/android/ndk.php)) + * GNU Make + +## Usage + +### Compiling + +Linux. +``` +./build-android.sh $(NDK_ROOT) +``` +Windows: +``` +build-android.bat $(NDK_ROOT) +``` +NOTE: Do not forget to replace backslash with slashes in $(NDK_ROOT). For example set $(NDK_ROOT) to D:/android-ndk-r8e instead of D:\android-ndk-r8e + +On windows you will need MSYS to be able to launch the corresponding bat files (http://www.mingw.org/wiki/MSYS). + +This command will download and build boost against the NDK specified and output the final headers and libs in the `build` folder. Make sure to provide an absolute path the the NDK folder! + +For more info about usage and available commands use `--help`. + +### Including + +Now that you got Boost compiled you must add it to your `Android.mk` file. Locate the `build` folder and copy the `include` and `lib` folders over to your project's `jni` folder. A recommended path inside your project is `/jni/boost/`. + +Add the following to your `Android.mk` (note that here we're using Boost 1.48 and have assumed that Boost resides inside `/jni/boost`): + + LOCAL_CFLAGS += -I$(LOCAL_PATH)/boost/include/boost-1_48 + LOCAL_LDLIBS += -L$(LOCAL_PATH)/boost/lib/ -lboost_system -lboost_... + + LOCAL_CPPFLAGS += -fexceptions + LOCAL_CPPFLAGS += -frtti + +Now use `ndk-build` to build and have fun with it! + +Note that you should build your project and Boost with the same version of NDK as the C++ STL inside NDK r4 and NDK r5 are not compatible in some subtle details. + +## Contribute + +The projects is split into two main branches, the master and devel. The master branch is where the current stable version lies and which should be used in most of the cases, the devel branch in turn is where development occurs. To contribute to the project make sure to use the devel branch which will make it easier to test changes and to merge incoming pull requests (PR). + +## Troubleshooting + +In case you encounter bunch of linker errors when building your app with boost, +this might help: + +### Building from a 64 bit machine (Linux) + +Make sure you have installed the 32 bit libraries. Those are required to be able +to use the NDK. + +To install them just use the following + + $ sudo apt-get install ia32-libs + +### NDK 7 (CrystaX) + +Add `-lgnustl_static` *AFTER* all boost libraries to the LOCAL_LDLIBS line in +Android.mk. Example: + + LOCAL_LDLIBS += lboost_system-gcc-md lboost_thread-gcc-md -lgnustl_static + +### NDK 8 (official) + +Do everything that is in the NDK 7 Crystax section, but also +add full path to the gnustl_static library to the link paths. Example: + + LOCAL_LDLIBS += lboost_system-gcc-md lboost_thread-gcc-md \ + -L$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi \ + -lgnustl_static diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.bat b/External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.bat new file mode 100644 index 00000000..08882433 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.bat @@ -0,0 +1,10 @@ +@Echo Off + +sh -c "echo MSYS found. Running ./build-android.sh" +If %ERRORLEVEL% EQU 0 GOTO MSYSOK +echo This script requires MSYS installed and path to its bin folder added to PATH variable +echo Read http://www.mingw.org/wiki/MSYS for more information +GOTO:EOF +:MSYSOK + +sh -c "./build-android.sh %*" diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.sh b/External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.sh new file mode 100644 index 00000000..b52e0373 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/build-android.sh @@ -0,0 +1,435 @@ +#!/bin/sh +# Copyright (C) 2010 Mystic Tree Games +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Moritz "Moss" Wundke (b.thax.dcg@gmail.com) +# +# +# +# Build boost for android completly. It will download boost 1.45.0 +# prepare the build system and finally build it for android + +# Add common build methods +. `dirname $0`/build-common.sh + +# ----------------------- +# Command line arguments +# ----------------------- + +BOOST_VER1=1 +BOOST_VER2=53 +BOOST_VER3=0 +register_option "--boost=" boost_version "Boost version to be used, one of {1.55.0, 1.54.0, 1.53.0, 1.49.0, 1.48.0, 1.45.0}, default is 1.53.0." +boost_version() +{ + if [ "$1" = "1.59.0" ]; then + BOOST_VER1=1 + BOOST_VER2=59 + BOOST_VER3=0 + elif [ "$1" = "1.55.0" ]; then + BOOST_VER1=1 + BOOST_VER2=55 + BOOST_VER3=0 + elif [ "$1" = "1.54.0" ]; then + BOOST_VER1=1 + BOOST_VER2=54 + BOOST_VER3=0 + elif [ "$1" = "1.53.0" ]; then + BOOST_VER1=1 + BOOST_VER2=53 + BOOST_VER3=0 + elif [ "$1" = "1.49.0" ]; then + BOOST_VER1=1 + BOOST_VER2=49 + BOOST_VER3=0 + elif [ "$1" = "1.48.0" ]; then + BOOST_VER1=1 + BOOST_VER2=48 + BOOST_VER3=0 + elif [ "$1" = "1.45.0" ]; then + BOOST_VER1=1 + BOOST_VER2=45 + BOOST_VER3=0 + else + echo "Unsupported boost version '$1'." + exit 1 + fi +} + +register_option "--toolchain=" select_toolchain "Select a toolchain. To see available execute ls -l ANDROID_NDK/toolchains." +select_toolchain () { + TOOLCHAIN=$1 +} + +CLEAN=no +register_option "--clean" do_clean "Delete all previously downloaded and built files, then exit." +do_clean () { CLEAN=yes; } + +DOWNLOAD=no +register_option "--download" do_download "Only download required files and clean up previus build. No build will be performed." + +do_download () +{ + DOWNLOAD=yes + # Clean previus stuff too! + CLEAN=yes +} + +#LIBRARIES=--with-libraries=date_time,filesystem,program_options,regex,signals,system,thread,iostreams +LIBRARIES= +register_option "--with-libraries=" do_with_libraries "Comma separated list of libraries to build." +do_with_libraries () { + for lib in $(echo $1 | tr ',' '\n') ; do LIBRARIES="--with-$lib ${LIBRARIES}"; done +} + +register_option "--without-libraries=" do_without_libraries "Comma separated list of libraries to exclude from the build." +do_without_libraries () { LIBRARIES="--without-libraries=$1"; } +do_without_libraries () { + for lib in $(echo $1 | tr ',' '\n') ; do LIBRARIES="--without-$lib ${LIBRARIES}"; done +} + +register_option "--prefix=" do_prefix "Prefix to be used when installing libraries and includes." +do_prefix () { + if [ -d $1 ]; then + PREFIX=$1; + fi +} + +PROGRAM_PARAMETERS="" +PROGRAM_DESCRIPTION=\ +" Boost For Android\n"\ +"Copyright (C) 2010 Mystic Tree Games\n"\ + +extract_parameters $@ + +echo "Building boost version: $BOOST_VER1.$BOOST_VER2.$BOOST_VER3" + +# ----------------------- +# Build constants +# ----------------------- + +BOOST_DOWNLOAD_LINK="http://downloads.sourceforge.net/project/boost/boost/$BOOST_VER1.$BOOST_VER2.$BOOST_VER3/boost_${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3}.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F${BOOST_VER1}.${BOOST_VER2}.${BOOST_VER3}%2F&ts=1291326673&use_mirror=garr" +BOOST_TAR="boost_${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3}.tar.bz2" +BOOST_DIR="boost_${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3}" +BUILD_DIR="./build/" + +# ----------------------- + +if [ $CLEAN = yes ] ; then + echo "Cleaning: $BUILD_DIR" + rm -f -r $PROGDIR/$BUILD_DIR + + echo "Cleaning: $BOOST_DIR" + rm -f -r $PROGDIR/$BOOST_DIR + + echo "Cleaning: $BOOST_TAR" + rm -f $PROGDIR/$BOOST_TAR + + echo "Cleaning: logs" + rm -f -r logs + rm -f build.log + + [ "$DOWNLOAD" = "yes" ] || exit 0 +fi + +# It is almost never desirable to have the boost-X_Y_Z directory from +# previous builds as this script doesn't check in which state it's +# been left (bootstrapped, patched, built, ...). Unless maybe during +# a debug, in which case it's easy for a developer to comment out +# this code. + +if [ -d "$PROGDIR/$BOOST_DIR" ]; then + echo "Cleaning: $BOOST_DIR" + rm -f -r $PROGDIR/$BOOST_DIR +fi + +if [ -d "$PROGDIR/$BUILD_DIR" ]; then + echo "Cleaning: $BUILD_DIR" + rm -f -r $PROGDIR/$BUILD_DIR +fi + + +AndroidNDKRoot=$PARAMETERS +if [ -z "$AndroidNDKRoot" ] ; then + if [ -n "${ANDROID_BUILD_TOP}" ]; then # building from Android sources + AndroidNDKRoot="${ANDROID_BUILD_TOP}/prebuilts/ndk/current" + export AndroidSourcesDetected=1 + elif [ -z "`which ndk-build`" ]; then + dump "ERROR: You need to provide a !" + exit 1 + else + AndroidNDKRoot=`which ndk-build` + AndroidNDKRoot=`dirname $AndroidNDKRoot` + fi + echo "Using AndroidNDKRoot = $AndroidNDKRoot" +else + # User passed the NDK root as a parameter. Make sure the directory + # exists and make it an absolute path. + if [ ! -f "$AndroidNDKRoot/ndk-build" ]; then + dump "ERROR: $AndroidNDKRoot is not a valid NDK root" + exit 1 + fi + AndroidNDKRoot=$(cd $AndroidNDKRoot; pwd -P) +fi +export AndroidNDKRoot + +# Check platform patch +case "$HOST_OS" in + linux) + PlatformOS=linux + ;; + darwin|freebsd) + PlatformOS=darwin + ;; + windows|cygwin) + PlatformOS=windows + ;; + *) # let's play safe here + PlatformOS=linux +esac + +NDK_RELEASE_FILE=$AndroidNDKRoot"/RELEASE.TXT" +if [ -f "${NDK_RELEASE_FILE}" ]; then + NDK_RN=`cat $NDK_RELEASE_FILE | sed 's/^r\(.*\)$/\1/g'` +elif [ -n "${AndroidSourcesDetected}" ]; then + if [ -f "${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" ]; then + NDK_RELEASE_FILE="${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" + NDK_RN=`grep "android-ndk-" "${NDK_RELEASE_FILE}" | head -1 | sed 's/^.*r\(.*\)$/\1/'` + elif [ -f "${ANDROID_BUILD_TOP}/ndk/docs/text/CHANGES.text" ]; then + NDK_RELEASE_FILE="${ANDROID_BUILD_TOP}/ndk/docs/text/CHANGES.text" + NDK_RN=`grep "android-ndk-" "${NDK_RELEASE_FILE}" | head -1 | sed 's/^.*r\(.*\)$/\1/'` + else + dump "ERROR: can not find ndk version" + exit 1 + fi +else + dump "ERROR: can not find ndk version" + exit 1 +fi + +echo "Detected Android NDK version $NDK_RN" + +case "$NDK_RN" in + 4*) + TOOLCHAIN=${TOOLCHAIN:-arm-eabi-4.4.0} + CXXPATH=$AndroidNDKRoot/build/prebuilt/$PlatformOS-x86/${TOOLCHAIN}/bin/arm-eabi-g++ + TOOLSET=gcc-androidR4 + ;; + 5*) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.4.3} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR5 + ;; + 7-crystax-5.beta3) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6.3} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR7crystax5beta3 + ;; + 8) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.4.3} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8 + ;; + 8b|8c|8d) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8b + ;; + 8e|9|9b|9c|9d) + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/$PlatformOS-x86/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8e + ;; + "8e (64-bit)") + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8e + ;; + "9 (64-bit)"|"9b (64-bit)"|"9c (64-bit)"|"9d (64-bit)") + TOOLCHAIN=${TOOLCHAIN:-arm-linux-androideabi-4.6} + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/arm-linux-androideabi-g++ + TOOLSET=gcc-androidR8e + ;; + "10 (64-bit)") + TOOLCHAIN=llvm-3.4 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e + ;; + "10e-rc4 (64-bit)") + TOOLCHAIN=llvm-3.6 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e + ;; + *) + echo "Undefined or not supported Android NDK version!" + exit 1 +esac + +if [ -n "${AndroidSourcesDetected}" ]; then # Overwrite CXXPATH if we are building from Android sources + CXXPATH="${ANDROID_TOOLCHAIN}/arm-linux-androideabi-g++" +fi + +echo Building with TOOLSET=$TOOLSET CXXPATH=$CXXPATH CXXFLAGS=$CXXFLAGS | tee $PROGDIR/build.log + +# Check if the ndk is valid or not +if [ ! -f $CXXPATH ] +then + echo "Cannot find C++ compiler at: $CXXPATH" + exit 1 +fi + +# ----------------------- +# Download required files +# ----------------------- + +# Downalod and unzip boost in a temporal folder and +if [ ! -f $BOOST_TAR ] +then + echo "Downloading boost ${BOOST_VER1}.${BOOST_VER2}.${BOOST_VER3} please wait..." + prepare_download + download_file $BOOST_DOWNLOAD_LINK $PROGDIR/$BOOST_TAR +fi + +if [ ! -f $PROGDIR/$BOOST_TAR ] +then + echo "Failed to download boost! Please download boost ${BOOST_VER1}.${BOOST_VER2}.${BOOST_VER3} manually\nand save it in this directory as $BOOST_TAR" + exit 1 +fi + +if [ ! -d $PROGDIR/$BOOST_DIR ] +then + echo "Unpacking boost" + if [ $OPTION_PROGRESS = "yes" ] ; then + pv $PROGDIR/$BOOST_TAR | tar xjf - -C $PROGDIR + else + tar xjf $PROGDIR/$BOOST_TAR + fi +fi + +if [ $DOWNLOAD = yes ] ; then + echo "All required files has been downloaded and unpacked!" + exit 0 +fi + +# --------- +# Bootstrap +# --------- +if [ ! -f ./$BOOST_DIR/bjam ] +then + # Make the initial bootstrap + echo "Performing boost bootstrap" + + cd $BOOST_DIR + case "$HOST_OS" in + windows) + cmd //c "bootstrap.bat" 2>&1 | tee -a $PROGDIR/build.log + ;; + *) # Linux and others + ./bootstrap.sh 2>&1 | tee -a $PROGDIR/build.log + esac + + + if [ $? != 0 ] ; then + dump "ERROR: Could not perform boostrap! See $TMPLOG for more info." + exit 1 + fi + cd $PROGDIR + + # ------------------------------------------------------------- + # Patching will be done only if we had a successfull bootstrap! + # ------------------------------------------------------------- + + # Apply patches to boost + BOOST_VER=${BOOST_VER1}_${BOOST_VER2}_${BOOST_VER3} + PATCH_BOOST_DIR=$PROGDIR/patches/boost-${BOOST_VER} + + cp configs/user-config-boost-${BOOST_VER}.jam $BOOST_DIR/tools/build/src/user-config.jam + + #for dir in $PATCH_BOOST_DIR; do + # if [ ! -d "$dir" ]; then + # echo "Could not find directory '$dir' while looking for patches" + # exit 1 + # fi + + #PATCHES=`(cd $dir && ls *.patch | sort) 2> /dev/null` + + #if [ -z "$PATCHES" ]; then + # echo "No patches found in directory '$dir'" + # exit 1 + #fi + + #for PATCH in $PATCHES; do + #PATCH=`echo $PATCH | sed -e s%^\./%%g` + #SRC_DIR=$PROGDIR/$BOOST_DIR + #PATCHDIR=`dirname $PATCH` + #PATCHNAME=`basename $PATCH` + #log "Applying $PATCHNAME into $SRC_DIR/$PATCHDIR" + #cd $SRC_DIR && patch -p1 < $dir/$PATCH && cd $PROGDIR + #if [ $? != 0 ] ; then + #dump "ERROR: Patch failure !! Please check your patches directory!" + #dump " Try to perform a clean build using --clean ." + #dump " Problem patch: $dir/$PATCHNAME" + #exit 1 + #fi + #done + #done +fi + +echo "# ---------------" +echo "# Build using NDK" +echo "# ---------------" + +# Build boost for android +echo "Building boost for android" +( + cd $BOOST_DIR + + echo "Adding pathname: `dirname $CXXPATH`" + # `AndroidBinariesPath` could be used by user-config-boost-*.jam + export AndroidBinariesPath=`dirname $CXXPATH` + export PATH=$AndroidBinariesPath:$PATH + export AndroidNDKRoot + export NO_BZIP2=1 + export ICONV_PATH="`pwd`/../../libiconv/armeabi-v7a" + + cxxflags="" + for flag in $CXXFLAGS; do cxxflags="$cxxflags cxxflags=$flag"; done + + { ./bjam -q \ + target-os=linux \ + toolset=$TOOLSET \ + $cxxflags \ + link=static \ + threading=multi \ + --layout=versioned \ + --prefix="./../$BUILD_DIR/" \ + boost.locale.posix=off \ + boost.locale.std=on \ + boost.locale.iconv=on \ + boost.locale.icu=off \ + $LIBRARIES \ + release debug install 2>&1 \ + || { dump "ERROR: Failed to build boost for android!" ; exit 1 ; } + } | tee -a $PROGDIR/build.log + + # PIPESTATUS variable is defined only in Bash, and we are using /bin/sh, which is not Bash on newer Debian/Ubuntu +) + +dump "Done!" + +if [ $PREFIX ]; then + echo "Prefix set, copying files to $PREFIX" + cp -r $PROGDIR/$BUILD_DIR/lib $PREFIX + cp -r $PROGDIR/$BUILD_DIR/include $PREFIX +fi diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/build-common.sh b/External/cpprestsdk/Build_android/build/Boost-for-Android/build-common.sh new file mode 100644 index 00000000..3275a9b5 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/build-common.sh @@ -0,0 +1,671 @@ +#!/bin/sh +# +# Copyright (C) 2010 Mystic Tree Games +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Moritz "Moss" Wundke (b.thax.dcg@gmail.com) +# +# +# +# Adapted common build methods from NDK-Common.sh and prebuilt-common.sh +# from the Android NDK +# + +# Current script name into PROGNAME +PROGNAME=`basename $0` +PROGDIR=`pwd` + +## Logging support +## +VERBOSE=${VERBOSE-yes} +VERBOSE2=${VERBOSE2-no} + +TMPLOG= + +# Setup a log file where all log() and log2() output will be sent +# +# $1: log file path (optional) +# +setup_log_file () +{ + if [ -n "$1" ] ; then + TMPLOG="$1" + else + mkdir -p $PROGDIR/logs/ + TMPLOG=$PROGDIR/logs/myst-log-$$.log + fi + rm -f $TMPLOG && touch $TMPLOG + echo "To follow build in another terminal, please use: tail -F $TMPLOG" +} + +dump () +{ + if [ -n "$TMPLOG" ] ; then + echo "$@" >> $TMPLOG + fi + echo "$@" +} + +log () +{ + if [ "$VERBOSE" = "yes" ] ; then + echo "$@" + else + if [ "$TMPLOG" ] ; then + echo "$@" >> $TMPLOG + fi + fi +} + +log2 () +{ + if [ "$VERBOSE2" = "yes" ] ; then + echo "$@" + else + if [ -n "$TMPLOG" ] ; then + echo "$@" >> $TMPLOG + fi + fi +} + +run () +{ + if [ "$VERBOSE" = "yes" ] ; then + echo "##### NEW COMMAND" + echo "$@" + $@ 2>&1 + else + if [ -n "$TMPLOG" ] ; then + echo "##### NEW COMMAND" >> $TMPLOG + echo "$@" >> $TMPLOG + $@ 2>&1 | tee -a $TMPLOG + else + $@ > /dev/null 2>&1 + fi + fi +} + +## Utilities +## + +# Generate a random temp directory +random_temp_directory () +{ + mktemp -d /tmp/myst-dir-XXXXXX +} + +# return the value of a given named variable +# $1: variable name +# +# example: +# FOO=BAR +# BAR=ZOO +# echo `var_value $FOO` +# will print 'ZOO' +# +var_value () +{ + # find a better way to do that ? + eval echo "$`echo $1`" +} + +# convert to uppercase +# assumes tr is installed on the platform ? +# +to_uppercase () +{ + echo $1 | tr "[:lower:]" "[:upper:]" +} + +## Normalize OS and CPU +## +HOST_ARCH=`uname -m` +case "$HOST_ARCH" in + i?86) HOST_ARCH=x86 + ;; + amd64) HOST_ARCH=x86_64 + ;; + powerpc) HOST_ARCH=ppc + ;; +esac + +log2 "HOST_ARCH=$HOST_ARCH" + +# at this point, the supported values for CPU are: +# x86 +# x86_64 +# ppc +# +# other values may be possible but haven't been tested +# +HOST_EXE="" +HOST_OS=`uname -s` +case "$HOST_OS" in + Darwin) + HOST_OS=darwin + ;; + Linux) + # note that building 32-bit binaries on x86_64 is handled later + HOST_OS=linux + ;; + FreeBsd) # note: this is not tested + HOST_OS=freebsd + ;; + CYGWIN*|*_NT-*) + HOST_OS=windows + HOST_EXE=.exe + if [ "x$OSTYPE" = xcygwin ] ; then + HOST_OS=cygwin + fi + ;; +esac + +log2 "HOST_OS=$HOST_OS" +log2 "HOST_EXE=$HOST_EXE" + +# at this point, the value of HOST_OS should be one of the following: +# linux +# darwin +# windows (MSys) +# cygwin +# +# Note that cygwin is treated as a special case because it behaves very differently +# for a few things. Other values may be possible but have not been tested +# + +# define HOST_TAG as a unique tag used to identify both the host OS and CPU +# supported values are: +# +# linux-x86 +# linux-x86_64 +# darwin-x86 +# darwin-ppc +# windows +# +# other values are possible but were not tested. +# +compute_host_tag () +{ + case "$HOST_OS" in + windows|cygwin) + HOST_TAG="windows" + ;; + *) HOST_TAG="${HOST_OS}-${HOST_ARCH}" + esac + log2 "HOST_TAG=$HOST_TAG" +} + +compute_host_tag + +# Compute the number of host CPU cores an HOST_NUM_CPUS +# +case "$HOST_OS" in + linux) + HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l` + ;; + darwin|freebsd) + HOST_NUM_CPUS=`sysctl -n hw.ncpu` + ;; + windows|cygwin) + HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS + ;; + *) # let's play safe here + HOST_NUM_CPUS=1 +esac + +log2 "HOST_NUM_CPUS=$HOST_NUM_CPUS" + +# If BUILD_NUM_CPUS is not already defined in your environment, +# define it as the double of HOST_NUM_CPUS. This is used to +# run Make commends in parralles, as in 'make -j$BUILD_NUM_CPUS' +# +if [ -z "$BUILD_NUM_CPUS" ] ; then + BUILD_NUM_CPUS=`expr $HOST_NUM_CPUS \* 2` +fi + +log2 "BUILD_NUM_CPUS=$BUILD_NUM_CPUS" + +# Various probes are going to need to run a small C program +TMPC=/tmp/myst-$$-test.c +TMPO=/tmp/myst-$$-test.o +TMPE=/tmp/myst-$$-test$EXE +TMPL=/tmp/myst-$$-test.log + +# cleanup temporary files +clean_temp () +{ + rm -f $TMPC $TMPO $TMPL $TMPE +} + +# cleanup temp files then exit with an error +clean_exit () +{ + clean_temp + exit 1 +} + +pattern_match () +{ + echo "$2" | grep -q -E -e "$1" +} + +# Let's check that we have a working md5sum here +check_md5sum () +{ + A_MD5=`echo "A" | md5sum | cut -d' ' -f1` + if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then + echo "Please install md5sum on this machine" + exit 2 + fi +} + +# Find if a given shell program is available. +# We need to take care of the fact that the 'which ' command +# may return either an empty string (Linux) or something like +# "no in ..." (Darwin). Also, we need to redirect stderr +# to /dev/null for Cygwin +# +# $1: variable name +# $2: program name +# +# Result: set $1 to the full path of the corresponding command +# or to the empty/undefined string if not available +# +find_program () +{ + local PROG + PROG=`which $2 2>/dev/null` + if [ -n "$PROG" ] ; then + if pattern_match '^no ' "$PROG"; then + PROG= + fi + fi + eval $1="$PROG" +} + +prepare_download () +{ + find_program CMD_WGET wget + find_program CMD_CURL curl + find_program CMD_SCRP scp +} + +# Download a file with either 'curl', 'wget' or 'scp' +# +# $1: source URL (e.g. http://foo.com, ssh://blah, /some/path) +# $2: target file +download_file () +{ + # Is this HTTP, HTTPS or FTP ? + if pattern_match "^(http|https|ftp):.*" "$1"; then + if [ -n "$CMD_WGET" ] ; then + run $CMD_WGET -O $2 $1 + elif [ -n "$CMD_CURL" ] ; then + run $CMD_CURL -o -L $2 $1 + else + echo "Please install wget or curl on this machine" + exit 1 + fi + return + fi + + # Is this SSH ? + # Accept both ssh:// or : + # + if pattern_match "^(ssh|[^:]+):.*" "$1"; then + if [ -n "$CMD_SCP" ] ; then + scp_src=`echo $1 | sed -e s%ssh://%%g` + run $CMD_SCP $scp_src $2 + else + echo "Please install scp on this machine" + exit 1 + fi + return + fi + + # Is this a file copy ? + # Accept both file:// or / + # + if pattern_match "^(file://|/).*" "$1"; then + cp_src=`echo $1 | sed -e s%^file://%%g` + run cp -f $cp_src $2 + return + fi +} + +# Return the maximum length of a series of strings +# +# Usage: len=`max_length ...` +# +max_length () +{ + echo "$@" | tr ' ' '\n' | awk 'BEGIN {max=0} {len=length($1); if (len > max) max=len} END {print max}' +} + +# Translate dashes to underscores +# Usage: str=`dashes_to_underscores ` +dashes_to_underscores () +{ + echo $@ | tr '-' '_' +} + +# Translate underscores to dashes +# Usage: str=`underscores_to_dashes ` +underscores_to_dashes () +{ + echo $@ | tr '_' '-' +} + +#----------------------------------------------------------------------- +# OPTION PROCESSING +#----------------------------------------------------------------------- + +# We recognize the following option formats: +# +# -f +# --flag +# +# -s +# --setting= +# + +# NOTE: We translate '-' into '_' when storing the options in global +# variables +# + +OPTIONS="" +OPTION_FLAGS="" +OPTION_SETTINGS="" + +# Set a given option attribute +# $1: option name +# $2: option attribute +# $3: attribute value +# +option_set_attr () +{ + eval OPTIONS_$1_$2=\"$3\" +} + +# Get a given option attribute +# $1: option name +# $2: option attribute +# +option_get_attr () +{ + echo `var_value OPTIONS_$1_$2` +} + +# Determine optional variable value +# $1: final variable name +# $2: option variable name +# $3: small description for the option +fix_option () +{ + if [ -n "$2" ] ; then + eval $1="$2" + log "Using specific $3: $2" + else + log "Using default $3: `var_value $1`" + fi +} + +# Register a new option +# $1: option +# $2: name of function that will be called when the option is parsed +# $3: small abstract for the option +# $4: optional. default value +# +register_option () +{ + local optname optvalue opttype optlabel + optlabel= + optname= + optvalue= + opttype= + while [ -n "1" ] ; do + # Check for something like --setting= + echo "$1" | grep -q -E -e '^--[^=]+=<.+>$' + if [ $? = 0 ] ; then + optlabel=`expr -- "$1" : '\(--[^=]*\)=.*'` + optvalue=`expr -- "$1" : '--[^=]*=\(<.*>\)'` + opttype="long_setting" + break + fi + + # Check for something like --flag + echo "$1" | grep -q -E -e '^--[^=]+$' + if [ $? = 0 ] ; then + optlabel="$1" + opttype="long_flag" + break + fi + + # Check for something like -f + echo "$1" | grep -q -E -e '^-[A-Za-z0-9]<.+>$' + if [ $? = 0 ] ; then + optlabel=`expr -- "$1" : '\(-.\).*'` + optvalue=`expr -- "$1" : '-.\(<.+>\)'` + opttype="short_setting" + break + fi + + # Check for something like -f + echo "$1" | grep -q -E -e '^-.$' + if [ $? = 0 ] ; then + optlabel="$1" + opttype="short_flag" + break + fi + + echo "ERROR: Invalid option format: $1" + echo " Check register_option call" + exit 1 + done + + log "new option: type='$opttype' name='$optlabel' value='$optvalue'" + + optname=`dashes_to_underscores $optlabel` + OPTIONS="$OPTIONS $optname" + OPTIONS_TEXT="$OPTIONS_TEXT $1" + option_set_attr $optname label "$optlabel" + option_set_attr $optname otype "$opttype" + option_set_attr $optname value "$optvalue" + option_set_attr $optname text "$1" + option_set_attr $optname funcname "$2" + option_set_attr $optname abstract "$3" + option_set_attr $optname default "$4" +} + +# Print the help, including a list of registered options for this program +# Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and +# correspond to the parameters list and the program description +# +print_help () +{ + local opt text abstract default + + echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS" + echo "" + if [ -n "$PROGRAM_DESCRIPTION" ] ; then + echo "$PROGRAM_DESCRIPTION" + echo "" + fi + echo "Valid options (defaults are in brackets):" + echo "" + + maxw=`max_length "$OPTIONS_TEXT"` + AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"` + for opt in $OPTIONS; do + text=`option_get_attr $opt text | awk "$AWK_SCRIPT"` + abstract=`option_get_attr $opt abstract` + default=`option_get_attr $opt default` + if [ -n "$default" ] ; then + echo " $text $abstract [$default]" + else + echo " $text $abstract" + fi + done + echo "" +} + +option_panic_no_args () +{ + echo "ERROR: Option '$1' does not take arguments. See --help for usage." + exit 1 +} + +option_panic_missing_arg () +{ + echo "ERROR: Option '$1' requires an argument. See --help for usage." + exit 1 +} + +extract_parameters () +{ + local opt optname otype value name fin funcname + PARAMETERS="" + while [ -n "$1" ] ; do + # If the parameter does not begin with a dash + # it is not an option. + param=`expr -- "$1" : '^\([^\-].*\)$'` + if [ -n "$param" ] ; then + if [ -z "$PARAMETERS" ] ; then + PARAMETERS="$1" + else + PARAMETERS="$PARAMETERS $1" + fi + shift + continue + fi + + while [ -n "1" ] ; do + # Try to match a long setting, i.e. --option=value + opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'` + if [ -n "$opt" ] ; then + otype="long_setting" + value=`expr -- "$1" : '^--[^=]*=\(.*\)$'` + break + fi + + # Try to match a long flag, i.e. --option + opt=`expr -- "$1" : '^\(--.*\)$'` + if [ -n "$opt" ] ; then + otype="long_flag" + value= + break + fi + + # Try to match a short setting, i.e. -o + opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'` + if [ -n "$opt" ] ; then + otype="short_setting" + value=`expr -- "$1" : '^-.\(.*\)$'` + break + fi + + # Try to match a short flag, i.e. -o + opt=`expr -- "$1" : '^\(-.\)$'` + if [ -n "$opt" ] ; then + otype="short_flag" + value= + break + fi + + echo "ERROR: Unknown option '$1'. Use --help for list of valid values." + exit 1 + done + + #echo "Found opt='$opt' otype='$otype' value='$value'" + + name=`dashes_to_underscores $opt` + found=0 + for xopt in $OPTIONS; do + if [ "$name" != "$xopt" ] ; then + continue + fi + # Check that the type is correct here + # + # This also allows us to handle -o as -o + # + xotype=`option_get_attr $name otype` + if [ "$otype" != "$xotype" ] ; then + case "$xotype" in + "short_flag") + option_panic_no_args $opt + ;; + "short_setting") + if [ -z "$2" ] ; then + option_panic_missing_arg $opt + fi + value="$2" + shift + ;; + "long_flag") + option_panic_no_args $opt + ;; + "long_setting") + option_panic_missing_arg $opt + ;; + esac + fi + found=1 + break + break + done + if [ "$found" = "0" ] ; then + echo "ERROR: Unknown option '$opt'. See --help for usage." + exit 1 + fi + # Launch option-specific function, value, if any as argument + eval `option_get_attr $name funcname` \"$value\" + shift + done + + # Change log out put if requested + if [ "x$OPTION_OUTPUT" != "x" ] ; then + setup_log_file $OPTION_OUTPUT + else + setup_log_file + fi +} + +do_option_help () +{ + print_help + exit 0 +} + +VERBOSE=no +VERBOSE2=no +do_option_verbose () +{ + if [ $VERBOSE = "yes" ] ; then + VERBOSE2=yes + else + VERBOSE=yes + fi +} + +OPTION_OUTPUT= +do_logpath () { OPTION_OUTPUT=$1; } + +do_progress_bar() +{ + OPTION_PROGRESS="yes" +} + +register_option "--help" do_option_help "Print this help." +register_option "--verbose" do_option_verbose "Enable verbose mode." +register_option "--output=" do_logpath "Specify specific log output path (only terminal output by default)" +register_option "--progress" do_progress_bar "Enable extraction progress bar" diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_45_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_45_0.jam new file mode 100644 index 00000000..1cc43a1f --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_45_0.jam @@ -0,0 +1,269 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference.html#bbv2.reference.init +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# ---------------------- +# Android configurations. +# ---------------------- + +# -------------------------------------------------------------------- + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using gcc : androidR4 +: +arm-eabi-c++ +: +arm-eabi-ar +-I$(AndroidNDKRoot)/build/platforms/android-8/arch-arm/usr/include +-fpic +-mthumb-interwork +-ffunction-sections +-funwind-tables +-fstack-protector +-fno-short-enums +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-DANDROID +-D__ANDROID__ +-Wa,--noexecstack +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR5 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-8/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +-I$(AndroidNDKRoot)/sources/wchar-support/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR7crystax5beta3 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include/4.6.3 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/4.6.3/include +-I$(AndroidNDKRoot)/sources/crystax/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-DBOOST_THREAD_LINUX +-DBOOST_HAS_PTHREADS +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +-DBOOST_HAS_GETTIMEOFDAY +; + +# -------------------------------------------------------------------- +using gcc : androidR8 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_48_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_48_0.jam new file mode 100644 index 00000000..6e5437d5 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_48_0.jam @@ -0,0 +1,231 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ---------------------- +# Android configuration. +# ---------------------- + +# -------------------------------------------------------------------- + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using gcc : androidR7crystax5beta3 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include/4.6.3 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/4.6.3/include +-I$(AndroidNDKRoot)/sources/crystax/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8b +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_49_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_49_0.jam new file mode 100644 index 00000000..4027f2c5 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_49_0.jam @@ -0,0 +1,273 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + +# ------------------ +# Android configurations. +# ------------------ +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using gcc : androidR7crystax5beta3 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include/4.6.3 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/4.6.3/include +-I$(AndroidNDKRoot)/sources/crystax/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8 +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +# Is same for 8b, 8c and 8d +using gcc : androidR8b +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8e +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_53_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_53_0.jam new file mode 100644 index 00000000..b9bf10df --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_53_0.jam @@ -0,0 +1,130 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; +local AndroidBinariesPath = [ os.environ AndroidBinariesPath ] ; + +# -------------------------------------------------------------------- +# Is same for 8b, 8c and 8d +using gcc : androidR8b +: +$(AndroidBinariesPath)/arm-linux-androideabi-g++ +: +$(AndroidBinariesPath)/arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8e +: +$(AndroidBinariesPath)/arm-linux-androideabi-g++ +: +$(AndroidBinariesPath)/arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_54_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_54_0.jam new file mode 100644 index 00000000..666d4c86 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_54_0.jam @@ -0,0 +1,186 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +# Is same for 8b, 8c and 8d +using gcc : androidR8b +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + +# -------------------------------------------------------------------- +using gcc : androidR8e +: +arm-linux-androideabi-g++ +: +arm-linux-androideabi-ar +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Wno-psabi +-march=armv5te +-mtune=xscale +-msoft-float +-mthumb +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-finline-limit=64 +-I$(AndroidNDKRoot)/platforms/android-9/arch-arm/usr/include +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +; + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_55_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_55_0.jam new file mode 100644 index 00000000..df597f69 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_55_0.jam @@ -0,0 +1,147 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using clang : androidR8e +: +$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/linux-x86_64/bin/clang++ +: +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64" +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-no-canonical-prefixes +--target=armv7-none-linux-androideabi +-march=armv7-a +-mfloat-abi=softfp +-mfpu=vfpv3-d16 +-mthumb +--sysroot="$(AndroidNDKRoot)/platforms/android-9/arch-arm" +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/include +--target=armv7-none-linux-androideabi +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-arm +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +-std=c++11 +; + + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_59_0.jam b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_59_0.jam new file mode 100644 index 00000000..df597f69 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/configs/user-config-boost-1_59_0.jam @@ -0,0 +1,147 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# +# ------------------ +# Android configurations. +# ------------------ + +import os ; +local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; + +# -------------------------------------------------------------------- +using clang : androidR8e +: +$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/linux-x86_64/bin/clang++ +: +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64" +-fexceptions +-frtti +-fpic +-ffunction-sections +-funwind-tables +-no-canonical-prefixes +--target=armv7-none-linux-androideabi +-march=armv7-a +-mfloat-abi=softfp +-mfpu=vfpv3-d16 +-mthumb +--sysroot="$(AndroidNDKRoot)/platforms/android-9/arch-arm" +-D__ARM_ARCH_5__ +-D__ARM_ARCH_5T__ +-D__ARM_ARCH_5E__ +-D__ARM_ARCH_5TE__ +-Os +-fomit-frame-pointer +-fno-strict-aliasing +-Wa,--noexecstack +-DANDROID +-D__ANDROID__ +-DNDEBUG +-O2 +-g +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/include +--target=armv7-none-linux-androideabi +--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-arm +# @Moss - Above are the 'oficial' android flags +arm +-fvisibility=hidden +-fvisibility-inlines-hidden +-fdata-sections +-D__arm__ +-D_REENTRANT +-D_GLIBCXX__PTHREADS +-std=c++11 +; + + + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/cpprestsdk.patched.stamp b/External/cpprestsdk/Build_android/build/Boost-for-Android/cpprestsdk.patched.stamp new file mode 100644 index 00000000..e69de29b diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/address_v6.ipp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/address_v6.ipp.patch new file mode 100644 index 00000000..034f4af1 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/address_v6.ipp.patch @@ -0,0 +1,26 @@ +--- boost_1_45_0-old/boost/asio/ip/impl/address_v6.ipp 2010-06-09 12:40:46.000000000 +0300 ++++ boost_1_45_0/boost/asio/ip/impl/address_v6.ipp 2011-06-06 15:29:57.777421112 +0300 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.jam.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.jam.patch new file mode 100644 index 00000000..f16acf65 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.jam.patch @@ -0,0 +1,1067 @@ +--- boost_1_45_0-old/tools/build/v2/tools/android.jam 1970-01-01 03:00:00.000000000 +0300 ++++ boost_1_45_0/tools/build/v2/tools/android.jam 2011-06-06 15:29:57.787421112 +0300 +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.py.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.py.patch new file mode 100644 index 00000000..df332750 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/android.py.patch @@ -0,0 +1,801 @@ +--- boost_1_45_0-old/tools/build/v2/tools/android.py 1970-01-01 03:00:00.000000000 +0300 ++++ boost_1_45_0/tools/build/v2/tools/android.py 2011-06-06 15:29:57.787421112 +0300 +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/endian.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/endian.hpp.patch new file mode 100644 index 00000000..0d4d2ed0 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/endian.hpp.patch @@ -0,0 +1,12 @@ +diff -u -r boost_1_45_0-old/boost/detail/endian.hpp boost_1_45_0/boost/detail/endian.hpp +--- boost_1_45_0-old/boost/detail/endian.hpp 2010-11-17 11:51:56.000000000 +0200 ++++ boost_1_45_0/boost/detail/endian.hpp 2011-07-28 13:51:36.988916179 +0300 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/fenced_block.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/fenced_block.hpp.patch new file mode 100644 index 00000000..697816b4 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/fenced_block.hpp.patch @@ -0,0 +1,38 @@ +--- boost_1_45_0-old/boost/asio/detail/fenced_block.hpp 2010-07-12 02:42:34.000000000 +0300 ++++ boost_1_45_0/boost/asio/detail/fenced_block.hpp 2011-06-06 15:29:57.777421112 +0300 +@@ -25,14 +25,15 @@ + # include + #elif defined(__sun) + # include +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + # include + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + # include + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + # include + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + # include +@@ -54,14 +55,15 @@ + typedef macos_fenced_block fenced_block; + #elif defined(__sun) + typedef solaris_fenced_block fenced_block; +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + typedef gcc_arm_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + typedef gcc_hppa_fenced_block fenced_block; + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + typedef gcc_sync_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + typedef gcc_x86_fenced_block fenced_block; diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/operations.cpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/operations.cpp.patch new file mode 100644 index 00000000..d34f79ea --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/operations.cpp.patch @@ -0,0 +1,39 @@ +--- boost_1_45_0-old/libs/filesystem/v3/src/operations.cpp 2010-10-16 16:09:25.000000000 +0300 ++++ boost_1_45_0/libs/filesystem/v3/src/operations.cpp 2011-06-06 15:29:57.787421112 +0300 +@@ -66,13 +66,15 @@ + # ifdef BOOST_POSIX_API + + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -201,7 +203,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/socket_types.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/socket_types.hpp.patch new file mode 100644 index 00000000..a11a4a0d --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/socket_types.hpp.patch @@ -0,0 +1,15 @@ +--- boost_1_45_0-old/boost/asio/detail/socket_types.hpp 2010-10-17 15:24:50.000000000 +0300 ++++ boost_1_45_0/boost/asio/detail/socket_types.hpp 2011-06-06 15:29:57.777421112 +0300 +@@ -122,7 +122,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/user.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/user.hpp.patch new file mode 100644 index 00000000..c1e47b3b --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/user.hpp.patch @@ -0,0 +1,18 @@ +--- boost_1_45_0-old/boost/config/user.hpp 2004-01-10 14:10:00.000000000 +0200 ++++ boost_1_45_0/boost/config/user.hpp 2011-06-06 15:29:57.797421112 +0300 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/v2_operations.cpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/v2_operations.cpp.patch new file mode 100644 index 00000000..03c9ebce --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/v2_operations.cpp.patch @@ -0,0 +1,31 @@ +--- boost_1_45_0-old/libs/filesystem/v2/src/v2_operations.cpp 2010-08-10 23:00:09.000000000 +0300 ++++ boost_1_45_0/libs/filesystem/v2/src/v2_operations.cpp 2011-06-06 15:29:57.777421112 +0300 +@@ -58,13 +58,15 @@ + + # else // BOOST_POSIX_API + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + #ifdef __OpenBSD__ + # include ++#elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + #endif + # include + # define BOOST_STATVFS statfs +@@ -1262,7 +1264,11 @@ + if ( max == 0 ) + { + errno = 0; ++# ifdef __ANDROID__ || ANDROID ++ long tmp = 4096; ++# else + long tmp = ::pathconf( "/", _PC_NAME_MAX ); ++# endif + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/workaround.hpp.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/workaround.hpp.patch new file mode 100644 index 00000000..7c25a2fe --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_45_0/workaround.hpp.patch @@ -0,0 +1,11 @@ +--- boost_1_45_0-old/boost/interprocess/detail/workaround.hpp 2010-10-12 21:18:42.000000000 +0300 ++++ boost_1_45_0/boost/interprocess/detail/workaround.hpp 2011-06-06 15:29:57.797421112 +0300 +@@ -64,7 +64,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) + # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_48_0/boost-1_48_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_48_0/boost-1_48_0.patch new file mode 100644 index 00000000..ec057ce9 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_48_0/boost-1_48_0.patch @@ -0,0 +1,2069 @@ +diff -ruN boost_1_48_0-boot/boost/asio/detail/fenced_block.hpp boost_1_48_0-patched/boost/asio/detail/fenced_block.hpp +--- boost_1_48_0-boot/boost/asio/detail/fenced_block.hpp 2011-10-09 23:59:57.000000000 +0200 ++++ boost_1_48_0-patched/boost/asio/detail/fenced_block.hpp 2012-06-16 23:59:57.000000000 +0200 +@@ -25,7 +25,7 @@ + # include + #elif defined(__sun) + # include +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + # include + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + # include +@@ -34,7 +34,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + # include + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + # include +@@ -54,7 +55,7 @@ + typedef macos_fenced_block fenced_block; + #elif defined(__sun) + typedef solaris_fenced_block fenced_block; +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + typedef gcc_arm_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + typedef gcc_hppa_fenced_block fenced_block; +@@ -63,7 +64,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + typedef gcc_sync_fenced_block fenced_block; + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + typedef win_fenced_block fenced_block; +diff -ruN boost_1_48_0-boot/boost/asio/detail/socket_types.hpp boost_1_48_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_48_0-boot/boost/asio/detail/socket_types.hpp 2011-06-06 01:21:43.000000000 +0200 ++++ boost_1_48_0-patched/boost/asio/detail/socket_types.hpp 2012-06-16 23:55:05.000000000 +0200 +@@ -123,7 +123,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_48_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_48_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_48_0-boot/boost/asio/ip/impl/address_v6.ipp 2011-06-06 01:21:43.000000000 +0200 ++++ boost_1_48_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-16 23:53:27.000000000 +0200 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_48_0-boot/boost/config/user.hpp boost_1_48_0-patched/boost/config/user.hpp +--- boost_1_48_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100 ++++ boost_1_48_0-patched/boost/config/user.hpp 2012-06-16 23:58:53.000000000 +0200 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_48_0-boot/boost/detail/endian.hpp boost_1_48_0-patched/boost/detail/endian.hpp +--- boost_1_48_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200 ++++ boost_1_48_0-patched/boost/detail/endian.hpp 2012-06-16 23:57:19.000000000 +0200 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN +diff -ruN boost_1_48_0-boot/boost/interprocess/detail/workaround.hpp boost_1_48_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_48_0-boot/boost/interprocess/detail/workaround.hpp 2011-08-30 17:46:15.000000000 +0200 ++++ boost_1_48_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-17 00:05:30.000000000 +0200 +@@ -64,7 +64,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) + # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_48_0-boot/libs/filesystem/v2/src/v2_operations.cpp boost_1_48_0-patched/libs/filesystem/v2/src/v2_operations.cpp +--- boost_1_48_0-boot/libs/filesystem/v2/src/v2_operations.cpp 2011-07-29 21:51:24.000000000 +0200 ++++ boost_1_48_0-patched/libs/filesystem/v2/src/v2_operations.cpp 2012-06-17 00:02:25.000000000 +0200 +@@ -58,13 +58,15 @@ + + # else // BOOST_POSIX_API + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + #ifdef __OpenBSD__ + # include ++#elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + #endif + # include + # define BOOST_STATVFS statfs +@@ -1265,7 +1267,11 @@ + if ( max == 0 ) + { + errno = 0; ++# ifdef __ANDROID__ || ANDROID ++ long tmp = 4096; ++# else + long tmp = ::pathconf( "/", _PC_NAME_MAX ); ++# endif + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate +diff -ruN boost_1_48_0-boot/libs/filesystem/v3/src/operations.cpp boost_1_48_0-patched/libs/filesystem/v3/src/operations.cpp +--- boost_1_48_0-boot/libs/filesystem/v3/src/operations.cpp 2011-10-09 15:54:09.000000000 +0200 ++++ boost_1_48_0-patched/libs/filesystem/v3/src/operations.cpp 2012-06-17 00:04:37.000000000 +0200 +@@ -80,13 +80,15 @@ + const fs::path dot_path("."); + const fs::path dot_dot_path(".."); + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -212,7 +214,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST +diff -ruN boost_1_48_0-boot/tools/build/v2/tools/android.jam boost_1_48_0-patched/tools/build/v2/tools/android.jam +--- boost_1_48_0-boot/tools/build/v2/tools/android.jam 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_48_0-patched/tools/build/v2/tools/android.jam 2012-06-17 00:16:04.000000000 +0200 +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; +diff -ruN boost_1_48_0-boot/tools/build/v2/tools/android.py boost_1_48_0-patched/tools/build/v2/tools/android.py +--- boost_1_48_0-boot/tools/build/v2/tools/android.py 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_48_0-patched/tools/build/v2/tools/android.py 2012-06-17 00:15:47.000000000 +0200 +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_49_0/boost-1_49_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_49_0/boost-1_49_0.patch new file mode 100644 index 00000000..66e90c9c --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_49_0/boost-1_49_0.patch @@ -0,0 +1,2099 @@ +diff -ruN boost_1_49_0-boot/boost/asio/detail/fenced_block.hpp boost_1_49_0-patched/boost/asio/detail/fenced_block.hpp +--- boost_1_49_0-boot/boost/asio/detail/fenced_block.hpp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_49_0-patched/boost/asio/detail/fenced_block.hpp 2012-06-27 19:19:06.069571660 +0200 +@@ -25,7 +25,7 @@ + # include + #elif defined(__sun) + # include +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + # include + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + # include +@@ -34,7 +34,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + # include + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + # include +@@ -54,7 +55,7 @@ + typedef macos_fenced_block fenced_block; + #elif defined(__sun) + typedef solaris_fenced_block fenced_block; +-#elif defined(__GNUC__) && defined(__arm__) ++#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) + typedef gcc_arm_fenced_block fenced_block; + #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + typedef gcc_hppa_fenced_block fenced_block; +@@ -63,7 +64,8 @@ + #elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +- && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) ++ && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \ ++ && !defined(ANDROID) && !defined(__ANDROID__) + typedef gcc_sync_fenced_block fenced_block; + #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) + typedef win_fenced_block fenced_block; +diff -ruN boost_1_49_0-boot/boost/asio/detail/socket_types.hpp boost_1_49_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_49_0-boot/boost/asio/detail/socket_types.hpp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_49_0-patched/boost/asio/detail/socket_types.hpp 2012-06-27 19:19:01.279562338 +0200 +@@ -123,7 +123,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_49_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_49_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_49_0-boot/boost/asio/ip/impl/address_v6.ipp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_49_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-27 19:19:11.029581297 +0200 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_49_0-boot/boost/config/user.hpp boost_1_49_0-patched/boost/config/user.hpp +--- boost_1_49_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100 ++++ boost_1_49_0-patched/boost/config/user.hpp 2012-06-27 19:18:46.129532736 +0200 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_49_0-boot/boost/detail/endian.hpp boost_1_49_0-patched/boost/detail/endian.hpp +--- boost_1_49_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200 ++++ boost_1_49_0-patched/boost/detail/endian.hpp 2012-06-27 19:18:39.359519453 +0200 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN +diff -ruN boost_1_49_0-boot/boost/interprocess/detail/workaround.hpp boost_1_49_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_49_0-boot/boost/interprocess/detail/workaround.hpp 2011-12-26 18:21:36.000000000 +0100 ++++ boost_1_49_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-27 19:18:52.909546004 +0200 +@@ -64,7 +64,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) + # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_49_0-boot/libs/filesystem/v2/src/v2_operations.cpp boost_1_49_0-patched/libs/filesystem/v2/src/v2_operations.cpp +--- boost_1_49_0-boot/libs/filesystem/v2/src/v2_operations.cpp 2012-01-15 20:22:27.000000000 +0100 ++++ boost_1_49_0-patched/libs/filesystem/v2/src/v2_operations.cpp 2012-06-27 19:19:15.239589462 +0200 +@@ -60,13 +60,15 @@ + + # else // BOOST_POSIX_API + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + #ifdef __OpenBSD__ + # include ++#elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + #endif + # include + # define BOOST_STATVFS statfs +@@ -1267,7 +1269,11 @@ + if ( max == 0 ) + { + errno = 0; ++# ifdef __ANDROID__ || ANDROID ++ long tmp = 4096; ++# else + long tmp = ::pathconf( "/", _PC_NAME_MAX ); ++# endif + if ( tmp < 0 ) + { + if ( errno == 0 ) // indeterminate +diff -ruN boost_1_49_0-boot/libs/filesystem/v3/src/operations.cpp boost_1_49_0-patched/libs/filesystem/v3/src/operations.cpp +--- boost_1_49_0-boot/libs/filesystem/v3/src/operations.cpp 2012-01-28 15:40:16.000000000 +0100 ++++ boost_1_49_0-patched/libs/filesystem/v3/src/operations.cpp 2012-06-27 19:19:19.269597266 +0200 +@@ -81,13 +81,15 @@ + const fs::path dot_path("."); + const fs::path dot_dot_path(".."); + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -214,7 +216,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST +--- boost_1_49_0_vanila/libs/filesystem/v3/src/path.cpp 2012-01-28 15:40:16.000000000 +0100 ++++ boost_1_49_0/libs/filesystem/v3/src/path.cpp 2013-04-19 05:11:40.020270272 +0200 +@@ -35,7 +35,7 @@ + #ifdef BOOST_WINDOWS_API + # include "windows_file_codecvt.hpp" + # include +-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ++#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__ANDROID__) + # include + #endif + +@@ -766,7 +766,7 @@ + codecvt_facet(&std::use_facet > + (path_locale)); + +-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ++#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__ANDROID__) + + // "All BSD system functions expect their string parameters to be in UTF-8 encoding + // and nothing else." See +@@ -822,7 +822,8 @@ + const path::codecvt_type*& path::wchar_t_codecvt_facet() + { + # if defined(BOOST_POSIX_API) && \ +- !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) ++ !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && \ ++ !(defined(__ANDROID__)) + // A local static initialized by calling path::imbue ensures that std::locale(""), + // which may throw, is called only if path_locale and condecvt_facet will actually + // be used. Thus misconfigured environmental variables will only cause an +diff -ruN boost_1_49_0-boot/tools/build/v2/tools/android.jam boost_1_49_0-patched/tools/build/v2/tools/android.jam +--- boost_1_49_0-boot/tools/build/v2/tools/android.jam 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_49_0-patched/tools/build/v2/tools/android.jam 2012-06-27 19:19:24.829608011 +0200 +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; +diff -ruN boost_1_49_0-boot/tools/build/v2/tools/android.py boost_1_49_0-patched/tools/build/v2/tools/android.py +--- boost_1_49_0-boot/tools/build/v2/tools/android.py 1970-01-01 01:00:00.000000000 +0100 ++++ boost_1_49_0-patched/tools/build/v2/tools/android.py 2012-06-27 19:19:30.359618678 +0200 +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_53_0/boost-1_53_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_53_0/boost-1_53_0.patch new file mode 100644 index 00000000..3eaca543 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_53_0/boost-1_53_0.patch @@ -0,0 +1,138 @@ +diff -ruN boost_1_54_0/libs/filesystem/src/path.cpp boost_1_54_0_patched/libs/filesystem/src/path.cpp +--- boost_1_54_0/libs/filesystem/src/path.cpp 2012-04-16 15:36:28.000000000 +0200 ++++ boost_1_54_0_patched/libs/filesystem/src/path.cpp 2013-10-28 02:55:32.773380890 +0100 +@@ -902,7 +902,7 @@ + + const path::codecvt_type& path::codecvt() + { +-# if defined(BOOST_POSIX_API) && \ ++# if defined(BOOST_POSIX_API) && !defined(__ANDROID__) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) + // A local static initialized by calling path::imbue ensures that std::locale(""), + // which may throw, is called only if path_locale and condecvt_facet will actually +diff -ruN boost_1_53_0-boot/boost/asio/detail/socket_types.hpp boost_1_53_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_53_0-boot/boost/asio/detail/socket_types.hpp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_53_0-patched/boost/asio/detail/socket_types.hpp 2012-06-27 19:19:01.279562338 +0200 +@@ -123,7 +123,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_53_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_53_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_53_0-boot/boost/asio/ip/impl/address_v6.ipp 2012-01-15 14:46:25.000000000 +0100 ++++ boost_1_53_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-27 19:19:11.029581297 +0200 +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_53_0-boot/boost/config/user.hpp boost_1_53_0-patched/boost/config/user.hpp +--- boost_1_53_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100 ++++ boost_1_53_0-patched/boost/config/user.hpp 2012-06-27 19:18:46.129532736 +0200 +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_53_0-boot/boost/detail/endian.hpp boost_1_53_0-patched/boost/detail/endian.hpp +--- boost_1_53_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200 ++++ boost_1_53_0-patched/boost/detail/endian.hpp 2012-06-27 19:18:39.359519453 +0200 +@@ -31,7 +31,7 @@ + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) || defined(__ANDROID__) + # include + # if (__BYTE_ORDER == __LITTLE_ENDIAN) + # define BOOST_LITTLE_ENDIAN +diff -ruN boost_1_53_0-boot/boost/interprocess/detail/workaround.hpp boost_1_53_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_53_0-boot/boost/interprocess/detail/workaround.hpp 2011-12-26 18:21:36.000000000 +0100 ++++ boost_1_53_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-27 19:18:52.909546004 +0200 +@@ -54,7 +54,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) && !defined(__ANDROID__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_53_0-boot/libs/filesystem/src/operations.cpp boost_1_53_0-patched/libs/filesystem/src/operations.cpp +--- boost_1_53_0-boot/libs/filesystem/src/operations.cpp 2012-01-28 15:40:16.000000000 +0100 ++++ boost_1_53_0-patched/libs/filesystem/src/operations.cpp 2012-06-27 19:19:19.269597266 +0200 +@@ -73,13 +73,15 @@ + const fs::path dot_dot_path(".."); + # include + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -206,7 +208,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_54_0/boost-1_54_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_54_0/boost-1_54_0.patch new file mode 100644 index 00000000..63d66816 --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_54_0/boost-1_54_0.patch @@ -0,0 +1,2008 @@ +diff -ruN boost_1_54_0/libs/filesystem/src/path.cpp boost_1_54_0_patched/libs/filesystem/src/path.cpp +--- boost_1_54_0/libs/filesystem/src/path.cpp 2012-04-16 15:36:28.000000000 +0200 ++++ boost_1_54_0_patched/libs/filesystem/src/path.cpp 2013-10-28 02:55:32.773380890 +0100 +@@ -902,7 +902,7 @@ + + const path::codecvt_type& path::codecvt() + { +-# if defined(BOOST_POSIX_API) && \ ++# if defined(BOOST_POSIX_API) && !defined(__ANDROID__) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) + // A local static initialized by calling path::imbue ensures that std::locale(""), + // which may throw, is called only if path_locale and condecvt_facet will actually +diff -ruN boost_1_54_0-boot/boost/asio/detail/socket_types.hpp boost_1_54_0-patched/boost/asio/detail/socket_types.hpp +--- boost_1_54_0-boot/boost/asio/detail/socket_types.hpp ++++ boost_1_54_0-patched/boost/asio/detail/socket_types.hpp +@@ -124,7 +124,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -ruN boost_1_54_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_54_0-patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_54_0-boot/boost/asio/ip/impl/address_v6.ipp ++++ boost_1_54_0-patched/boost/asio/ip/impl/address_v6.ipp +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -ruN boost_1_54_0-boot/boost/config/user.hpp boost_1_54_0-patched/boost/config/user.hpp +--- boost_1_54_0-boot/boost/config/user.hpp ++++ boost_1_54_0-patched/boost/config/user.hpp +@@ -13,6 +13,15 @@ + // configuration policy: + // + ++// Android defines ++#define __arm__ 1 ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -ruN boost_1_54_0-boot/boost/detail/endian.hpp boost_1_54_0-patched/boost/detail/endian.hpp +--- boost_1_54_0-boot/boost/detail/endian.hpp ++++ boost_1_54_0-patched/boost/detail/endian.hpp +@@ -31,7 +31,7 @@ + // + // Special cases come first: + // +-#if defined (__GLIBC__) ++#if defined (__GLIBC__) || defined(ANDROID) || defined(__ANDROID__) + // GNU libc offers the helpful header which defines + // __BYTE_ORDER + # include +diff -ruN boost_1_54_0-boot/boost/interprocess/detail/workaround.hpp boost_1_54_0-patched/boost/interprocess/detail/workaround.hpp +--- boost_1_54_0-boot/boost/interprocess/detail/workaround.hpp ++++ boost_1_54_0-patched/boost/interprocess/detail/workaround.hpp +@@ -56,7 +56,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) && !defined(__ANDROID__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -ruN boost_1_54_0-boot/libs/filesystem/src/operations.cpp boost_1_54_0-patched/libs/filesystem/src/operations.cpp +--- boost_1_54_0-boot/libs/filesystem/src/operations.cpp ++++ boost_1_54_0-patched/libs/filesystem/src/operations.cpp +@@ -73,13 +73,15 @@ + const fs::path dot_dot_path(".."); + # include + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include ++# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D ++# include + # endif + # include + # define BOOST_STATVFS statfs +@@ -206,7 +208,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST +diff -ruN boost_1_54_0-boot/tools/build/v2/tools/android.jam boost_1_54_0-patched/tools/build/v2/tools/android.jam +--- boost_1_54_0-boot/tools/build/v2/tools/android.jam ++++ boost_1_54_0-patched/tools/build/v2/tools/android.jam +@@ -0,0 +1,1064 @@ ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import "class" : new ; ++import common ; ++import errors ; ++import feature ; ++import generators ; ++import os ; ++import pch ; ++import property ; ++import property-set ; ++import toolset ; ++import type ; ++import rc ; ++import regex ; ++import set ; ++import unix ; ++import fortran ; ++ ++ ++if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ++{ ++ .debug-configuration = true ; ++} ++ ++ ++feature.extend toolset : android ; ++# feature.subfeature toolset android : flavor : : optional ; ++ ++toolset.inherit-generators android : unix : unix.link unix.link.dll ; ++toolset.inherit-flags android : unix ; ++toolset.inherit-rules android : unix ; ++ ++generators.override android.prebuilt : builtin.prebuilt ; ++generators.override android.searched-lib-generator : searched-lib-generator ; ++ ++# Make android toolset object files use the "o" suffix on all platforms. ++type.set-generated-target-suffix OBJ : android : o ; ++type.set-generated-target-suffix OBJ : android windows : o ; ++type.set-generated-target-suffix OBJ : android cygwin : o ; ++ ++# Initializes the android toolset for the given version. If necessary, command may ++# be used to specify where the compiler is located. The parameter 'options' is a ++# space-delimited list of options, each one specified as ++# option-value. Valid option names are: cxxflags, linkflags and ++# linker-type. Accepted linker-type values are aix, darwin, gnu, hpux, osf or ++# sun and the default value will be selected based on the current OS. ++# Example: ++# using android : 3.4 : : foo bar sun ; ++# ++rule init ( version ? : command * : options * ) ++{ ++ # Information about the android command... ++ # The command. ++ local command = [ common.get-invocation-command android : g++ : $(command) ] ; ++ # The root directory of the tool install. ++ local root = [ feature.get-values : $(options) ] ; ++ # The bin directory where to find the command to execute. ++ local bin ; ++ # The flavor of compiler. ++ local flavor = [ feature.get-values : $(options) ] ; ++ # Autodetect the root and bin dir if not given. ++ if $(command) ++ { ++ bin ?= [ common.get-absolute-tool-path $(command[-1]) ] ; ++ root ?= $(bin:D) ; ++ } ++ # The 'command' variable can have multiple elements. When calling ++ # the SHELL builtin we need a single string. ++ local command-string = $(command:J=" ") ; ++ # Autodetect the version and flavor if not given. ++ if $(command) ++ { ++ local machine = [ MATCH "^([^ ]+)" ++ : [ SHELL "$(command-string) -dumpmachine" ] ] ; ++ version ?= [ MATCH "^([0-9.]+)" ++ : [ SHELL "$(command-string) -dumpversion" ] ] ; ++ switch $(machine:L) ++ { ++ case *mingw* : flavor ?= mingw ; ++ } ++ } ++ ++ local condition ; ++ if $(flavor) ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ : flavor $(flavor) ++ ] ; ++ } ++ else ++ { ++ condition = [ common.check-init-parameters android ++ : version $(version) ++ ] ; ++ condition = $(condition) ; #/ ; ++ } ++ ++ common.handle-options android : $(condition) : $(command) : $(options) ; ++ ++ local linker = [ feature.get-values : $(options) ] ; ++ # The logic below should actually be keyed on ++ if ! $(linker) ++ { ++ if [ os.name ] = OSF ++ { ++ linker = osf ; ++ } ++ else if [ os.name ] = HPUX ++ { ++ linker = hpux ; ++ } ++ else if [ os.name ] = AIX ++ { ++ linker = aix ; ++ } ++ else if [ os.name ] = SOLARIS ++ { ++ linker = sun ; ++ } ++ else ++ { ++ linker = gnu ; ++ } ++ } ++ init-link-flags android $(linker) $(condition) ; ++ ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if $(command) ++ { ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ local lib_path = $(root)/bin $(root)/lib $(root)/lib32 $(root)/lib64 ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android libraries :: $(condition) :: $(lib_path) ; ++ } ++ toolset.flags android.link RUN_PATH $(condition) : $(lib_path) ; ++ } ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ local nl = " ++" ; ++ ++ # - The archive builder. ++ local archiver = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ar" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .AR $(condition) : $(archiver[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android archiver :: $(condition) :: $(archiver[1]) ; ++ } ++ ++ # - Ranlib ++ local ranlib = [ common.get-invocation-command android ++ : [ NORMALIZE_PATH [ MATCH "(.*)[$(nl)]+" : [ SHELL "$(command-string) -print-prog-name=ranlib" ] ] ] ++ : [ feature.get-values : $(options) ] ++ : $(bin) ++ : search-path ] ; ++ toolset.flags android.archive .RANLIB $(condition) : $(ranlib[1]) ; ++ if $(.debug-configuration) ++ { ++ ECHO notice: using android ranlib :: $(condition) :: $(ranlib[1]) ; ++ } ++ ++ ++ # - The resource compiler. ++ local rc = ++ [ common.get-invocation-command-nodefault android ++ : windres : [ feature.get-values : $(options) ] : $(bin) : search-path ] ; ++ local rc-type = ++ [ feature.get-values : $(options) ] ; ++ rc-type ?= windres ; ++ if ! $(rc) ++ { ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc = [ common.get-invocation-command android : as : : $(bin) : search-path ] ; ++ rc-type = null ; ++ } ++ rc.configure $(rc) : $(condition) : $(rc-type) ; ++} ++ ++if [ os.name ] = NT ++{ ++ # This causes single-line command invocation to not go through .bat files, ++ # thus avoiding command-line length limitations. ++ JAMSHELL = % ; ++} ++ ++generators.register-c-compiler android.compile.c++ : CPP : OBJ : android ; ++generators.register-c-compiler android.compile.c : C : OBJ : android ; ++generators.register-c-compiler android.compile.asm : ASM : OBJ : android ; ++generators.register-fortran-compiler android.compile.fortran : FORTRAN FORTRAN90 : OBJ : android ; ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set-generated-target-suffix PCH : android : gch ; ++ ++# android-specific pch generator. ++class android-pch-generator : pch-generator ++{ ++ import project ; ++ import property-set ; ++ import type ; ++ ++ rule run-pch ( project name ? : property-set : sources + ) ++ { ++ # Find the header in sources. Ignore any CPP sources. ++ local header ; ++ for local s in $(sources) ++ { ++ if [ type.is-derived [ $(s).type ] H ] ++ { ++ header = $(s) ; ++ } ++ } ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ local header-name = [ $(header).name ] ; ++ local header-basename = $(header-name:B) ; ++ if $(header-basename) != $(name) ++ { ++ local location = [ $(project).project-module ] ; ++ errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ } ++ ++ local pch-file = [ generator.run $(project) $(name) : $(property-set) ++ : $(header) ] ; ++ ++ # return result of base class and pch-file property as usage-requirements ++ return ++ [ property-set.create $(pch-file) -Winvalid-pch ] ++ $(pch-file) ++ ; ++ } ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ rule generated-targets ( sources + : property-set : project name ? ) ++ { ++ name = [ $(sources[1]).name ] ; ++ return [ generator.generated-targets $(sources) ++ : $(property-set) : $(project) $(name) ] ; ++ } ++} ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register [ new android-pch-generator android.compile.c.pch : H : C_PCH : on android ] ; ++generators.register [ new android-pch-generator android.compile.c++.pch : H : CPP_PCH : on android ] ; ++ ++# Override default do-nothing generators. ++generators.override android.compile.c.pch : pch.default-c-pch-generator ; ++generators.override android.compile.c++.pch : pch.default-cpp-pch-generator ; ++ ++toolset.flags android.compile PCH_FILE on : ; ++ ++# Declare flags and action for compilation. ++toolset.flags android.compile OPTIONS off : -O0 ; ++toolset.flags android.compile OPTIONS speed : -O3 ; ++toolset.flags android.compile OPTIONS space : -Os ; ++ ++toolset.flags android.compile OPTIONS off : -fno-inline ; ++toolset.flags android.compile OPTIONS on : -Wno-inline ; ++toolset.flags android.compile OPTIONS full : -finline-functions -Wno-inline ; ++ ++toolset.flags android.compile OPTIONS off : -w ; ++toolset.flags android.compile OPTIONS on : -Wall ; ++toolset.flags android.compile OPTIONS all : -Wall -pedantic ; ++toolset.flags android.compile OPTIONS on : -Werror ; ++ ++toolset.flags android.compile OPTIONS on : -g ; ++toolset.flags android.compile OPTIONS on : -pg ; ++toolset.flags android.compile OPTIONS off : -fno-rtti ; ++ ++rule setup-fpic ( targets * : sources * : properties * ) ++{ ++ local link = [ feature.get-values link : $(properties) ] ; ++ if $(link) = shared ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it is not needed, as 'd' is used only in exe. However, it is hard to ++ # detect where a target is going to be used. Alternatively, we can set -fPIC ++ # only when main target type is LIB but than 'b' would be compiled without ++ # -fPIC which would lead to link errors on x86-64. So, compile everything ++ # with -fPIC. ++ # ++ # Yet another alternative would be to create a propagated ++ # feature and set it when building shared libraries, but that would be hard ++ # to implement and would increase the target path length even more. ++ ++ # On Windows, fPIC is default, specifying -fPIC explicitly leads to ++ # a warning. ++ if $(target) != cygwin && $(target) != windows ++ { ++ OPTIONS on $(targets) += -fPIC ; ++ } ++ } ++} ++ ++rule setup-address-model ( targets * : sources * : properties * ) ++{ ++ local model = [ feature.get-values address-model : $(properties) ] ; ++ if $(model) ++ { ++ local option ; ++ local os = [ feature.get-values target-os : $(properties) ] ; ++ if $(os) = aix ++ { ++ if $(model) = 32 ++ { ++ option = -maix32 ; ++ } ++ else ++ { ++ option = -maix64 ; ++ } ++ } ++ else ++ { ++ if $(model) = 32 ++ { ++ option = -m32 ; ++ } ++ else if $(model) = 64 ++ { ++ option = -m64 ; ++ } ++ # For darwin, the model can be 32_64. darwin.jam will handle that ++ # on its own. ++ } ++ OPTIONS on $(targets) += $(option) ; ++ } ++} ++ ++ ++# FIXME: this should not use os.name. ++if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX ++{ ++ # OSF does have an option called -soname but it does not seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = -h ; ++} ++ ++# HPUX, for some reason, seem to use '+h', not '-h'. ++if [ os.name ] = HPUX ++{ ++ HAVE_SONAME = "" ; ++ SONAME_OPTION = +h ; ++} ++ ++toolset.flags android.compile USER_OPTIONS ; ++toolset.flags android.compile.c++ USER_OPTIONS ; ++toolset.flags android.compile DEFINES ; ++toolset.flags android.compile INCLUDES ; ++toolset.flags android.compile.c++ TEMPLATE_DEPTH ; ++toolset.flags android.compile.fortran USER_OPTIONS ; ++ ++rule compile.c++.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++.pch ++{ ++ "$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c.pch ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c.pch ++{ ++ "$(CONFIG_COMMAND)" -x c-header $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.c++ ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C ++ { ++ LANG on $(<) = "-x c++" ; ++ } ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++ ++ # Here we want to raise the template-depth parameter value to something ++ # higher than the default value of 17. Note that we could do this using the ++ # feature.set-default rule but we do not want to set the default value for ++ # all toolsets as well. ++ # ++ # TODO: This 'modified default' has been inherited from some 'older Boost ++ # Build implementation' and has most likely been added to make some Boost ++ # library parts compile correctly. We should see what exactly prompted this ++ # and whether we can get around the problem more locally. ++ local template-depth = [ on $(<) return $(TEMPLATE_DEPTH) ] ; ++ if ! $(template-depth) ++ { ++ TEMPLATE_DEPTH on $(<) = 128 ; ++ } ++} ++ ++rule compile.c ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ LANG on $(<) = "-x c" ; ++ #} ++ DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ; ++} ++ ++rule compile.fortran ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-fpic $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++} ++ ++actions compile.c++ bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-$(TEMPLATE_DEPTH) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<:W)" "$(>:W)" ++} ++ ++actions compile.c bind PCH_FILE ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++actions compile.fortran ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++rule compile.asm ++{ ++ LANG on $(<) = "-x assembler-with-cpp" ; ++} ++ ++actions compile.asm ++{ ++ "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" ++} ++ ++# The class which check that we don't try to use the static ++# property while creating or using shared library, since it's not supported by ++# android/libc. ++class android-linking-generator : unix-linking-generator ++{ ++ rule run ( project name ? : property-set : sources + ) ++ { ++ # TODO: Replace this with the use of a target-os property. ++ local no-static-link = ; ++ if [ modules.peek : UNIX ] ++ { ++ switch [ modules.peek : JAMUNAME ] ++ { ++ case * : no-static-link = true ; ++ } ++ } ++ ++ local properties = [ $(property-set).raw ] ; ++ local reason ; ++ if $(no-static-link) && static in $(properties) ++ { ++ if shared in $(properties) ++ { ++ reason = ++ "On android, DLL can't be build with 'static'." ; ++ } ++ else if [ type.is-derived $(self.target-types[1]) EXE ] ++ { ++ for local s in $(sources) ++ { ++ local type = [ $(s).type ] ; ++ if $(type) && [ type.is-derived $(type) SHARED_LIB ] ++ { ++ reason = ++ "On android, using DLLS together with the" ++ "static options is not possible " ; ++ } ++ } ++ } ++ } ++ if $(reason) ++ { ++ ECHO warning: ++ $(reason) ; ++ ECHO warning: ++ "It is suggested to use 'static' together" ++ "with 'static'." ; ++ return ; ++ } ++ else ++ { ++ local generated-targets = [ unix-linking-generator.run $(project) ++ $(name) : $(property-set) : $(sources) ] ; ++ return $(generated-targets) ; ++ } ++ } ++} ++ ++# The set of permissible input types is different on mingw. ++# So, define two sets of generators, with mingw generators ++# selected when target-os=windows. ++ ++local g ; ++g = [ new android-linking-generator android.mingw.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android windows ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.mingw.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android windows ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.register ++ [ new android-linking-generator android.link ++ : LIB OBJ ++ : EXE ++ : android ] ; ++generators.register ++ [ new android-linking-generator android.link.dll ++ : LIB OBJ ++ : SHARED_LIB ++ : android ] ; ++ ++generators.override android.mingw.link : android.link ; ++generators.override android.mingw.link.dll : android.link.dll ; ++ ++# Cygwin is similar to msvc and mingw in that it uses import libraries. ++# While in simple cases, it can directly link to a shared library, ++# it is believed to be slower, and not always possible. Define cygwin-specific ++# generators here. ++ ++g = [ new android-linking-generator android.cygwin.link ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : EXE ++ : android cygwin ] ; ++$(g).set-rule-name android.link ; ++generators.register $(g) ; ++ ++g = [ new android-linking-generator android.cygwin.link.dll ++ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB ++ : IMPORT_LIB SHARED_LIB ++ : android cygwin ] ; ++$(g).set-rule-name android.link.dll ; ++generators.register $(g) ; ++ ++generators.override android.cygwin.link : android.link ; ++generators.override android.cygwin.link.dll : android.link.dll ; ++ ++# Declare flags for linking. ++# First, the common flags. ++toolset.flags android.link OPTIONS on : -g ; ++toolset.flags android.link OPTIONS on : -pg ; ++toolset.flags android.link USER_OPTIONS ; ++toolset.flags android.link LINKPATH ; ++toolset.flags android.link FINDLIBS-ST ; ++toolset.flags android.link FINDLIBS-SA ; ++toolset.flags android.link LIBRARIES ; ++ ++toolset.flags android.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; ++toolset.flags android.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if [ os.name ] != HPUX ++{ ++ toolset.flags android.link OPTIONS static : -static ; ++} ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. ++rule init-link-flags ( toolset linker condition ) ++{ ++ switch $(linker) ++ { ++ case aix : ++ { ++ # ++ # On AIX we *have* to use the native linker. ++ # ++ # Using -brtl, the AIX linker will look for libraries with both the .a ++ # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the ++ # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived ++ # file that may contain shared objects and is different from static libs ++ # as on Linux. ++ # ++ # The -bnoipath strips the prepending (relative) path of libraries from ++ # the loader section in the target library or executable. Hence, during ++ # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded ++ # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without ++ # this option, the prepending (relative) path + library name is ++ # hard-coded in the loader section, causing *only* this path to be ++ # searched during load-time. Note that the AIX linker does not have an ++ # -soname equivalent, this is as close as it gets. ++ # ++ # The above options are definately for AIX 5.x, and most likely also for ++ # AIX 4.x and AIX 6.x. For details about the AIX linker see: ++ # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf ++ # ++ ++ toolset.flags $(toolset).link OPTIONS : -Wl,-brtl -Wl,-bnoipath ++ : unchecked ; ++ } ++ ++ case darwin : ++ { ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ } ++ ++ case gnu : ++ { ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : : unchecked ; ++ toolset.flags $(toolset).link RPATH_LINK $(condition) : : unchecked ; ++ toolset.flags $(toolset).link START-GROUP $(condition) : -Wl,--start-group : unchecked ; ++ toolset.flags $(toolset).link END-GROUP $(condition) : -Wl,--end-group : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/shared ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/shared ++ : -Wl,-Bdynamic : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ toolset.flags $(toolset).link FINDLIBS-ST-PFX $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ toolset.flags $(toolset).link FINDLIBS-SA-PFX $(condition)/static/windows ++ : -Wl,-Bdynamic : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/static/windows ++ : -Wl,-Bstatic : unchecked ; ++ } ++ ++ case hpux : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -fPIC : unchecked ; ++ } ++ ++ case osf : ++ { ++ # No --strip-all, just -s. ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # This does not supports -R. ++ toolset.flags $(toolset).link RPATH_OPTION $(condition) : -rpath ++ : unchecked ; ++ # -rpath-link is not supported at all. ++ } ++ ++ case sun : ++ { ++ toolset.flags $(toolset).link OPTIONS $(condition)/on ++ : -Wl,-s : unchecked ; ++ toolset.flags $(toolset).link RPATH $(condition) : ++ : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ toolset.flags $(toolset).link LINKPATH $(condition) : ++ : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ toolset.flags $(toolset).link OPTIONS $(condition)/shared ++ : -mimpure-text : unchecked ; ++ } ++ ++ case * : ++ { ++ errors.user-error ++ "$(toolset) initialization: invalid linker '$(linker)'" : ++ "The value '$(linker)' specified for is not recognized." : ++ "Possible values are 'aix', 'darwin', 'gnu', 'hpux', 'osf' or 'sun'" ; ++ } ++ } ++} ++ ++# Enclose the RPATH variable on 'targets' in (double) quotes, ++# unless it's already enclosed in single quotes. ++# This special casing is done because it's common to pass ++# '$ORIGIN' to linker -- and it has to have single quotes ++# to prevent expansion by shell -- and if we add double ++# quotes then preventing properties of single quotes disappear. ++rule quote-rpath ( targets * ) ++{ ++ local r = [ on $(targets[1]) return $(RPATH) ] ; ++ if ! [ MATCH "('.*')" : $(r) ] ++ { ++ r = "\"$(r)\"" ; ++ } ++ RPATH on $(targets) = $(r) ; ++} ++ ++# Declare actions for linking. ++rule link ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++actions link bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++ ++} ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++.AR = ar ; ++.RANLIB = ranlib ; ++ ++toolset.flags android.archive AROPTIONS ; ++ ++rule archive ( targets * : sources * : properties * ) ++{ ++ # Always remove archive and start again. Here is the rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ # ++ local clean.a = $(targets[1])(clean) ; ++ TEMPORARY $(clean.a) ; ++ NOCARE $(clean.a) ; ++ LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; ++ DEPENDS $(clean.a) : $(sources) ; ++ DEPENDS $(targets) : $(clean.a) ; ++ common.RmTemps $(clean.a) : $(targets) ; ++} ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++actions piecemeal archive ++{ ++ "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" ++ "$(.RANLIB)" "$(<)" ++} ++ ++rule link.dll ( targets * : sources * : properties * ) ++{ ++ setup-threading $(targets) : $(sources) : $(properties) ; ++ setup-address-model $(targets) : $(sources) : $(properties) ; ++ SPACE on $(targets) = " " ; ++ JAM_SEMAPHORE on $(targets) = android-link-semaphore ; ++ quote-rpath $(targets) ; ++} ++ ++# Differs from 'link' above only by -shared. ++actions link.dll bind LIBRARIES ++{ ++ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) ++} ++ ++rule setup-threading ( targets * : sources * : properties * ) ++{ ++ local threading = [ feature.get-values threading : $(properties) ] ; ++ if $(threading) = multi ++ { ++ local target = [ feature.get-values target-os : $(properties) ] ; ++ local option ; ++ local libs ; ++ ++ ECHO "MOSSS>>> target: $(target)" ; ++ ++ switch $(target) ++ { ++ case windows : ++ { ++ option = -mthreads ; ++ } ++ case cygwin : ++ { ++ option = -mthreads ; ++ } ++ case solaris : ++ { ++ option = -pthreads ; ++ libs = rt ; ++ } ++ case beos : ++ { ++ # BeOS has no threading options, so do not set anything here. ++ } ++ case *bsd : ++ { ++ option = -pthread ; ++ # There is no -lrt on BSD. ++ } ++ case sgi : ++ { ++ # android on IRIX does not support multi-threading so do not set anything ++ # here. ++ } ++ case darwin : ++ { ++ # Darwin has no threading options so do not set anything here. ++ } ++ case android : ++ { ++ # @Moss - Make Android decision here ++ } ++ case * : ++ { ++ #option = -pthread ; ++ #libs = rt ; ++ } ++ } ++ ++ if $(option) ++ { ++ OPTIONS on $(targets) += $(option) ; ++ } ++ if $(libs) ++ { ++ FINDLIBS-SA on $(targets) += $(libs) ; ++ } ++ } ++} ++ ++local rule cpu-flags ( toolset variable : architecture : instruction-set + : values + : default ? ) ++{ ++ if $(default) ++ { ++ toolset.flags $(toolset) $(variable) ++ $(architecture)/ ++ : $(values) ; ++ } ++ toolset.flags $(toolset) $(variable) ++ /$(instruction-set) ++ $(architecture)/$(instruction-set) ++ : $(values) ; ++} ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++# The 'native' option appeared in android 4.2 so we cannot safely use it ++# as default. Use conservative i386 instead. ++cpu-flags android OPTIONS : x86 : native : -march=native ; ++cpu-flags android OPTIONS : x86 : i386 : -march=i386 : default ; ++cpu-flags android OPTIONS : x86 : i486 : -march=i486 ; ++cpu-flags android OPTIONS : x86 : i586 : -march=i586 ; ++cpu-flags android OPTIONS : x86 : i686 : -march=i686 ; ++cpu-flags android OPTIONS : x86 : pentium : -march=pentium ; ++cpu-flags android OPTIONS : x86 : pentium-mmx : -march=pentium-mmx ; ++cpu-flags android OPTIONS : x86 : pentiumpro : -march=pentiumpro ; ++cpu-flags android OPTIONS : x86 : pentium2 : -march=pentium2 ; ++cpu-flags android OPTIONS : x86 : pentium3 : -march=pentium3 ; ++cpu-flags android OPTIONS : x86 : pentium3m : -march=pentium3m ; ++cpu-flags android OPTIONS : x86 : pentium-m : -march=pentium-m ; ++cpu-flags android OPTIONS : x86 : pentium4 : -march=pentium4 ; ++cpu-flags android OPTIONS : x86 : pentium4m : -march=pentium4m ; ++cpu-flags android OPTIONS : x86 : prescott : -march=prescott ; ++cpu-flags android OPTIONS : x86 : nocona : -march=nocona ; ++cpu-flags android OPTIONS : x86 : core2 : -march=core2 ; ++cpu-flags android OPTIONS : x86 : k6 : -march=k6 ; ++cpu-flags android OPTIONS : x86 : k6-2 : -march=k6-2 ; ++cpu-flags android OPTIONS : x86 : k6-3 : -march=k6-3 ; ++cpu-flags android OPTIONS : x86 : athlon : -march=athlon ; ++cpu-flags android OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ; ++cpu-flags android OPTIONS : x86 : athlon-4 : -march=athlon-4 ; ++cpu-flags android OPTIONS : x86 : athlon-xp : -march=athlon-xp ; ++cpu-flags android OPTIONS : x86 : athlon-mp : -march=athlon-mp ; ++## ++cpu-flags android OPTIONS : x86 : k8 : -march=k8 ; ++cpu-flags android OPTIONS : x86 : opteron : -march=opteron ; ++cpu-flags android OPTIONS : x86 : athlon64 : -march=athlon64 ; ++cpu-flags android OPTIONS : x86 : athlon-fx : -march=athlon-fx ; ++cpu-flags android OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ; ++cpu-flags android OPTIONS : x86 : winchip2 : -march=winchip2 ; ++cpu-flags android OPTIONS : x86 : c3 : -march=c3 ; ++cpu-flags android OPTIONS : x86 : c3-2 : -march=c3-2 ; ++# Sparc ++cpu-flags android OPTIONS : sparc : c3 : -mcpu=c3 : default ; ++cpu-flags android OPTIONS : sparc : v7 : -mcpu=v7 ; ++cpu-flags android OPTIONS : sparc : cypress : -mcpu=cypress ; ++cpu-flags android OPTIONS : sparc : v8 : -mcpu=v8 ; ++cpu-flags android OPTIONS : sparc : supersparc : -mcpu=supersparc ; ++cpu-flags android OPTIONS : sparc : sparclite : -mcpu=sparclite ; ++cpu-flags android OPTIONS : sparc : hypersparc : -mcpu=hypersparc ; ++cpu-flags android OPTIONS : sparc : sparclite86x : -mcpu=sparclite86x ; ++cpu-flags android OPTIONS : sparc : f930 : -mcpu=f930 ; ++cpu-flags android OPTIONS : sparc : f934 : -mcpu=f934 ; ++cpu-flags android OPTIONS : sparc : sparclet : -mcpu=sparclet ; ++cpu-flags android OPTIONS : sparc : tsc701 : -mcpu=tsc701 ; ++cpu-flags android OPTIONS : sparc : v9 : -mcpu=v9 ; ++cpu-flags android OPTIONS : sparc : ultrasparc : -mcpu=ultrasparc ; ++cpu-flags android OPTIONS : sparc : ultrasparc3 : -mcpu=ultrasparc3 ; ++# RS/6000 & PowerPC ++cpu-flags android OPTIONS : power : 403 : -mcpu=403 ; ++cpu-flags android OPTIONS : power : 505 : -mcpu=505 ; ++cpu-flags android OPTIONS : power : 601 : -mcpu=601 ; ++cpu-flags android OPTIONS : power : 602 : -mcpu=602 ; ++cpu-flags android OPTIONS : power : 603 : -mcpu=603 ; ++cpu-flags android OPTIONS : power : 603e : -mcpu=603e ; ++cpu-flags android OPTIONS : power : 604 : -mcpu=604 ; ++cpu-flags android OPTIONS : power : 604e : -mcpu=604e ; ++cpu-flags android OPTIONS : power : 620 : -mcpu=620 ; ++cpu-flags android OPTIONS : power : 630 : -mcpu=630 ; ++cpu-flags android OPTIONS : power : 740 : -mcpu=740 ; ++cpu-flags android OPTIONS : power : 7400 : -mcpu=7400 ; ++cpu-flags android OPTIONS : power : 7450 : -mcpu=7450 ; ++cpu-flags android OPTIONS : power : 750 : -mcpu=750 ; ++cpu-flags android OPTIONS : power : 801 : -mcpu=801 ; ++cpu-flags android OPTIONS : power : 821 : -mcpu=821 ; ++cpu-flags android OPTIONS : power : 823 : -mcpu=823 ; ++cpu-flags android OPTIONS : power : 860 : -mcpu=860 ; ++cpu-flags android OPTIONS : power : 970 : -mcpu=970 ; ++cpu-flags android OPTIONS : power : 8540 : -mcpu=8540 ; ++cpu-flags android OPTIONS : power : power : -mcpu=power ; ++cpu-flags android OPTIONS : power : power2 : -mcpu=power2 ; ++cpu-flags android OPTIONS : power : power3 : -mcpu=power3 ; ++cpu-flags android OPTIONS : power : power4 : -mcpu=power4 ; ++cpu-flags android OPTIONS : power : power5 : -mcpu=power5 ; ++cpu-flags android OPTIONS : power : powerpc : -mcpu=powerpc ; ++cpu-flags android OPTIONS : power : powerpc64 : -mcpu=powerpc64 ; ++cpu-flags android OPTIONS : power : rios : -mcpu=rios ; ++cpu-flags android OPTIONS : power : rios1 : -mcpu=rios1 ; ++cpu-flags android OPTIONS : power : rios2 : -mcpu=rios2 ; ++cpu-flags android OPTIONS : power : rsc : -mcpu=rsc ; ++cpu-flags android OPTIONS : power : rs64a : -mcpu=rs64 ; ++# AIX variant of RS/6000 & PowerPC ++toolset.flags android AROPTIONS 64/aix : "-X 64" ; +diff -ruN boost_1_54_0-boot/tools/build/v2/tools/android.py boost_1_54_0-patched/tools/build/v2/tools/android.py +--- boost_1_54_0-boot/tools/build/v2/tools/android.py ++++ boost_1_54_0-patched/tools/build/v2/tools/android.py +@@ -0,0 +1,798 @@ ++# Status: being ported by Steven Watanabe ++# Base revision: 47077 ++# TODO: common.jam needs to be ported ++# TODO: generators.jam needs to have register_c_compiler. ++# ++# Copyright 2001 David Abrahams. ++# Copyright 2002-2006 Rene Rivera. ++# Copyright 2002-2003 Vladimir Prus. ++# Copyright (c) 2005 Reece H. Dunn. ++# Copyright 2006 Ilya Sokolov. ++# Copyright 2007 Roland Schwarz ++# Copyright 2007 Boris Gubenko. ++# Copyright 2008 Steven Watanabe ++# Copyright 2010 Moritz Wundke. ++# ++# Distributed under the Boost Software License, Version 1.0. ++# (See accompanying file LICENSE_1_0.txt or copy at ++# http://www.boost.org/LICENSE_1_0.txt) ++ ++import os ++import subprocess ++import re ++ ++import bjam ++ ++from b2.tools import unix, common, rc, pch, builtin ++from b2.build import feature, type, toolset, generators ++from b2.util.utility import os_name, on_windows ++from b2.manager import get_manager ++from b2.build.generators import Generator ++from b2.build.toolset import flags ++from b2.util.utility import to_seq ++ ++__debug = None ++ ++def debug(): ++ global __debug ++ if __debug is None: ++ __debug = "--debug-configuration" in bjam.variable("ARGV") ++ return __debug ++ ++feature.extend('toolset', ['android']) ++ ++ ++toolset.inherit_generators('android', [], 'unix', ['unix.link', 'unix.link.dll']) ++toolset.inherit_flags('android', 'unix') ++toolset.inherit_rules('android', 'unix') ++ ++generators.override('android.prebuilt', 'builtin.prebuilt') ++generators.override('android.searched-lib-generator', 'searched-lib-generator') ++ ++# Target naming is determined by types/lib.jam and the settings below this ++# comment. ++# ++# On *nix: ++# libxxx.a static library ++# libxxx.so shared library ++# ++# On windows (mingw): ++# libxxx.lib static library ++# xxx.dll DLL ++# xxx.lib import library ++# ++# On windows (cygwin) i.e. cygwin ++# libxxx.a static library ++# xxx.dll DLL ++# libxxx.dll.a import library ++# ++# Note: user can always override by using the @rule ++# This settings have been choosen, so that mingw ++# is in line with msvc naming conventions. For ++# cygwin the cygwin naming convention has been choosen. ++ ++# Make the "o" suffix used for android toolset on all ++# platforms ++type.set_generated_target_suffix('OBJ', ['android'], 'o') ++type.set_generated_target_suffix('STATIC_LIB', ['android', 'cygwin'], 'a') ++ ++type.set_generated_target_suffix('IMPORT_LIB', ['android', 'cygwin'], 'dll.a') ++type.set_generated_target_prefix('IMPORT_LIB', ['android', 'cygwin'], 'lib') ++ ++__machine_match = re.compile('^([^ ]+)') ++__version_match = re.compile('^([0-9.]+)') ++ ++def init(version = None, command = None, options = None): ++ """ ++ Initializes the android toolset for the given version. If necessary, command may ++ be used to specify where the compiler is located. The parameter 'options' is a ++ space-delimited list of options, each one specified as ++ option-value. Valid option names are: cxxflags, linkflags and ++ linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun ++ and the default value will be selected based on the current OS. ++ Example: ++ using android : 3.4 : : foo bar sun ; ++ """ ++ ++ options = to_seq(options) ++ command = to_seq(command) ++ ++ # Information about the android command... ++ # The command. ++ command = to_seq(common.get_invocation_command('android', 'g++', command)) ++ # The root directory of the tool install. ++ root = feature.get_values('', options) ; ++ # The bin directory where to find the command to execute. ++ bin = None ++ # The flavor of compiler. ++ flavor = feature.get_values('', options) ++ # Autodetect the root and bin dir if not given. ++ if command: ++ if not bin: ++ bin = common.get_absolute_tool_path(command[-1]) ++ if not root: ++ root = os.path.dirname(bin) ++ # Autodetect the version and flavor if not given. ++ if command: ++ machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0] ++ machine = __machine_match.search(machine_info).group(1) ++ ++ version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0] ++ version = __version_match.search(version_info).group(1) ++ if not flavor and machine.find('mingw') != -1: ++ flavor = 'mingw' ++ ++ condition = None ++ if flavor: ++ condition = common.check_init_parameters('android', None, ++ ('version', version), ++ ('flavor', flavor)) ++ else: ++ condition = common.check_init_parameters('android', None, ++ ('version', version)) ++ ++ if command: ++ command = command[0] ++ ++ common.handle_options('android', condition, command, options) ++ ++ linker = feature.get_values('', options) ++ if not linker: ++ if os_name() == 'OSF': ++ linker = 'osf' ++ elif os_name() == 'HPUX': ++ linker = 'hpux' ; ++ else: ++ linker = 'gnu' ++ ++ init_link_flags('android', linker, condition) ++ ++ # If android is installed in non-standard location, we'd need to add ++ # LD_LIBRARY_PATH when running programs created with it (for unit-test/run ++ # rules). ++ if command: ++ # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries ++ # and all must be added to LD_LIBRARY_PATH. The linker will pick the ++ # right onces. Note that we don't provide a clean way to build 32-bit ++ # binary with 64-bit compiler, but user can always pass -m32 manually. ++ lib_path = [os.path.join(root, 'bin'), ++ os.path.join(root, 'lib'), ++ os.path.join(root, 'lib32'), ++ os.path.join(root, 'lib64')] ++ if debug(): ++ print 'notice: using android libraries ::', condition, '::', lib_path ++ toolset.flags('android.link', 'RUN_PATH', condition, lib_path) ++ ++ # If it's not a system android install we should adjust the various programs as ++ # needed to prefer using the install specific versions. This is essential ++ # for correct use of MinGW and for cross-compiling. ++ ++ # - The archive builder. ++ archiver = common.get_invocation_command('android', ++ 'ar', feature.get_values('', options), [bin], path_last=True) ++ toolset.flags('android.archive', '.AR', condition, [archiver]) ++ if debug(): ++ print 'notice: using android archiver ::', condition, '::', archiver ++ ++ # - The resource compiler. ++ rc_command = common.get_invocation_command_nodefault('android', ++ 'windres', feature.get_values('', options), [bin], path_last=True) ++ rc_type = feature.get_values('', options) ++ ++ if not rc_type: ++ rc_type = 'windres' ++ ++ if not rc_command: ++ # If we can't find an RC compiler we fallback to a null RC compiler that ++ # creates empty object files. This allows the same Jamfiles to work ++ # across the board. The null RC uses the assembler to create the empty ++ # objects, so configure that. ++ rc_command = common.get_invocation_command('android', 'as', [], [bin], path_last=True) ++ rc_type = 'null' ++ rc.configure(rc_command, condition, '' + rc_type) ++ ++###if [ os.name ] = NT ++###{ ++### # This causes single-line command invocation to not go through .bat files, ++### # thus avoiding command-line length limitations. ++### JAMSHELL = % ; ++###} ++ ++#FIXME: when register_c_compiler is moved to ++# generators, these should be updated ++builtin.register_c_compiler('android.compile.c++', ['CPP'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.c', ['C'], ['OBJ'], ['android']) ++builtin.register_c_compiler('android.compile.asm', ['ASM'], ['OBJ'], ['android']) ++ ++# pch support ++ ++# The compiler looks for a precompiled header in each directory just before it ++# looks for the include file in that directory. The name searched for is the ++# name specified in the #include directive with ".gch" suffix appended. The ++# logic in android-pch-generator will make sure that BASE_PCH suffix is appended to ++# full name of the header. ++ ++type.set_generated_target_suffix('PCH', ['android'], 'gch') ++ ++# android-specific pch generator. ++class androidPchGenerator(pch.PchGenerator): ++ ++ # Inherit the __init__ method ++ ++ def run_pch(self, project, name, prop_set, sources): ++ # Find the header in sources. Ignore any CPP sources. ++ header = None ++ for s in sources: ++ if type.is_derived(s.type, 'H'): ++ header = s ++ ++ # Error handling: Base header file name should be the same as the base ++ # precompiled header name. ++ header_name = header.name ++ header_basename = os.path.basename(header_name).rsplit('.', 1)[0] ++ if header_basename != name: ++ location = project.project_module ++ ###FIXME: ++ raise Exception() ++ ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; ++ ++ pch_file = Generator.run(self, project, name, prop_set, [header]) ++ ++ # return result of base class and pch-file property as usage-requirements ++ # FIXME: what about multiple results from generator.run? ++ return (property_set.create('' + pch_file[0], '-Winvalid-pch'), ++ pch_file) ++ ++ # Calls the base version specifying source's name as the name of the created ++ # target. As result, the PCH will be named whatever.hpp.gch, and not ++ # whatever.gch. ++ def generated_targets(self, sources, prop_set, project, name = None): ++ name = sources[0].name ++ return Generator.generated_targets(self, sources, ++ prop_set, project, name) ++ ++# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The ++# latter have HPP type, but HPP type is derived from H. The type of compilation ++# is determined entirely by the destination type. ++generators.register(androidPchGenerator('android.compile.c.pch', False, ['H'], ['C_PCH'], ['on', 'android' ])) ++generators.register(androidPchGenerator('android.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['on', 'android' ])) ++ ++# Override default do-nothing generators. ++generators.override('android.compile.c.pch', 'pch.default-c-pch-generator') ++generators.override('android.compile.c++.pch', 'pch.default-cpp-pch-generator') ++ ++flags('android.compile', 'PCH_FILE', ['on'], ['']) ++ ++# Declare flags and action for compilation ++flags('android.compile', 'OPTIONS', ['off'], ['-O0']) ++flags('android.compile', 'OPTIONS', ['speed'], ['-O3']) ++flags('android.compile', 'OPTIONS', ['space'], ['-Os']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-inline']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wno-inline']) ++flags('android.compile', 'OPTIONS', ['full'], ['-finline-functions', '-Wno-inline']) ++ ++flags('android.compile', 'OPTIONS', ['off'], ['-w']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Wall']) ++flags('android.compile', 'OPTIONS', ['all'], ['-Wall', '-pedantic']) ++flags('android.compile', 'OPTIONS', ['on'], ['-Werror']) ++ ++flags('android.compile', 'OPTIONS', ['on'], ['-g']) ++flags('android.compile', 'OPTIONS', ['on'], ['-pg']) ++flags('android.compile', 'OPTIONS', ['off'], ['-fno-rtti']) ++ ++# On cygwin and mingw, android generates position independent code by default, and ++# warns if -fPIC is specified. This might not be the right way of checking if ++# we're using cygwin. For example, it's possible to run cygwin android from NT ++# shell, or using crosscompiling. But we'll solve that problem when it's time. ++# In that case we'll just add another parameter to 'init' and move this login ++# inside 'init'. ++if not os_name () in ['CYGWIN', 'NT']: ++ print "osname:", os_name() ++ # This logic will add -fPIC for all compilations: ++ # ++ # lib a : a.cpp b ; ++ # obj b : b.cpp ; ++ # exe c : c.cpp a d ; ++ # obj d : d.cpp ; ++ # ++ # This all is fine, except that 'd' will be compiled with -fPIC even though ++ # it's not needed, as 'd' is used only in exe. However, it's hard to detect ++ # where a target is going to be used. Alternative, we can set -fPIC only ++ # when main target type is LIB but than 'b' will be compiled without -fPIC. ++ # In x86-64 that will lead to link errors. So, compile everything with ++ # -fPIC. ++ # ++ # Yet another alternative would be to create propagated ++ # feature, and set it when building shared libraries, but that's hard to ++ # implement and will increase target path length even more. ++ flags('android.compile', 'OPTIONS', ['shared'], ['-fPIC']) ++ ++if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX': ++ # OSF does have an option called -soname but it doesn't seem to work as ++ # expected, therefore it has been disabled. ++ HAVE_SONAME = '' ++ SONAME_OPTION = '-h' ++ ++ ++flags('android.compile', 'USER_OPTIONS', [], ['']) ++flags('android.compile.c++', 'USER_OPTIONS',[], ['']) ++flags('android.compile', 'DEFINES', [], ['']) ++flags('android.compile', 'INCLUDES', [], ['']) ++ ++engine = get_manager().engine() ++ ++engine.register_action('android.compile.c++.pch', ++ '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++engine.register_action('android.compile.c.pch', ++ '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"') ++ ++ ++def android_compile_cpp(targets, sources, properties): ++ # Some extensions are compiled as C++ by default. For others, we need to ++ # pass -x c++. We could always pass -x c++ but distcc does not work with it. ++ extension = os.path.splitext (sources [0]) [1] ++ lang = '' ++ if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: ++ lang = '-x c++' ++ get_manager().engine().set_target_variable (targets, 'LANG', lang) ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++def android_compile_c(targets, sources, properties): ++ engine = get_manager().engine() ++ # If we use the name g++ then default file suffix -> language mapping does ++ # not work. So have to pass -x option. Maybe, we can work around this by ++ # allowing the user to specify both C and C++ compiler names. ++ #if $(>:S) != .c ++ #{ ++ engine.set_target_variable (targets, 'LANG', '-x c') ++ #} ++ engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE')) ++ ++engine.register_action( ++ 'android.compile.c++', ++ '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' + ++ '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' + ++ '-c -o "$(<:W)" "$(>:W)"', ++ function=android_compile_cpp, ++ bound_list=['PCH_FILE']) ++ ++engine.register_action( ++ 'android.compile.c', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' + ++ '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_c, ++ bound_list=['PCH_FILE']) ++ ++def android_compile_asm(targets, sources, properties): ++ get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp') ++ ++engine.register_action( ++ 'android.compile.asm', ++ '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"', ++ function=android_compile_asm) ++ ++ ++class androidLinkingGenerator(unix.UnixLinkingGenerator): ++ """ ++ The class which check that we don't try to use the static ++ property while creating or using shared library, since it's not supported by ++ android/libc. ++ """ ++ def run(self, project, name, prop_set, sources): ++ # TODO: Replace this with the use of a target-os property. ++ ++ no_static_link = False ++ if bjam.variable('UNIX'): ++ no_static_link = True; ++ ##FIXME: what does this mean? ++## { ++## switch [ modules.peek : JAMUNAME ] ++## { ++## case * : no-static-link = true ; ++## } ++## } ++ ++ properties = prop_set.raw() ++ reason = None ++ if no_static_link and 'static' in properties: ++ if 'shared' in properties: ++ reason = "On android, DLL can't be build with 'static'." ++ elif type.is_derived(self.target_types[0], 'EXE'): ++ for s in sources: ++ source_type = s.type() ++ if source_type and type.is_derived(source_type, 'SHARED_LIB'): ++ reason = "On android, using DLLS together with the " +\ ++ "static options is not possible " ++ if reason: ++ print 'warning:', reason ++ print 'warning:',\ ++ "It is suggested to use 'static' together",\ ++ "with 'static'." ; ++ return ++ else: ++ generated_targets = unix.UnixLinkingGenerator.run(self, project, ++ name, prop_set, sources) ++ return generated_targets ++ ++if on_windows(): ++ flags('android.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,']) ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ [ 'EXE' ], ++ [ 'android' ])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ++ ['IMPORT_LIB', 'SHARED_LIB'], ++ ['android'])) ++else: ++ generators.register( ++ androidLinkingGenerator('android.link', True, ++ ['LIB', 'OBJ'], ++ ['EXE'], ++ ['android'])) ++ generators.register( ++ androidLinkingGenerator('android.link.dll', True, ++ ['LIB', 'OBJ'], ++ ['SHARED_LIB'], ++ ['android'])) ++ ++# Declare flags for linking. ++# First, the common flags. ++flags('android.link', 'OPTIONS', ['on'], ['-g']) ++flags('android.link', 'OPTIONS', ['on'], ['-pg']) ++flags('android.link', 'USER_OPTIONS', [], ['']) ++flags('android.link', 'LINKPATH', [], ['']) ++flags('android.link', 'FINDLIBS-ST', [], ['']) ++flags('android.link', 'FINDLIBS-SA', [], ['']) ++flags('android.link', 'LIBRARIES', [], ['']) ++ ++# For static we made sure there are no dynamic libraries in the ++# link. On HP-UX not all system libraries exist as archived libraries (for ++# example, there is no libunwind.a), so, on this platform, the -static option ++# cannot be specified. ++if os_name() != 'HPUX': ++ flags('android.link', 'OPTIONS', ['static'], ['-static']) ++ ++# Now, the vendor specific flags. ++# The parameter linker can be either gnu, darwin, osf, hpux or sun. ++def init_link_flags(toolset, linker, condition): ++ """ ++ Now, the vendor specific flags. ++ The parameter linker can be either gnu, darwin, osf, hpux or sun. ++ """ ++ toolset_link = toolset + '.link' ++ if linker == 'gnu': ++ # Strip the binary when no debugging is needed. We use --strip-all flag ++ # as opposed to -s since icc (intel's compiler) is generally ++ # option-compatible with and inherits from the android toolset, but does not ++ # support -s. ++ ++ # FIXME: what does unchecked translate to? ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,--strip-all']) # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ; ++ flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ; ++ ++ # gnu ld has the ability to change the search behaviour for libraries ++ # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic ++ # and change search for -l switches that follow them. The following list ++ # shows the tried variants. ++ # The search stops at the first variant that has a match. ++ # *nix: -Bstatic -lxxx ++ # libxxx.a ++ # ++ # *nix: -Bdynamic -lxxx ++ # libxxx.so ++ # libxxx.a ++ # ++ # windows (mingw,cygwin) -Bstatic -lxxx ++ # libxxx.a ++ # xxx.lib ++ # ++ # windows (mingw,cygwin) -Bdynamic -lxxx ++ # libxxx.dll.a ++ # xxx.dll.a ++ # libxxx.a ++ # xxx.lib ++ # cygxxx.dll (*) ++ # libxxx.dll ++ # xxx.dll ++ # libxxx.a ++ # ++ # (*) This is for cygwin ++ # Please note that -Bstatic and -Bdynamic are not a guarantee that a ++ # static or dynamic lib indeed gets linked in. The switches only change ++ # search patterns! ++ ++ # On *nix mixing shared libs with static runtime is not a good idea. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/shared', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ ++ # On windows allow mixing of static and dynamic libs with static ++ # runtime. ++ flags(toolset_link, 'FINDLIBS-ST-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ flags(toolset_link, 'FINDLIBS-SA-PFX', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bdynamic']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', ++ map(lambda x: x + '/static/windows', condition), ++ ['-Wl,-Bstatic']) # : unchecked ; ++ ++ elif linker == 'darwin': ++ # On Darwin, the -s option to ld does not work unless we pass -static, ++ # and passing -static unconditionally is a bad idea. So, don't pass -s. ++ # at all, darwin.jam will use separate 'strip' invocation. ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ flags(toolset_link, 'RPATH_LINK', condition, ['']) # : unchecked ; ++ ++ elif linker == 'osf': ++ # No --strip-all, just -s. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # This does not supports -R. ++ flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ; ++ # -rpath-link is not supported at all. ++ ++ elif linker == 'sun': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ['-Wl,-s']) ++ # : unchecked ; ++ flags(toolset_link, 'RPATH', condition, ['']) # : unchecked ; ++ # Solaris linker does not have a separate -rpath-link, but allows to use ++ # -L for the same purpose. ++ flags(toolset_link, 'LINKPATH', condition, ['']) # : unchecked ; ++ ++ # This permits shared libraries with non-PIC code on Solaris. ++ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the ++ # following is not needed. Whether -fPIC should be hardcoded, is a ++ # separate question. ++ # AH, 2004/10/16: it is still necessary because some tests link against ++ # static libraries that were compiled without PIC. ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ['-mimpure-text']) ++ # : unchecked ; ++ ++ elif linker == 'hpux': ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/off', condition), ++ ['-Wl,-s']) # : unchecked ; ++ flags(toolset_link, 'OPTIONS', map(lambda x: x + '/shared', condition), ++ ['-fPIC']) # : unchecked ; ++ ++ else: ++ # FIXME: ++ errors.user_error( ++ "$(toolset) initialization: invalid linker '$(linker)' " + ++ "The value '$(linker)' specified for is not recognized. " + ++ "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'") ++ ++# Declare actions for linking. ++def android_link(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ # Serialize execution of the 'link' action, since running N links in ++ # parallel is just slower. For now, serialize only android links, it might be a ++ # good idea to serialize all links. ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link', ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' + ++ '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function=android_link, ++ bound_list=['LIBRARIES']) ++ ++# Default value. Mostly for the sake of intel-linux that inherits from android, but ++# does not have the same logic to set the .AR variable. We can put the same ++# logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is ++# always available. ++__AR = 'ar' ++ ++flags('android.archive', 'AROPTIONS', [], ['']) ++ ++def android_archive(targets, sources, properties): ++ # Always remove archive and start again. Here's rationale from ++ # ++ # Andre Hentz: ++ # ++ # I had a file, say a1.c, that was included into liba.a. I moved a1.c to ++ # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd ++ # errors. After some debugging I traced it back to the fact that a1.o was ++ # *still* in liba.a ++ # ++ # Rene Rivera: ++ # ++ # Originally removing the archive was done by splicing an RM onto the ++ # archive action. That makes archives fail to build on NT when they have ++ # many files because it will no longer execute the action directly and blow ++ # the line length limit. Instead we remove the file in a different action, ++ # just before building the archive. ++ clean = targets[0] + '(clean)' ++ bjam.call('TEMPORARY', clean) ++ bjam.call('NOCARE', clean) ++ engine = get_manager().engine() ++ engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) ++ engine.add_dependency(clean, sources) ++ engine.add_dependency(targets, clean) ++ engine.set_update_action('common.RmTemps', clean, targets, None) ++ ++# Declare action for creating static libraries. ++# The letter 'r' means to add files to the archive with replacement. Since we ++# remove archive, we don't care about replacement, but there's no option "add ++# without replacement". ++# The letter 'c' suppresses the warning in case the archive does not exists yet. ++# That warning is produced only on some platforms, for whatever reasons. ++engine.register_action('android.archive', ++ '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"', ++ function=android_archive, ++ flags=['piecemeal']) ++ ++def android_link_dll(targets, sources, properties): ++ engine = get_manager().engine() ++ engine.set_target_variable(targets, 'SPACE', ' ') ++ engine.set_target_variable(targets, 'JAM_SEMAPHORE', 'android-link-semaphore') ++ ++engine.register_action( ++ 'android.link.dll', ++ # Differ from 'link' above only by -shared. ++ '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' + ++ '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' + ++ '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' + ++ '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' + ++ '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' + ++ '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' + ++ '$(OPTIONS) $(USER_OPTIONS)', ++ function = android_link_dll, ++ bound_list=['LIBRARIES']) ++ ++# Set up threading support. It's somewhat contrived, so perform it at the end, ++# to avoid cluttering other code. ++ ++if on_windows(): ++ flags('android', 'OPTIONS', ['multi'], ['-mthreads']) ++elif bjam.variable('UNIX'): ++ jamuname = bjam.variable('JAMUNAME') ++ host_os_name = jamuname[0] ++ print "MOSSS>>> host_os_name:", host_os_name ++ if host_os_name.startswith('SunOS'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthreads']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ elif host_os_name == 'BeOS': ++ # BeOS has no threading options, don't set anything here. ++ pass ++ elif host_os_name.endswith('BSD'): ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD ++ elif host_os_name == 'DragonFly': ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ # there is no -lrt on BSD - DragonFly is a FreeBSD variant, ++ # which anoyingly doesn't say it's a *BSD. ++ elif host_os_name == 'IRIX': ++ # android on IRIX does not support multi-threading, don't set anything here. ++ pass ++ elif host_os_name == 'Darwin': ++ # Darwin has no threading options, don't set anything here. ++ pass ++ else: ++ #flags('android', 'OPTIONS', ['multi'], ['-pthread']) ++ #flags('android', 'FINDLIBS-SA', [], ['rt']) ++ ++def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): ++ #FIXME: for some reason this fails. Probably out of date feature code ++## if default: ++## flags(toolset, variable, ++## ['' + architecture + '/'], ++## values) ++ flags(toolset, variable, ++ #FIXME: same as above ++ [##'/' + instruction_set, ++ '' + architecture + '/' + instruction_set], ++ values) ++ ++# Set architecture/instruction-set options. ++# ++# x86 and compatible ++flags('android', 'OPTIONS', ['x86/32'], ['-m32']) ++flags('android', 'OPTIONS', ['x86/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True) ++cpu_flags('android', 'OPTIONS', 'x86', 'i486', ['-march=i486']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i586', ['-march=i586']) ++cpu_flags('android', 'OPTIONS', 'x86', 'i686', ['-march=i686']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium', ['-march=pentium']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m']) ++cpu_flags('android', 'OPTIONS', 'x86', 'prescott', ['-march=prescott']) ++cpu_flags('android', 'OPTIONS', 'x86', 'nocona', ['-march=nocona']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6', ['-march=k6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon', ['-march=athlon']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp']) ++## ++cpu_flags('android', 'OPTIONS', 'x86', 'k8', ['-march=k8']) ++cpu_flags('android', 'OPTIONS', 'x86', 'opteron', ['-march=opteron']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64']) ++cpu_flags('android', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6']) ++cpu_flags('android', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3', ['-march=c3']) ++cpu_flags('android', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2']) ++# Sparc ++flags('android', 'OPTIONS', ['sparc/32'], ['-m32']) ++flags('android', 'OPTIONS', ['sparc/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc']) ++cpu_flags('android', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3']) ++# RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32'], ['-m32']) ++flags('android', 'OPTIONS', ['power/64'], ['-m64']) ++cpu_flags('android', 'OPTIONS', 'power', '403', ['-mcpu=403']) ++cpu_flags('android', 'OPTIONS', 'power', '505', ['-mcpu=505']) ++cpu_flags('android', 'OPTIONS', 'power', '601', ['-mcpu=601']) ++cpu_flags('android', 'OPTIONS', 'power', '602', ['-mcpu=602']) ++cpu_flags('android', 'OPTIONS', 'power', '603', ['-mcpu=603']) ++cpu_flags('android', 'OPTIONS', 'power', '603e', ['-mcpu=603e']) ++cpu_flags('android', 'OPTIONS', 'power', '604', ['-mcpu=604']) ++cpu_flags('android', 'OPTIONS', 'power', '604e', ['-mcpu=604e']) ++cpu_flags('android', 'OPTIONS', 'power', '620', ['-mcpu=620']) ++cpu_flags('android', 'OPTIONS', 'power', '630', ['-mcpu=630']) ++cpu_flags('android', 'OPTIONS', 'power', '740', ['-mcpu=740']) ++cpu_flags('android', 'OPTIONS', 'power', '7400', ['-mcpu=7400']) ++cpu_flags('android', 'OPTIONS', 'power', '7450', ['-mcpu=7450']) ++cpu_flags('android', 'OPTIONS', 'power', '750', ['-mcpu=750']) ++cpu_flags('android', 'OPTIONS', 'power', '801', ['-mcpu=801']) ++cpu_flags('android', 'OPTIONS', 'power', '821', ['-mcpu=821']) ++cpu_flags('android', 'OPTIONS', 'power', '823', ['-mcpu=823']) ++cpu_flags('android', 'OPTIONS', 'power', '860', ['-mcpu=860']) ++cpu_flags('android', 'OPTIONS', 'power', '970', ['-mcpu=970']) ++cpu_flags('android', 'OPTIONS', 'power', '8540', ['-mcpu=8540']) ++cpu_flags('android', 'OPTIONS', 'power', 'power', ['-mcpu=power']) ++cpu_flags('android', 'OPTIONS', 'power', 'power2', ['-mcpu=power2']) ++cpu_flags('android', 'OPTIONS', 'power', 'power3', ['-mcpu=power3']) ++cpu_flags('android', 'OPTIONS', 'power', 'power4', ['-mcpu=power4']) ++cpu_flags('android', 'OPTIONS', 'power', 'power5', ['-mcpu=power5']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc']) ++cpu_flags('android', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios', ['-mcpu=rios']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1']) ++cpu_flags('android', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2']) ++cpu_flags('android', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc']) ++cpu_flags('android', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64']) ++# AIX variant of RS/6000 & PowerPC ++flags('android', 'OPTIONS', ['power/32/aix'], ['-maix32']) ++flags('android', 'OPTIONS', ['power/64/aix'], ['-maix64']) ++flags('android', 'AROPTIONS', ['power/64/aix'], ['-X 64']) diff --git a/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_55_0/boost-1_55_0.patch b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_55_0/boost-1_55_0.patch new file mode 100644 index 00000000..8d0ea7df --- /dev/null +++ b/External/cpprestsdk/Build_android/build/Boost-for-Android/patches/boost-1_55_0/boost-1_55_0.patch @@ -0,0 +1,125 @@ +diff -u -r boost_1_55_0/boost/asio/detail/socket_types.hpp boost_1_55_0.patched/boost/asio/detail/socket_types.hpp +--- boost_1_55_0/boost/asio/detail/socket_types.hpp ++++ boost_1_55_0.patched/boost/asio/detail/socket_types.hpp +@@ -278,7 +278,12 @@ + typedef int socket_type; + const int invalid_socket = -1; + const int socket_error_retval = -1; ++// @Moss - Some platforms do not define it (Android) ++#if defined(INET_ADDRSTRLEN) + const int max_addr_v4_str_len = INET_ADDRSTRLEN; ++#else // defined(INET_ADDRSTRLEN) ++const int max_addr_v4_str_len = 16; ++#endif // defined(INET_ADDRSTRLEN) + #if defined(INET6_ADDRSTRLEN) + const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; + #else // defined(INET6_ADDRSTRLEN) +diff -u -r boost_1_55_0/boost/asio/ip/impl/address_v6.ipp boost_1_55_0.patched/boost/asio/ip/impl/address_v6.ipp +--- boost_1_55_0/boost/asio/ip/impl/address_v6.ipp ++++ boost_1_55_0.patched/boost/asio/ip/impl/address_v6.ipp +@@ -11,6 +11,23 @@ + #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP + ++// @Moss - Define IPv6 macros ++#if !defined(IN6_IS_ADDR_MULTICAST) ++#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_NODELOCAL) ++#define IN6_IS_ADDR_MC_NODELOCAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) ++#endif ++ ++#if !defined(IN6_IS_ADDR_MC_GLOBAL) ++#define IN6_IS_ADDR_MC_GLOBAL(a) \ ++ (IN6_IS_ADDR_MULTICAST(a) \ ++ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) ++#endif ++ + #if defined(_MSC_VER) && (_MSC_VER >= 1200) + # pragma once + #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +diff -u -r boost_1_55_0/boost/config/user.hpp boost_1_55_0.patched/boost/config/user.hpp +--- boost_1_55_0/boost/config/user.hpp ++++ boost_1_55_0.patched/boost/config/user.hpp +@@ -13,6 +13,14 @@ + // configuration policy: + // + ++// Android defines ++#define _REENTRANT 1 ++#define _GLIBCXX__PTHREADS 1 ++// There is problem with std::atomic on android (and some other platforms). ++// See this link for more info: ++// https://code.google.com/p/android/issues/detail?id=42735#makechanges ++#define BOOST_ASIO_DISABLE_STD_ATOMIC 1 ++ + // define this to locate a compiler config file: + // #define BOOST_COMPILER_CONFIG + +diff -u -r boost_1_55_0/boost/interprocess/detail/workaround.hpp boost_1_55_0.patched/boost/interprocess/detail/workaround.hpp +--- boost_1_55_0/boost/interprocess/detail/workaround.hpp 2013-09-16 19:01:45.000000000 +0200 ++++ boost_1_55_0.patched/boost/interprocess/detail/workaround.hpp 2013-11-29 17:51:33.111025389 +0100 +@@ -73,7 +73,7 @@ + #endif + + //Check for XSI shared memory objects. They are available in nearly all UNIX platforms +- #if !defined(__QNXNTO__) ++ #if !defined(__QNXNTO__) && !defined(ANDROID) && !defined(__ANDROID__) + #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + #endif + +diff -u -r boost_1_55_0/boost/predef/other/endian.h boost_1_55_0.patched/boost/predef/other/endian.h +--- boost_1_55_0/boost/predef/other/endian.h ++++ boost_1_55_0.patched/boost/predef/other/endian.h +@@ -53,7 +53,7 @@ + */ + #if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +-# if BOOST_LIB_C_GNU ++# if BOOST_LIB_C_GNU || defined(ANDROID) || defined(__ANDROID__) + # include + # else + # if BOOST_OS_MACOS +diff -u -r boost_1_55_0/libs/filesystem/src/operations.cpp boost_1_55_0.patched/libs/filesystem/src/operations.cpp +--- boost_1_55_0/libs/filesystem/src/operations.cpp ++++ boost_1_55_0.patched/libs/filesystem/src/operations.cpp +@@ -73,14 +73,14 @@ + const fs::path dot_dot_path(".."); + # include + # include +-# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) ++# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID) + # include + # define BOOST_STATVFS statvfs + # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize + # else + # ifdef __OpenBSD__ + # include +-# elif defined(__ANDROID__) ++# elif defined(__ANDROID__) || defined(ANDROID) + # include + # endif + # include +@@ -208,7 +208,19 @@ + || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) + # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) + # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) ++#if defined(__ANDROID__) || defined(ANDROID) ++ int BOOST_RESIZE_FILE(const char *path, off_t size) ++ { ++ int result = -1; ++ int fd = open(path, O_WRONLY); ++ if (fd != -1) ++ result = ftruncate(fd, size); ++ close(fd); ++ return result; ++ } ++#else + # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) ++#endif + + # define BOOST_ERROR_NOT_SUPPORTED ENOSYS + # define BOOST_ERROR_ALREADY_EXISTS EEXIST diff --git a/External/cpprestsdk/Build_android/configure.sh b/External/cpprestsdk/Build_android/configure.sh new file mode 100644 index 00000000..ed3dff15 --- /dev/null +++ b/External/cpprestsdk/Build_android/configure.sh @@ -0,0 +1,283 @@ +#!/bin/bash +# ==++== +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ==--== +# =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +# +# configure.sh +# +# Build script for casablanca on android +# +# For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk +# +# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +set -e + +# Note: we require android ndk r10e available from +# http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.tar.bz2 +# http://dl.google.com/android/ndk/android-ndk-r10e-windows-x86_64.zip + +# ----------------- +# Parse args +# ----------------- + +DO_LIBICONV=1 +DO_BOOST=1 +DO_OPENSSL=1 +DO_CPPRESTSDK=1 + +function usage { + echo "Usage: $0 [--skip-boost] [--skip-openssl] [--skip-libiconv] [--skip-cpprestsdk] [-h] [--ndk ]" + echo "" + echo " --skip-boost Skip fetching and compiling boost" + echo " --skip-openssl Skip fetching and compiling openssl" + echo " --skip-libiconv Skip fetching and compiling libiconv" + echo " --skip-cpprestsdk Skip compiling cpprestsdk" + echo " -h,--help,-? Display this information" + echo " --ndk If specified, overrides the ANDROID_NDK environment variable" +} + +while [[ $# > 0 ]] +do + case $1 in + "--skip-boost") + DO_BOOST=0 + ;; + "--skip-openssl") + DO_OPENSSL=0 + ;; + "--skip-libiconv") + DO_LIBICONV=0 + ;; + "--skip-cpprestsdk") + DO_CPPRESTSDK=0 + ;; + "-?"|"-h"|"--help") + usage + exit + ;; + "--ndk") + shift + export ANDROID_NDK=$1 + ;; + *) + usage + exit 1 + ;; + esac + shift +done + +# Variables setup + +if [ ! -e "${ANDROID_NDK}/ndk-build" ] +then + echo "ANDROID_NDK does not point to a valid NDK." + echo "(current setting: '${ANDROID_NDK}')" + exit 1 +fi +NDK_DIR=`cd "${ANDROID_NDK}" && pwd` +SRC_DIR=`pwd` + +# ----------------------- +# Identify the script dir +# ----------------------- + +# source: +# http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +if [ "$SRC_DIR" == "$DIR" ] +then + echo "You must use a separate directory for building." + echo "(try 'mkdir build; cd build; ../configure.sh')" + exit 1 +fi + +# ------- +# Openssl +# ------- + +# This steps are based on the official openssl build instructions +# http://wiki.openssl.org/index.php/Android +if [ "${DO_OPENSSL}" == "1" ] +then +( + if [ ! -d "openssl" ]; then mkdir openssl; fi + cd openssl + cp "${DIR}/openssl/Makefile" . + export ANDROID_NDK_ROOT="${NDK_DIR}" + make all +) +fi + +# -------- +# libiconv +# -------- + +# This steps are based on the blog post +# http://danilogiulianelli.blogspot.com/2012/12/how-to-cross-compile-libiconv-for.html +if [ "${DO_LIBICONV}" == "1" ] +then +( + if [ ! -e "libiconv-1.13.1.tar.gz" ] + then + wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz + fi + rm -rf libiconv + mkdir libiconv + cd libiconv + tar xzf ../libiconv-1.13.1.tar.gz + patch -b -p0 < "$DIR/libiconv/libiconv.patch" + cd libiconv-1.13.1 + ./configure + cp -r "$DIR/libiconv/jni" .. + cd ../jni + "${NDK_DIR}/ndk-build" || exit 1 + cd .. + mkdir -p armeabi-v7a/include + mkdir -p armeabi-v7a/lib + mkdir -p x86/include + mkdir -p x86/lib + cp libiconv-1.13.1/include/iconv.h armeabi-v7a/include/ + cp libiconv-1.13.1/include/iconv.h x86/include/ + cp obj/local/x86/libiconv.a x86/lib/ + cp obj/local/armeabi-v7a/libiconv.a armeabi-v7a/lib/ +) +fi + +# ----- +# Boost +# ----- +# Uses the script from MysticTreeGames + +if [ "${DO_BOOST}" == "1" ] +then +( + ( + cd Boost-for-Android + if [ ! -e "cpprestsdk.patched.stamp" ] + then + git checkout 1c95d349d5f92c5ac1c24e0ec6985272a3e3883c + git reset --hard HEAD + git apply "$DIR/boost-for-android.patch" + touch cpprestsdk.patched.stamp + fi + PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.59.0 --with-libraries=atomic,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 + ) + + ( + cd Boost-for-Android-x86 + if [ ! -e "cpprestsdk.patched.stamp" ] + then + git checkout 1c95d349d5f92c5ac1c24e0ec6985272a3e3883c + git reset --hard HEAD + git apply "$DIR/boost-for-android-x86.patch" + ln -s ../Boost-for-Android/boost_1_55_0.tar.bz2 . + touch cpprestsdk.patched.stamp + fi + PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.59.0 --with-libraries=atomic,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 + ) +) +fi + +if [ "${DO_CPPRESTSDK}" == "1" ] +then +( +# ------------- +# android-cmake +# ------------- + if [ ! -e android-cmake ] + then + git clone https://github.com/taka-no-me/android-cmake.git + fi + +# ---------- +# casablanca +# ---------- + + ( + mkdir -p build.armv7.debug + cd build.armv7.debug + cmake "$DIR/../Release/" \ + -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ + -DANDROID_ABI=armeabi-v7a \ + -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.6 \ + -DANDROID_STL=none \ + -DANDROID_STL_FORCE_FEATURES=ON \ + -DANDROID_NATIVE_API_LEVEL=android-9 \ + -DANDROID_GOLD_LINKER=OFF \ + -DCMAKE_BUILD_TYPE=Debug \ + -DANDROID_NDK="${ANDROID_NDK}" + make -j 1 + ) + + ( + mkdir -p build.armv7.release + cd build.armv7.release + cmake "$DIR/../Release/" \ + -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ + -DANDROID_ABI=armeabi-v7a \ + -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.6 \ + -DANDROID_STL=none \ + -DANDROID_STL_FORCE_FEATURES=ON \ + -DANDROID_NDK="${ANDROID_NDK}" \ + -DANDROID_NATIVE_API_LEVEL=android-9 \ + -DANDROID_GOLD_LINKER=OFF \ + -DCMAKE_BUILD_TYPE=Release + make -j 1 + ) + + ( + mkdir -p build.x86.debug + cd build.x86.debug + cmake "$DIR/../Release/" \ + -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ + -DANDROID_ABI=x86 \ + -DANDROID_TOOLCHAIN_NAME=x86-clang3.6 \ + -DANDROID_STL=none \ + -DANDROID_STL_FORCE_FEATURES=ON \ + -DANDROID_NATIVE_API_LEVEL=android-9 \ + -DANDROID_GOLD_LINKER=OFF \ + -DCMAKE_BUILD_TYPE=Debug \ + -DANDROID_NDK="${ANDROID_NDK}" + make -j 1 + ) + + ( + mkdir -p build.x86.release + cd build.x86.release + cmake "$DIR/../Release/" \ + -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ + -DANDROID_ABI=x86 \ + -DANDROID_TOOLCHAIN_NAME=x86-clang3.6 \ + -DANDROID_STL=none \ + -DANDROID_STL_FORCE_FEATURES=ON \ + -DANDROID_NDK="${ANDROID_NDK}" \ + -DANDROID_NATIVE_API_LEVEL=android-9 \ + -DANDROID_GOLD_LINKER=OFF \ + -DCMAKE_BUILD_TYPE=Release + make -j 1 + ) +) +fi diff --git a/External/cpprestsdk/Build_android/libiconv/jni/Android.mk b/External/cpprestsdk/Build_android/libiconv/jni/Android.mk new file mode 100644 index 00000000..005e604b --- /dev/null +++ b/External/cpprestsdk/Build_android/libiconv/jni/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE := iconv +LOCAL_CFLAGS := \ + -Wno-multichar \ + -D_ANDROID \ + -DLIBDIR="\"c\"" \ + -DBUILDING_LIBICONV \ + -DIN_LIBRARY \ + -Wno-static-in-inline \ + -Wno-tautological-compare \ + -Wno-parentheses-equality + +LOCAL_C_INCLUDES := \ + ${LOCAL_PATH}/../libiconv-1.13.1 \ + ${LOCAL_PATH}/../libiconv-1.13.1/include \ + ${LOCAL_PATH}/../libiconv-1.13.1/lib \ + ${LOCAL_PATH}/../libiconv-1.13.1/libcharset/include +LOCAL_SRC_FILES := \ + ../libiconv-1.13.1/lib/iconv.c \ + ../libiconv-1.13.1/lib/relocatable.c \ + ../libiconv-1.13.1/libcharset/lib/localcharset.c +include $(BUILD_STATIC_LIBRARY) diff --git a/External/cpprestsdk/Build_android/libiconv/jni/Application.mk b/External/cpprestsdk/Build_android/libiconv/jni/Application.mk new file mode 100644 index 00000000..69145d70 --- /dev/null +++ b/External/cpprestsdk/Build_android/libiconv/jni/Application.mk @@ -0,0 +1,3 @@ +NDK_TOOLCHAIN_VERSION := clang3.4 +APP_PLATFORM := android-9 +APP_ABI := armeabi-v7a x86 diff --git a/External/cpprestsdk/Build_android/libiconv/libiconv.patch b/External/cpprestsdk/Build_android/libiconv/libiconv.patch new file mode 100644 index 00000000..60b7d179 --- /dev/null +++ b/External/cpprestsdk/Build_android/libiconv/libiconv.patch @@ -0,0 +1,22 @@ +diff --ignore-file-name-case -wuprN libiconv-1.13.1.orig/libcharset/lib/localcharset.c libiconv-1.13.1/libcharset/lib/localcharset.c +--- libiconv-1.13.1.orig/libcharset/lib/localcharset.c 2009-06-21 07:17:33.000000000 -0400 ++++ libiconv-1.13.1/libcharset/lib/localcharset.c 2012-12-18 10:20:27.000000000 -0500 +@@ -44,7 +44,7 @@ + # endif + #endif + +-#if !defined WIN32_NATIVE ++#if !defined(WIN32_NATIVE) && !defined(__ANDROID__) + # if HAVE_LANGINFO_CODESET + # include + # else +@@ -328,7 +328,7 @@ locale_charset (void) + const char *codeset; + const char *aliases; + +-#if !(defined WIN32_NATIVE || defined OS2) ++#if !(defined WIN32_NATIVE || defined OS2 || defined __ANDROID__) + + # if HAVE_LANGINFO_CODESET " > iconv.patch + + $ patch -b -p0 < ./iconv.patch diff --git a/External/cpprestsdk/Build_android/openssl/Makefile b/External/cpprestsdk/Build_android/openssl/Makefile new file mode 100644 index 00000000..6859faf5 --- /dev/null +++ b/External/cpprestsdk/Build_android/openssl/Makefile @@ -0,0 +1,61 @@ +SHELL := /bin/bash +OPENSSL_VER_CATEGORY = 1.0.2 +OPENSSL_VER = openssl-1.0.2f + +all: armeabi-v7a/lib/libssl.a x86/lib/libssl.a + +clean: + rm -rf $(OPENSSL_VER) + rm -rf $(OPENSSL_VER)-armeabi-v7a + rm -rf armeabi-v7a + rm -rf setenv-android-x86.sh + +setenv-android.sh: + wget https://wiki.openssl.org/images/7/70/Setenv-android.sh + mv Setenv-android.sh setenv-android.sh + chmod a+x setenv-android.sh + +setenv-android-x86.sh: setenv-android.sh + cp setenv-android.sh setenv-android-x86.sh.tmp + sed -i -e 's/_ANDROID_EABI="arm-linux-androideabi-4.8"/_ANDROID_EABI="x86-4.8"/g' setenv-android-x86.sh.tmp + sed -i -e 's/_ANDROID_ARCH=arch-arm/_ANDROID_ARCH=arch-x86/g' setenv-android-x86.sh.tmp + mv setenv-android-x86.sh.tmp setenv-android-x86.sh + +$(OPENSSL_VER).tar.gz: + wget https://www.openssl.org/source/old/$(OPENSSL_VER_CATEGORY)/$(OPENSSL_VER).tar.gz + +armeabi-v7a/lib/libssl.a: setenv-android.sh $(OPENSSL_VER).tar.gz + [ -d "$(ANDROID_NDK_ROOT)" ] + export ANDROID_NDK_ROOT="$(ANDROID_NDK_ROOT)"; \ + . ./setenv-android.sh; \ + ( \ + set -e; \ + rm -rf $(OPENSSL_VER)/; \ + tar xzf $(OPENSSL_VER).tar.gz; \ + rm -rf $(OPENSSL_VER)-armeabi-v7a/ \ + ) && \ + mv $(OPENSSL_VER) $(OPENSSL_VER)-armeabi-v7a && \ + cd $(OPENSSL_VER)-armeabi-v7a && \ + perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org && \ + ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir="`pwd`/../armeabi-v7a" && \ + make depend && \ + make all && \ + make install CC=$${ANDROID_TOOLCHAIN}/arm-linux-androideabi-gcc RANLIB=$${ANDROID_TOOLCHAIN}/arm-linux-androideabi-ranlib + +x86/lib/libssl.a: setenv-android-x86.sh $(OPENSSL_VER).tar.gz + [ -d "$(ANDROID_NDK_ROOT)" ] + export ANDROID_NDK_ROOT="$(ANDROID_NDK_ROOT)"; \ + . ./setenv-android-x86.sh; \ + ( \ + set -e; \ + rm -rf $(OPENSSL_VER)/; \ + tar xzf $(OPENSSL_VER).tar.gz; \ + rm -rf $(OPENSSL_VER)-x86/ \ + ) && \ + mv $(OPENSSL_VER) $(OPENSSL_VER)-x86 && \ + cd $(OPENSSL_VER)-x86 && \ + perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org && \ + ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir="`pwd`/../x86" && \ + make depend && \ + make all && \ + make install CC=$${ANDROID_TOOLCHAIN}/i686-linux-android-gcc RANLIB=$${ANDROID_TOOLCHAIN}/i686-linux-android-ranlib diff --git a/External/cpprestsdk/Build_iOS/.gitignore b/External/cpprestsdk/Build_iOS/.gitignore new file mode 100644 index 00000000..525689cf --- /dev/null +++ b/External/cpprestsdk/Build_iOS/.gitignore @@ -0,0 +1,6 @@ +# iOS folders that dependencies get stored in +boostoniphone/ +boost.framework/ +ios-cmake/ +openssl/ +OpenSSL-for-iPhone/ \ No newline at end of file diff --git a/External/cpprestsdk/Build_iOS/CMakeLists.txt b/External/cpprestsdk/Build_iOS/CMakeLists.txt new file mode 100644 index 00000000..624197a2 --- /dev/null +++ b/External/cpprestsdk/Build_iOS/CMakeLists.txt @@ -0,0 +1,179 @@ +<<<<<<< HEAD +project(casablanca-ios NONE) +cmake_minimum_required(VERSION 2.6) + +enable_testing() + +set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ios-cmake/toolchain/iOS.cmake") + +set(SIM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.i386" CACHE INTERNAL "") +set(SIM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") + +set(ARM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.arm" CACHE INTERNAL "") +set(ARM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") +add_test(NAME ios_runner + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../Release/tests/common/testrunner/ios + COMMAND xcodebuild test -project ios_runner.xcodeproj -configuration=${CMAKE_BUILD_TYPE} -scheme ios_runner -destination "platform=iOS Simulator,name=iPhone 6" LIBRARY_SEARCH_PATH=${SIM_BINARY_DIR} + ) + +file(MAKE_DIRECTORY ${SIM_BINARY_DIR}) +execute_process(WORKING_DIRECTORY ${SIM_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} + -GXcode + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} + -DIOS_PLATFORM=SIMULATOR + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + "${SIM_SOURCE_DIR}" + ) + +file(MAKE_DIRECTORY ${ARM_BINARY_DIR}) +execute_process(WORKING_DIRECTORY ${ARM_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} + -GXcode + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} + -DIOS_PLATFORM=OS + "-DCMAKE_OSX_ARCHITECTURES=armv7s;armv7;arm64" + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + "${ARM_SOURCE_DIR}" + ) + + +## Simulator version +add_custom_target(sim + COMMAND ${CMAKE_COMMAND} + --build ${SIM_BINARY_DIR} + --config ${CMAKE_BUILD_TYPE} + COMMENT "Building for i386 (simulator)" + VERBATIM +) + +## ARM version +add_custom_target(arm + COMMAND ${CMAKE_COMMAND} + --build ${ARM_BINARY_DIR} + --config ${CMAKE_BUILD_TYPE} + COMMENT "Building for armv7, armv7s, arm64" + VERBATIM +) + +set(LIB_CPPREST libcpprest.a) +add_custom_command( + OUTPUT ${LIB_CPPREST} + COMMAND lipo -create + -output "${CMAKE_CURRENT_BINARY_DIR}/${LIB_CPPREST}" + ${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} + ${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} + DEPENDS + sim + arm + "${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + "${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + VERBATIM +) + +add_custom_target(cpprest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIB_CPPREST}) +======= +project(casablanca-ios NONE) +cmake_minimum_required(VERSION 2.6) + +enable_testing() + +set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ios-cmake/toolchain/iOS.cmake") + +set(SIM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.i386" CACHE INTERNAL "") +set(SIM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") + +set(SIM64_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.x86_64" CACHE INTERNAL "") +set(SIM64_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") + +set(ARM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.arm" CACHE INTERNAL "") +set(ARM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") +add_test(NAME ios_runner + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../Release/tests/common/testrunner/ios + COMMAND xcodebuild test -project ios_runner.xcodeproj -configuration=${CMAKE_BUILD_TYPE} -scheme ios_runner -destination "platform=iOS Simulator,name=iPhone 6" LIBRARY_SEARCH_PATH=${SIM_BINARY_DIR} + ) + +file(MAKE_DIRECTORY ${SIM_BINARY_DIR}) +execute_process(WORKING_DIRECTORY ${SIM_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} + -GXcode + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} + -DIOS_PLATFORM=SIMULATOR + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_C_COMPILER=${CLANG_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CLANG_CXX_COMPILER} + "${SIM_SOURCE_DIR}" + ) + +file(MAKE_DIRECTORY ${SIM64_BINARY_DIR}) +execute_process(WORKING_DIRECTORY ${SIM64_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} + -GXcode + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} + -DIOS_PLATFORM=SIMULATOR64 + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_C_COMPILER=${CLANG_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CLANG_CXX_COMPILER} + "${SIM64_SOURCE_DIR}" +) + +file(MAKE_DIRECTORY ${ARM_BINARY_DIR}) +execute_process(WORKING_DIRECTORY ${ARM_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} + -GXcode + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} + -DIOS_PLATFORM=OS + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_C_COMPILER=${CLANG_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CLANG_CXX_COMPILER} + "${ARM_SOURCE_DIR}" + ) + + +## Simulator i386 version +add_custom_target(sim + COMMAND ${CMAKE_COMMAND} + --build ${SIM_BINARY_DIR} + --config ${CMAKE_BUILD_TYPE} + COMMENT "Building for i386 (simulator)" + VERBATIM +) + +## Simulator x86_64 version +add_custom_target(sim64 + COMMAND ${CMAKE_COMMAND} + --build ${SIM64_BINARY_DIR} + --config ${CMAKE_BUILD_TYPE} + COMMENT "Building for x86_64 (simulator)" +VERBATIM +) + +## ARM version +add_custom_target(arm + COMMAND ${CMAKE_COMMAND} + --build ${ARM_BINARY_DIR} + --config ${CMAKE_BUILD_TYPE} + COMMENT "Building for armv7, armv7s, arm64" + VERBATIM +) + +set(LIB_CPPREST libcpprest.a) +add_custom_command( + OUTPUT ${LIB_CPPREST} + COMMAND lipo -create + -output "${CMAKE_CURRENT_BINARY_DIR}/${LIB_CPPREST}" + ${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} + ${SIM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} + ${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} + DEPENDS + sim + sim64 + arm + "${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + "${SIM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + "${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + VERBATIM +) + +add_custom_target(cpprest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIB_CPPREST}) +>>>>>>> master diff --git a/External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.pbxproj b/External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.pbxproj new file mode 100644 index 00000000..eeb925f4 --- /dev/null +++ b/External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.pbxproj @@ -0,0 +1,636 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9B97BC1F1BE2D08200CF1E29 /* http_client_asio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBEB1BE2D08200CF1E29 /* http_client_asio.cpp */; }; + 9B97BC201BE2D08200CF1E29 /* http_client_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBEC1BE2D08200CF1E29 /* http_client_msg.cpp */; }; + 9B97BC231BE2D08200CF1E29 /* x509_cert_utilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBEF1BE2D08200CF1E29 /* x509_cert_utilities.cpp */; }; + 9B97BC251BE2D08200CF1E29 /* x509_cert_utilities_apple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBF11BE2D08200CF1E29 /* x509_cert_utilities_apple.cpp */; }; + 9B97BC271BE2D08200CF1E29 /* http_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBF41BE2D08200CF1E29 /* http_helpers.cpp */; }; + 9B97BC281BE2D08200CF1E29 /* http_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBF51BE2D08200CF1E29 /* http_msg.cpp */; }; + 9B97BC291BE2D08200CF1E29 /* http_listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBF71BE2D08200CF1E29 /* http_listener.cpp */; }; + 9B97BC2A1BE2D08200CF1E29 /* http_listener_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBF81BE2D08200CF1E29 /* http_listener_msg.cpp */; }; + 9B97BC2B1BE2D08200CF1E29 /* http_server_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBF91BE2D08200CF1E29 /* http_server_api.cpp */; }; + 9B97BC2C1BE2D08200CF1E29 /* http_server_asio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBFA1BE2D08200CF1E29 /* http_server_asio.cpp */; }; + 9B97BC2E1BE2D08200CF1E29 /* oauth1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBFD1BE2D08200CF1E29 /* oauth1.cpp */; }; + 9B97BC2F1BE2D08200CF1E29 /* oauth2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BBFE1BE2D08200CF1E29 /* oauth2.cpp */; }; + 9B97BC301BE2D08200CF1E29 /* json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC001BE2D08200CF1E29 /* json.cpp */; }; + 9B97BC311BE2D08200CF1E29 /* json_parsing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC011BE2D08200CF1E29 /* json_parsing.cpp */; }; + 9B97BC321BE2D08200CF1E29 /* json_serialization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC021BE2D08200CF1E29 /* json_serialization.cpp */; }; + 9B97BC331BE2D08200CF1E29 /* stdafx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC041BE2D08200CF1E29 /* stdafx.cpp */; }; + 9B97BC341BE2D08200CF1E29 /* pplx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC071BE2D08200CF1E29 /* pplx.cpp */; }; + 9B97BC351BE2D08200CF1E29 /* pplxapple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC081BE2D08200CF1E29 /* pplxapple.cpp */; }; + 9B97BC381BE2D08200CF1E29 /* threadpool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC0B1BE2D08200CF1E29 /* threadpool.cpp */; }; + 9B97BC391BE2D08200CF1E29 /* fileio_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC0D1BE2D08200CF1E29 /* fileio_posix.cpp */; }; + 9B97BC3C1BE2D08200CF1E29 /* uri.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC111BE2D08200CF1E29 /* uri.cpp */; }; + 9B97BC3D1BE2D08200CF1E29 /* uri_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC121BE2D08200CF1E29 /* uri_builder.cpp */; }; + 9B97BC3E1BE2D08200CF1E29 /* uri_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC131BE2D08200CF1E29 /* uri_parser.cpp */; }; + 9B97BC3F1BE2D08200CF1E29 /* asyncrt_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC151BE2D08200CF1E29 /* asyncrt_utils.cpp */; }; + 9B97BC401BE2D08200CF1E29 /* base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC161BE2D08200CF1E29 /* base64.cpp */; }; + 9B97BC411BE2D08200CF1E29 /* web_utilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC181BE2D08200CF1E29 /* web_utilities.cpp */; }; + 9B97BC421BE2D08200CF1E29 /* ws_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC1B1BE2D08200CF1E29 /* ws_client.cpp */; }; + 9B97BC441BE2D08200CF1E29 /* ws_client_wspp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC1D1BE2D08200CF1E29 /* ws_client_wspp.cpp */; }; + 9B97BC451BE2D08200CF1E29 /* ws_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B97BC1E1BE2D08200CF1E29 /* ws_msg.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9B97BADF1BE29EAF00CF1E29 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 9B97BAE11BE29EAF00CF1E29 /* libCasablanca.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCasablanca.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 9B97BB7E1BE2D06E00CF1E29 /* astreambuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = astreambuf.h; sourceTree = ""; }; + 9B97BB7F1BE2D06E00CF1E29 /* asyncrt_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asyncrt_utils.h; sourceTree = ""; }; + 9B97BB801BE2D06E00CF1E29 /* base_uri.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_uri.h; sourceTree = ""; }; + 9B97BB811BE2D06E00CF1E29 /* containerstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = containerstream.h; sourceTree = ""; }; + 9B97BB831BE2D06E00CF1E29 /* basic_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = basic_types.h; sourceTree = ""; }; + 9B97BB841BE2D06E00CF1E29 /* cpprest_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpprest_compat.h; sourceTree = ""; }; + 9B97BB851BE2D06E00CF1E29 /* fileio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileio.h; sourceTree = ""; }; + 9B97BB861BE2D06E00CF1E29 /* http_client_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_client_impl.h; sourceTree = ""; }; + 9B97BB871BE2D06E00CF1E29 /* http_constants.dat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = http_constants.dat; sourceTree = ""; }; + 9B97BB881BE2D06E00CF1E29 /* http_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_helpers.h; sourceTree = ""; }; + 9B97BB891BE2D06E00CF1E29 /* http_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_server.h; sourceTree = ""; }; + 9B97BB8A1BE2D06E00CF1E29 /* http_server_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_server_api.h; sourceTree = ""; }; + 9B97BB8B1BE2D06E00CF1E29 /* http_server_asio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_server_asio.h; sourceTree = ""; }; + 9B97BB8C1BE2D06E00CF1E29 /* http_server_httpsys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_server_httpsys.h; sourceTree = ""; }; + 9B97BB8D1BE2D06E00CF1E29 /* nosal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nosal.h; sourceTree = ""; }; + 9B97BB8E1BE2D06E00CF1E29 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; + 9B97BB8F1BE2D06E00CF1E29 /* SafeInt3.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SafeInt3.hpp; sourceTree = ""; }; + 9B97BB901BE2D06E00CF1E29 /* uri_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uri_parser.h; sourceTree = ""; }; + 9B97BB911BE2D06E00CF1E29 /* web_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = web_utilities.h; sourceTree = ""; }; + 9B97BB921BE2D06E00CF1E29 /* x509_cert_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509_cert_utilities.h; sourceTree = ""; }; + 9B97BB931BE2D06E00CF1E29 /* filestream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filestream.h; sourceTree = ""; }; + 9B97BB941BE2D06E00CF1E29 /* http_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_client.h; sourceTree = ""; }; + 9B97BB951BE2D06E00CF1E29 /* http_headers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_headers.h; sourceTree = ""; }; + 9B97BB961BE2D06E00CF1E29 /* http_listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_listener.h; sourceTree = ""; }; + 9B97BB971BE2D06E00CF1E29 /* http_msg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_msg.h; sourceTree = ""; }; + 9B97BB981BE2D06E00CF1E29 /* interopstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interopstream.h; sourceTree = ""; }; + 9B97BB991BE2D06E00CF1E29 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = ""; }; + 9B97BB9A1BE2D06E00CF1E29 /* oauth1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oauth1.h; sourceTree = ""; }; + 9B97BB9B1BE2D06E00CF1E29 /* oauth2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oauth2.h; sourceTree = ""; }; + 9B97BB9C1BE2D06E00CF1E29 /* producerconsumerstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = producerconsumerstream.h; sourceTree = ""; }; + 9B97BB9D1BE2D06E00CF1E29 /* rawptrstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rawptrstream.h; sourceTree = ""; }; + 9B97BB9E1BE2D06E00CF1E29 /* streams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streams.h; sourceTree = ""; }; + 9B97BB9F1BE2D06E00CF1E29 /* uri.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uri.h; sourceTree = ""; }; + 9B97BBA01BE2D06E00CF1E29 /* uri_builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uri_builder.h; sourceTree = ""; }; + 9B97BBA11BE2D06E00CF1E29 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; + 9B97BBA21BE2D06E00CF1E29 /* ws_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ws_client.h; sourceTree = ""; }; + 9B97BBA31BE2D06E00CF1E29 /* ws_msg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ws_msg.h; sourceTree = ""; }; + 9B97BBA51BE2D06E00CF1E29 /* pplx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplx.h; sourceTree = ""; }; + 9B97BBA61BE2D06E00CF1E29 /* pplxcancellation_token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplxcancellation_token.h; sourceTree = ""; }; + 9B97BBA71BE2D06E00CF1E29 /* pplxconv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplxconv.h; sourceTree = ""; }; + 9B97BBA81BE2D06E00CF1E29 /* pplxinterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplxinterface.h; sourceTree = ""; }; + 9B97BBA91BE2D06E00CF1E29 /* pplxlinux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplxlinux.h; sourceTree = ""; }; + 9B97BBAA1BE2D06E00CF1E29 /* pplxtasks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplxtasks.h; sourceTree = ""; }; + 9B97BBAB1BE2D06E00CF1E29 /* pplxwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pplxwin.h; sourceTree = ""; }; + 9B97BBAC1BE2D06E00CF1E29 /* threadpool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threadpool.h; sourceTree = ""; }; + 9B97BBEB1BE2D08200CF1E29 /* http_client_asio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_client_asio.cpp; sourceTree = ""; }; + 9B97BBEC1BE2D08200CF1E29 /* http_client_msg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_client_msg.cpp; sourceTree = ""; }; + 9B97BBEF1BE2D08200CF1E29 /* x509_cert_utilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x509_cert_utilities.cpp; sourceTree = ""; }; + 9B97BBF11BE2D08200CF1E29 /* x509_cert_utilities_apple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x509_cert_utilities_apple.cpp; sourceTree = ""; }; + 9B97BBF41BE2D08200CF1E29 /* http_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_helpers.cpp; sourceTree = ""; }; + 9B97BBF51BE2D08200CF1E29 /* http_msg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_msg.cpp; sourceTree = ""; }; + 9B97BBF71BE2D08200CF1E29 /* http_listener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_listener.cpp; sourceTree = ""; }; + 9B97BBF81BE2D08200CF1E29 /* http_listener_msg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_listener_msg.cpp; sourceTree = ""; }; + 9B97BBF91BE2D08200CF1E29 /* http_server_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_server_api.cpp; sourceTree = ""; }; + 9B97BBFA1BE2D08200CF1E29 /* http_server_asio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_server_asio.cpp; sourceTree = ""; }; + 9B97BBFD1BE2D08200CF1E29 /* oauth1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oauth1.cpp; sourceTree = ""; }; + 9B97BBFE1BE2D08200CF1E29 /* oauth2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oauth2.cpp; sourceTree = ""; }; + 9B97BC001BE2D08200CF1E29 /* json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json.cpp; sourceTree = ""; }; + 9B97BC011BE2D08200CF1E29 /* json_parsing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_parsing.cpp; sourceTree = ""; }; + 9B97BC021BE2D08200CF1E29 /* json_serialization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_serialization.cpp; sourceTree = ""; }; + 9B97BC041BE2D08200CF1E29 /* stdafx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stdafx.cpp; sourceTree = ""; }; + 9B97BC051BE2D08200CF1E29 /* stdafx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdafx.h; sourceTree = ""; }; + 9B97BC071BE2D08200CF1E29 /* pplx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pplx.cpp; sourceTree = ""; }; + 9B97BC081BE2D08200CF1E29 /* pplxapple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pplxapple.cpp; sourceTree = ""; }; + 9B97BC0B1BE2D08200CF1E29 /* threadpool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = threadpool.cpp; sourceTree = ""; }; + 9B97BC0D1BE2D08200CF1E29 /* fileio_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fileio_posix.cpp; sourceTree = ""; }; + 9B97BC111BE2D08200CF1E29 /* uri.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uri.cpp; sourceTree = ""; }; + 9B97BC121BE2D08200CF1E29 /* uri_builder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uri_builder.cpp; sourceTree = ""; }; + 9B97BC131BE2D08200CF1E29 /* uri_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uri_parser.cpp; sourceTree = ""; }; + 9B97BC151BE2D08200CF1E29 /* asyncrt_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = asyncrt_utils.cpp; sourceTree = ""; }; + 9B97BC161BE2D08200CF1E29 /* base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base64.cpp; sourceTree = ""; }; + 9B97BC171BE2D08200CF1E29 /* Resource.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Resource.rc; sourceTree = ""; }; + 9B97BC181BE2D08200CF1E29 /* web_utilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = web_utilities.cpp; sourceTree = ""; }; + 9B97BC1B1BE2D08200CF1E29 /* ws_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ws_client.cpp; sourceTree = ""; }; + 9B97BC1D1BE2D08200CF1E29 /* ws_client_wspp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ws_client_wspp.cpp; sourceTree = ""; }; + 9B97BC1E1BE2D08200CF1E29 /* ws_msg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ws_msg.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9B97BADE1BE29EAF00CF1E29 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9B97BAD81BE29EAF00CF1E29 = { + isa = PBXGroup; + children = ( + 9B97BB7C1BE2D06E00CF1E29 /* include */, + 9B97BBAD1BE2D08100CF1E29 /* src */, + 9B97BAE21BE29EAF00CF1E29 /* Products */, + ); + sourceTree = ""; + }; + 9B97BAE21BE29EAF00CF1E29 /* Products */ = { + isa = PBXGroup; + children = ( + 9B97BAE11BE29EAF00CF1E29 /* libCasablanca.a */, + ); + name = Products; + sourceTree = ""; + }; + 9B97BB7C1BE2D06E00CF1E29 /* include */ = { + isa = PBXGroup; + children = ( + 9B97BB7D1BE2D06E00CF1E29 /* cpprest */, + 9B97BBA41BE2D06E00CF1E29 /* pplx */, + ); + name = include; + path = ../Release/include; + sourceTree = ""; + }; + 9B97BB7D1BE2D06E00CF1E29 /* cpprest */ = { + isa = PBXGroup; + children = ( + 9B97BB7E1BE2D06E00CF1E29 /* astreambuf.h */, + 9B97BB7F1BE2D06E00CF1E29 /* asyncrt_utils.h */, + 9B97BB801BE2D06E00CF1E29 /* base_uri.h */, + 9B97BB811BE2D06E00CF1E29 /* containerstream.h */, + 9B97BB821BE2D06E00CF1E29 /* details */, + 9B97BB931BE2D06E00CF1E29 /* filestream.h */, + 9B97BB941BE2D06E00CF1E29 /* http_client.h */, + 9B97BB951BE2D06E00CF1E29 /* http_headers.h */, + 9B97BB961BE2D06E00CF1E29 /* http_listener.h */, + 9B97BB971BE2D06E00CF1E29 /* http_msg.h */, + 9B97BB981BE2D06E00CF1E29 /* interopstream.h */, + 9B97BB991BE2D06E00CF1E29 /* json.h */, + 9B97BB9A1BE2D06E00CF1E29 /* oauth1.h */, + 9B97BB9B1BE2D06E00CF1E29 /* oauth2.h */, + 9B97BB9C1BE2D06E00CF1E29 /* producerconsumerstream.h */, + 9B97BB9D1BE2D06E00CF1E29 /* rawptrstream.h */, + 9B97BB9E1BE2D06E00CF1E29 /* streams.h */, + 9B97BB9F1BE2D06E00CF1E29 /* uri.h */, + 9B97BBA01BE2D06E00CF1E29 /* uri_builder.h */, + 9B97BBA11BE2D06E00CF1E29 /* version.h */, + 9B97BBA21BE2D06E00CF1E29 /* ws_client.h */, + 9B97BBA31BE2D06E00CF1E29 /* ws_msg.h */, + ); + path = cpprest; + sourceTree = ""; + }; + 9B97BB821BE2D06E00CF1E29 /* details */ = { + isa = PBXGroup; + children = ( + 9B97BB831BE2D06E00CF1E29 /* basic_types.h */, + 9B97BB841BE2D06E00CF1E29 /* cpprest_compat.h */, + 9B97BB851BE2D06E00CF1E29 /* fileio.h */, + 9B97BB861BE2D06E00CF1E29 /* http_client_impl.h */, + 9B97BB871BE2D06E00CF1E29 /* http_constants.dat */, + 9B97BB881BE2D06E00CF1E29 /* http_helpers.h */, + 9B97BB891BE2D06E00CF1E29 /* http_server.h */, + 9B97BB8A1BE2D06E00CF1E29 /* http_server_api.h */, + 9B97BB8B1BE2D06E00CF1E29 /* http_server_asio.h */, + 9B97BB8C1BE2D06E00CF1E29 /* http_server_httpsys.h */, + 9B97BB8D1BE2D06E00CF1E29 /* nosal.h */, + 9B97BB8E1BE2D06E00CF1E29 /* resource.h */, + 9B97BB8F1BE2D06E00CF1E29 /* SafeInt3.hpp */, + 9B97BB901BE2D06E00CF1E29 /* uri_parser.h */, + 9B97BB911BE2D06E00CF1E29 /* web_utilities.h */, + 9B97BB921BE2D06E00CF1E29 /* x509_cert_utilities.h */, + ); + path = details; + sourceTree = ""; + }; + 9B97BBA41BE2D06E00CF1E29 /* pplx */ = { + isa = PBXGroup; + children = ( + 9B97BBA51BE2D06E00CF1E29 /* pplx.h */, + 9B97BBA61BE2D06E00CF1E29 /* pplxcancellation_token.h */, + 9B97BBA71BE2D06E00CF1E29 /* pplxconv.h */, + 9B97BBA81BE2D06E00CF1E29 /* pplxinterface.h */, + 9B97BBA91BE2D06E00CF1E29 /* pplxlinux.h */, + 9B97BBAA1BE2D06E00CF1E29 /* pplxtasks.h */, + 9B97BBAB1BE2D06E00CF1E29 /* pplxwin.h */, + 9B97BBAC1BE2D06E00CF1E29 /* threadpool.h */, + ); + path = pplx; + sourceTree = ""; + }; + 9B97BBAD1BE2D08100CF1E29 /* src */ = { + isa = PBXGroup; + children = ( + 9B97BBE91BE2D08200CF1E29 /* http */, + 9B97BBFF1BE2D08200CF1E29 /* json */, + 9B97BC031BE2D08200CF1E29 /* pch */, + 9B97BC061BE2D08200CF1E29 /* pplx */, + 9B97BC0C1BE2D08200CF1E29 /* streams */, + 9B97BC101BE2D08200CF1E29 /* uri */, + 9B97BC141BE2D08200CF1E29 /* utilities */, + 9B97BC191BE2D08200CF1E29 /* websockets */, + ); + name = src; + path = ../Release/src; + sourceTree = ""; + }; + 9B97BBE91BE2D08200CF1E29 /* http */ = { + isa = PBXGroup; + children = ( + 9B97BBEA1BE2D08200CF1E29 /* client */, + 9B97BBF31BE2D08200CF1E29 /* common */, + 9B97BBF61BE2D08200CF1E29 /* listener */, + 9B97BBFC1BE2D08200CF1E29 /* oauth */, + ); + path = http; + sourceTree = ""; + }; + 9B97BBEA1BE2D08200CF1E29 /* client */ = { + isa = PBXGroup; + children = ( + 9B97BBEB1BE2D08200CF1E29 /* http_client_asio.cpp */, + 9B97BBEC1BE2D08200CF1E29 /* http_client_msg.cpp */, + 9B97BBEF1BE2D08200CF1E29 /* x509_cert_utilities.cpp */, + 9B97BBF11BE2D08200CF1E29 /* x509_cert_utilities_apple.cpp */, + ); + path = client; + sourceTree = ""; + }; + 9B97BBF31BE2D08200CF1E29 /* common */ = { + isa = PBXGroup; + children = ( + 9B97BBF41BE2D08200CF1E29 /* http_helpers.cpp */, + 9B97BBF51BE2D08200CF1E29 /* http_msg.cpp */, + ); + path = common; + sourceTree = ""; + }; + 9B97BBF61BE2D08200CF1E29 /* listener */ = { + isa = PBXGroup; + children = ( + 9B97BBF71BE2D08200CF1E29 /* http_listener.cpp */, + 9B97BBF81BE2D08200CF1E29 /* http_listener_msg.cpp */, + 9B97BBF91BE2D08200CF1E29 /* http_server_api.cpp */, + 9B97BBFA1BE2D08200CF1E29 /* http_server_asio.cpp */, + ); + path = listener; + sourceTree = ""; + }; + 9B97BBFC1BE2D08200CF1E29 /* oauth */ = { + isa = PBXGroup; + children = ( + 9B97BBFD1BE2D08200CF1E29 /* oauth1.cpp */, + 9B97BBFE1BE2D08200CF1E29 /* oauth2.cpp */, + ); + path = oauth; + sourceTree = ""; + }; + 9B97BBFF1BE2D08200CF1E29 /* json */ = { + isa = PBXGroup; + children = ( + 9B97BC001BE2D08200CF1E29 /* json.cpp */, + 9B97BC011BE2D08200CF1E29 /* json_parsing.cpp */, + 9B97BC021BE2D08200CF1E29 /* json_serialization.cpp */, + ); + path = json; + sourceTree = ""; + }; + 9B97BC031BE2D08200CF1E29 /* pch */ = { + isa = PBXGroup; + children = ( + 9B97BC041BE2D08200CF1E29 /* stdafx.cpp */, + 9B97BC051BE2D08200CF1E29 /* stdafx.h */, + ); + path = pch; + sourceTree = ""; + }; + 9B97BC061BE2D08200CF1E29 /* pplx */ = { + isa = PBXGroup; + children = ( + 9B97BC071BE2D08200CF1E29 /* pplx.cpp */, + 9B97BC081BE2D08200CF1E29 /* pplxapple.cpp */, + 9B97BC0B1BE2D08200CF1E29 /* threadpool.cpp */, + ); + path = pplx; + sourceTree = ""; + }; + 9B97BC0C1BE2D08200CF1E29 /* streams */ = { + isa = PBXGroup; + children = ( + 9B97BC0D1BE2D08200CF1E29 /* fileio_posix.cpp */, + ); + path = streams; + sourceTree = ""; + }; + 9B97BC101BE2D08200CF1E29 /* uri */ = { + isa = PBXGroup; + children = ( + 9B97BC111BE2D08200CF1E29 /* uri.cpp */, + 9B97BC121BE2D08200CF1E29 /* uri_builder.cpp */, + 9B97BC131BE2D08200CF1E29 /* uri_parser.cpp */, + ); + path = uri; + sourceTree = ""; + }; + 9B97BC141BE2D08200CF1E29 /* utilities */ = { + isa = PBXGroup; + children = ( + 9B97BC151BE2D08200CF1E29 /* asyncrt_utils.cpp */, + 9B97BC161BE2D08200CF1E29 /* base64.cpp */, + 9B97BC171BE2D08200CF1E29 /* Resource.rc */, + 9B97BC181BE2D08200CF1E29 /* web_utilities.cpp */, + ); + path = utilities; + sourceTree = ""; + }; + 9B97BC191BE2D08200CF1E29 /* websockets */ = { + isa = PBXGroup; + children = ( + 9B97BC1A1BE2D08200CF1E29 /* client */, + ); + path = websockets; + sourceTree = ""; + }; + 9B97BC1A1BE2D08200CF1E29 /* client */ = { + isa = PBXGroup; + children = ( + 9B97BC1B1BE2D08200CF1E29 /* ws_client.cpp */, + 9B97BC1D1BE2D08200CF1E29 /* ws_client_wspp.cpp */, + 9B97BC1E1BE2D08200CF1E29 /* ws_msg.cpp */, + ); + path = client; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9B97BAE01BE29EAF00CF1E29 /* Casablanca */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9B97BAEA1BE29EAF00CF1E29 /* Build configuration list for PBXNativeTarget "Casablanca" */; + buildPhases = ( + 9B97BADD1BE29EAF00CF1E29 /* Sources */, + 9B97BADE1BE29EAF00CF1E29 /* Frameworks */, + 9B97BADF1BE29EAF00CF1E29 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Casablanca; + productName = Casablanca; + productReference = 9B97BAE11BE29EAF00CF1E29 /* libCasablanca.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9B97BAD91BE29EAF00CF1E29 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = "Microsoft Corporation"; + TargetAttributes = { + 9B97BAE01BE29EAF00CF1E29 = { + CreatedOnToolsVersion = 7.1; + }; + }; + }; + buildConfigurationList = 9B97BADC1BE29EAF00CF1E29 /* Build configuration list for PBXProject "Casablanca" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 9B97BAD81BE29EAF00CF1E29; + productRefGroup = 9B97BAE21BE29EAF00CF1E29 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9B97BAE01BE29EAF00CF1E29 /* Casablanca */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 9B97BADD1BE29EAF00CF1E29 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B97BC441BE2D08200CF1E29 /* ws_client_wspp.cpp in Sources */, + 9B97BC401BE2D08200CF1E29 /* base64.cpp in Sources */, + 9B97BC2F1BE2D08200CF1E29 /* oauth2.cpp in Sources */, + 9B97BC421BE2D08200CF1E29 /* ws_client.cpp in Sources */, + 9B97BC391BE2D08200CF1E29 /* fileio_posix.cpp in Sources */, + 9B97BC201BE2D08200CF1E29 /* http_client_msg.cpp in Sources */, + 9B97BC1F1BE2D08200CF1E29 /* http_client_asio.cpp in Sources */, + 9B97BC341BE2D08200CF1E29 /* pplx.cpp in Sources */, + 9B97BC3F1BE2D08200CF1E29 /* asyncrt_utils.cpp in Sources */, + 9B97BC311BE2D08200CF1E29 /* json_parsing.cpp in Sources */, + 9B97BC2C1BE2D08200CF1E29 /* http_server_asio.cpp in Sources */, + 9B97BC281BE2D08200CF1E29 /* http_msg.cpp in Sources */, + 9B97BC411BE2D08200CF1E29 /* web_utilities.cpp in Sources */, + 9B97BC251BE2D08200CF1E29 /* x509_cert_utilities_apple.cpp in Sources */, + 9B97BC321BE2D08200CF1E29 /* json_serialization.cpp in Sources */, + 9B97BC271BE2D08200CF1E29 /* http_helpers.cpp in Sources */, + 9B97BC331BE2D08200CF1E29 /* stdafx.cpp in Sources */, + 9B97BC291BE2D08200CF1E29 /* http_listener.cpp in Sources */, + 9B97BC301BE2D08200CF1E29 /* json.cpp in Sources */, + 9B97BC451BE2D08200CF1E29 /* ws_msg.cpp in Sources */, + 9B97BC2A1BE2D08200CF1E29 /* http_listener_msg.cpp in Sources */, + 9B97BC381BE2D08200CF1E29 /* threadpool.cpp in Sources */, + 9B97BC2B1BE2D08200CF1E29 /* http_server_api.cpp in Sources */, + 9B97BC3C1BE2D08200CF1E29 /* uri.cpp in Sources */, + 9B97BC2E1BE2D08200CF1E29 /* oauth1.cpp in Sources */, + 9B97BC3E1BE2D08200CF1E29 /* uri_parser.cpp in Sources */, + 9B97BC231BE2D08200CF1E29 /* x509_cert_utilities.cpp in Sources */, + 9B97BC3D1BE2D08200CF1E29 /* uri_builder.cpp in Sources */, + 9B97BC351BE2D08200CF1E29 /* pplxapple.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 9B97BAE81BE29EAF00CF1E29 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = i386; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 9B97BAE91BE29EAF00CF1E29 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = i386; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9B97BAEB1BE29EAF00CF1E29 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + COPY_PHASE_STRIP = YES; + DEPLOYMENT_POSTPROCESSING = YES; + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = ( + "${SRCROOT}/../Release/include/", + "$(SRCROOT)/../../External/OpenSSL/include", + "${SRCROOT}/../Release/libs/websocketpp/", + "$(SRCROOT)/../../External/Boost/include", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LIBRARY_SEARCH_PATHS = ( + "$(SRCROOT)/../../External/OpenSSL/iOS/lib/", + "$(SRCROOT)/../../External/Boost/iOS/lib", + ); + ONLY_ACTIVE_ARCH = NO; + OTHER_CFLAGS = ""; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + VALID_ARCHS = "arm64 armv7 armv7s"; + }; + name = Debug; + }; + 9B97BAEC1BE29EAF00CF1E29 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + COPY_PHASE_STRIP = YES; + DEPLOYMENT_POSTPROCESSING = YES; + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = ( + "${SRCROOT}/../Release/include/", + "$(SRCROOT)/../../External/OpenSSL/include", + "${SRCROOT}/../Release/libs/websocketpp/", + "$(SRCROOT)/../../External/Boost/include", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LIBRARY_SEARCH_PATHS = ( + "$(SRCROOT)/../../External/OpenSSL/iOS/lib/", + "$(SRCROOT)/../../External/Boost/iOS/lib", + ); + ONLY_ACTIVE_ARCH = NO; + OTHER_CFLAGS = ""; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + VALID_ARCHS = "arm64 armv7 armv7s"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9B97BADC1BE29EAF00CF1E29 /* Build configuration list for PBXProject "Casablanca" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B97BAE81BE29EAF00CF1E29 /* Debug */, + 9B97BAE91BE29EAF00CF1E29 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9B97BAEA1BE29EAF00CF1E29 /* Build configuration list for PBXNativeTarget "Casablanca" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B97BAEB1BE29EAF00CF1E29 /* Debug */, + 9B97BAEC1BE29EAF00CF1E29 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9B97BAD91BE29EAF00CF1E29 /* Project object */; +} diff --git a/External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..a7a746fb --- /dev/null +++ b/External/cpprestsdk/Build_iOS/Casablanca.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/External/cpprestsdk/Build_iOS/README.md b/External/cpprestsdk/Build_iOS/README.md new file mode 100644 index 00000000..a5c58cc9 --- /dev/null +++ b/External/cpprestsdk/Build_iOS/README.md @@ -0,0 +1 @@ +Please consult the documentation [here](https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-iOS) for iOS compilation. diff --git a/External/cpprestsdk/Build_iOS/configure.sh b/External/cpprestsdk/Build_iOS/configure.sh new file mode 100644 index 00000000..8c9c9eaf --- /dev/null +++ b/External/cpprestsdk/Build_iOS/configure.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +git clone https://gist.github.com/c629ae4c7168216a9856.git boostoniphone +pushd boostoniphone +git apply ../fix_boost_version.patch +./boost.sh +popd +mv boostoniphone/ios/framework/boost.framework . + +git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git +pushd OpenSSL-for-iPhone +./build-libssl.sh +popd +mkdir -p openssl/lib +cp -r OpenSSL-for-iPhone/bin/iPhoneOS8.2-armv7.sdk/include openssl +cp OpenSSL-for-iPhone/include/LICENSE openssl +lipo -create -output openssl/lib/libssl.a OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a +lipo -create -output openssl/lib/libcrypto.a OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a + +git clone https://github.com/cristeab/ios-cmake.git +pushd ios-cmake +git apply ../fix_ios_cmake_compiler.patch +popd +mkdir build.ios +pushd build.ios +cmake .. -DCMAKE_BUILD_TYPE=Release +make +popd +echo "====" +echo "The final library is available in 'build.ios/libcpprest.a'" diff --git a/External/cpprestsdk/Build_iOS/fix_boost_building_script.patch b/External/cpprestsdk/Build_iOS/fix_boost_building_script.patch new file mode 100644 index 00000000..a7f7b432 --- /dev/null +++ b/External/cpprestsdk/Build_iOS/fix_boost_building_script.patch @@ -0,0 +1,13 @@ +diff --git a/boost.sh b/boost.sh +index 2d5c05d..5c10ee9 100644 +--- a/boost.sh ++++ b/boost.sh +@@ -26,7 +26,7 @@ + # + #=============================================================================== + +-BOOST_LIBS="atomic chrono date_time exception filesystem program_options random signals system test thread" ++BOOST_LIBS="chrono filesystem random regex system thread" + + BUILD_IOS= + BUILD_OSX= diff --git a/External/cpprestsdk/Build_iOS/fix_boost_version.patch b/External/cpprestsdk/Build_iOS/fix_boost_version.patch new file mode 100644 index 00000000..e7f13ce1 --- /dev/null +++ b/External/cpprestsdk/Build_iOS/fix_boost_version.patch @@ -0,0 +1,186 @@ +diff --git a/boost.sh b/boost.sh +old mode 100644 +new mode 100755 +index 22b308c..07ef184 +--- a/boost.sh ++++ b/boost.sh +@@ -1,4 +1,4 @@ +-# Builds a Boost framework for the iPhone, iPhone Simulator, and OSX. ++# Builds a Boost framework for the iPhone and iPhone Simulator. + # Creates a set of universal libraries that can be used on an iPhone and in the + # iPhone simulator. Then creates a pseudo-framework to make using boost in Xcode + # less painful. +@@ -6,27 +6,21 @@ + # To configure the script, define: + # BOOST_LIBS: which libraries to build + # IPHONE_SDKVERSION: iPhone SDK version (e.g. 8.1) +-# OSX_SDKVERSION: OSX SDK version (e.g. 10.10) + # + # Then go get the source tar.bz of the boost you want to build, shove it in the + # same directory as this script, and run "./boost.sh". Grab a cuppa. And voila. + #=============================================================================== + +-: ${BOOST_VERSION:=1.56.0} +-: ${BOOST_VERSION2:=1_56_0} ++: ${BOOST_VERSION:=1.57.0} ++: ${BOOST_VERSION2:=1_57_0} + +-: ${BOOST_LIBS:="atomic chrono date_time exception filesystem program_options random signals system test thread"} ++: ${BOOST_LIBS:="thread chrono filesystem regex system random"} + + # Current iPhone SDK + : ${IPHONE_SDKVERSION:=`xcodebuild -showsdks | grep iphoneos | egrep "[[:digit:]]+\.[[:digit:]]+" -o | tail -1`} + # Specific iPhone SDK + # : ${IPHONE_SDKVERSION:=8.1} + +-# Current OSX SDK +-: ${OSX_SDKVERSION:=`xcodebuild -showsdks | grep macosx | egrep "[[:digit:]]+\.[[:digit:]]+" -o | tail -1`} +-# Specific OSX SDK +-# : ${OSX_SDKVERSION:=10.10} +- + : ${XCODE_ROOT:=`xcode-select -print-path`} + : ${EXTRA_CPPFLAGS:="-DBOOST_AC_USE_PTHREADS -DBOOST_SP_USE_PTHREADS -g -DNDEBUG -std=c++11 -stdlib=libc++"} + +@@ -41,10 +35,8 @@ + : ${TARBALLDIR:=`pwd`} + : ${SRCDIR:=`pwd`/src} + : ${IOSBUILDDIR:=`pwd`/ios/build} +-: ${OSXBUILDDIR:=`pwd`/osx/build} + : ${PREFIXDIR:=`pwd`/ios/prefix} + : ${IOSFRAMEWORKDIR:=`pwd`/ios/framework} +-: ${OSXFRAMEWORKDIR:=`pwd`/osx/framework} + + BOOST_TARBALL=$TARBALLDIR/boost_$BOOST_VERSION2.tar.bz2 + BOOST_SRC=$SRCDIR/boost_${BOOST_VERSION2} +@@ -52,7 +44,6 @@ BOOST_SRC=$SRCDIR/boost_${BOOST_VERSION2} + #=============================================================================== + ARM_DEV_CMD="xcrun --sdk iphoneos" + SIM_DEV_CMD="xcrun --sdk iphonesimulator" +-OSX_DEV_CMD="xcrun --sdk macosx" + + #=============================================================================== + # Functions +@@ -79,12 +70,10 @@ cleanEverythingReadyToStart() + { + echo Cleaning everything before we start to build... + +- rm -rf iphone-build iphonesim-build osx-build ++ rm -rf iphone-build iphonesim-build + rm -rf $IOSBUILDDIR +- rm -rf $OSXBUILDDIR + rm -rf $PREFIXDIR + rm -rf $IOSFRAMEWORKDIR/$FRAMEWORK_NAME.framework +- rm -rf $OSXFRAMEWORKDIR/$FRAMEWORK_NAME.framework + + doneSection + } +@@ -142,11 +131,6 @@ using darwin : ${IPHONE_SDKVERSION}~iphonesim + : $XCODE_ROOT/Platforms/iPhoneSimulator.platform/Developer + : x86 iphone + ; +-using darwin : ${OSX_SDKVERSION} +-: g++ -arch i386 -arch x86_64 -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS +-: $XCODE_ROOT/Platforms/MacOSX.platform/Developer +-: x86 darwin +-; + EOF + + doneSection +@@ -192,10 +176,6 @@ buildBoostForIPhoneOS() + echo Building Boost for iPhoneSimulator + ./b2 -j16 --build-dir=iphonesim-build --stagedir=iphonesim-build/stage toolset=darwin-${IPHONE_SDKVERSION}~iphonesim architecture=x86 target-os=iphone macosx-version=iphonesim-${IPHONE_SDKVERSION} link=static stage + doneSection +- +- echo building Boost for OSX +- ./b2 -j16 --build-dir=osx-build --stagedir=osx-build/stage toolset=clang cxxflags="-std=c++11 -stdlib=libc++ -arch i386 -arch x86_64" linkflags="-stdlib=libc++" link=static threading=multi macosx-version=${OSX_SDKVERSION} stage +- doneSection + } + + #=============================================================================== +@@ -233,10 +213,6 @@ scrunchAllLibsTogetherInOneLibPerPlatform() + mkdir -p $IOSBUILDDIR/i386/obj + mkdir -p $IOSBUILDDIR/x86_64/obj + +- # OSX +- mkdir -p $OSXBUILDDIR/i386/obj +- mkdir -p $OSXBUILDDIR/x86_64/obj +- + ALL_LIBS="" + + echo Splitting all existing fat binaries... +@@ -254,9 +230,6 @@ scrunchAllLibsTogetherInOneLibPerPlatform() + + $SIM_DEV_CMD lipo "iphonesim-build/stage/lib/libboost_$NAME.a" -thin i386 -o $IOSBUILDDIR/i386/libboost_$NAME.a + $SIM_DEV_CMD lipo "iphonesim-build/stage/lib/libboost_$NAME.a" -thin x86_64 -o $IOSBUILDDIR/x86_64/libboost_$NAME.a +- +- $OSX_DEV_CMD lipo "osx-build/stage/lib/libboost_$NAME.a" -thin i386 -o $OSXBUILDDIR/i386/libboost_$NAME.a +- $OSX_DEV_CMD lipo "osx-build/stage/lib/libboost_$NAME.a" -thin x86_64 -o $OSXBUILDDIR/x86_64/libboost_$NAME.a + done + + echo "Decomposing each architecture's .a files" +@@ -273,14 +246,10 @@ scrunchAllLibsTogetherInOneLibPerPlatform() + + unpackArchive "$IOSBUILDDIR/i386/obj" $NAME + unpackArchive "$IOSBUILDDIR/x86_64/obj" $NAME +- +- unpackArchive "$OSXBUILDDIR/i386/obj" $NAME +- unpackArchive "$OSXBUILDDIR/x86_64/obj" $NAME + done + + echo "Linking each architecture into an uberlib ($ALL_LIBS => libboost.a )" + rm $IOSBUILDDIR/*/libboost.a +- rm $OSXBUILDDIR/*/libboost.a + + for NAME in $BOOST_LIBS; do + if [ "$NAME" == "test" ]; then +@@ -300,11 +269,6 @@ scrunchAllLibsTogetherInOneLibPerPlatform() + (cd $IOSBUILDDIR/i386; $SIM_DEV_CMD ar crus libboost.a obj/$NAME/*.o; ) + echo ...x86_64 + (cd $IOSBUILDDIR/x86_64; $SIM_DEV_CMD ar crus libboost.a obj/$NAME/*.o; ) +- +- echo ...osx-i386 +- (cd $OSXBUILDDIR/i386; $OSX_DEV_CMD ar crus libboost.a obj/$NAME/*.o; ) +- echo ...osx-x86_64 +- (cd $OSXBUILDDIR/x86_64; $OSX_DEV_CMD ar crus libboost.a obj/$NAME/*.o; ) + done + } + +@@ -333,6 +297,7 @@ buildFramework() + mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION + mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Resources + mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Headers ++ mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Headers/boost + mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Documentation + + echo "Framework: Creating symlinks..." +@@ -348,7 +313,7 @@ buildFramework() + $ARM_DEV_CMD lipo -create $BUILDDIR/*/libboost.a -o "$FRAMEWORK_INSTALL_NAME" || abort "Lipo $1 failed" + + echo "Framework: Copying includes..." +- cp -r $PREFIXDIR/include/boost/* $FRAMEWORK_BUNDLE/Headers/ ++ cp -r $PREFIXDIR/include/boost/* $FRAMEWORK_BUNDLE/Headers/boost + + echo "Framework: Creating plist..." + cat > $FRAMEWORK_BUNDLE/Resources/Info.plist < + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file diff --git a/External/cpprestsdk/ThirdPartyNotices.txt b/External/cpprestsdk/ThirdPartyNotices.txt new file mode 100644 index 00000000..dab0d367 --- /dev/null +++ b/External/cpprestsdk/ThirdPartyNotices.txt @@ -0,0 +1,159 @@ + +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +C++ REST SDK incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. + +1. Websocket++ (http://www.zaphoyd.com/websocketpp/) + +%% Websocket++ NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Main Library: + +Copyright (c) 2014, Peter Thorson. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the WebSocket++ Project nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Bundled Libraries: + +****** Base 64 Library (base64/base64.hpp) ****** +base64.hpp is a repackaging of the base64.cpp and base64.h files into a +single header suitable for use as a header only library. This conversion was +done by Peter Thorson (webmaster@zaphoyd.com) in 2012. All modifications to +the code are redistributed under the same license as the original, which is +listed below. + +base64.cpp and base64.h + +Copyright (C) 2004-2008 Ren Nyffenegger + +This source code is provided 'as-is', without any express or implied +warranty. In no event will the author be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + +3. This notice may not be removed or altered from any source distribution. + +Ren Nyffenegger rene.nyffenegger@adp-gmbh.ch + +****** SHA1 Library (sha1/sha1.hpp) ****** +sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1 +library (http://code.google.com/p/smallsha1/) into a single header suitable for +use as a header only library. This conversion was done by Peter Thorson +(webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed +under the same license as the original, which is listed below. + + Copyright (c) 2011, Micael Hildenborg + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Micael Hildenborg nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +****** MD5 Library (common/md5.hpp) ****** +md5.hpp is a reformulation of the md5.h and md5.c code from +http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to +function as a component of a header only library. This conversion was done by +Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The +changes are released under the same license as the original (listed below) + +Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +****** UTF8 Validation logic (utf8_validation.hpp) ****** +utf8_validation.hpp is adapted from code originally written by Bjoern Hoehrmann +. See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for +details. + +The original license: + +Copyright (c) 2008-2009 Bjoern Hoehrmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF Websocket++ NOTICES, INFORMATION, AND LICENSE + + diff --git a/External/cpprestsdk/build.root b/External/cpprestsdk/build.root new file mode 100644 index 00000000..d423a1a7 --- /dev/null +++ b/External/cpprestsdk/build.root @@ -0,0 +1 @@ +Marker file indicating root of build system. diff --git a/External/cpprestsdk/casablanca110.Xbox.sln b/External/cpprestsdk/casablanca110.Xbox.sln new file mode 100644 index 00000000..102a2b0e --- /dev/null +++ b/External/cpprestsdk/casablanca110.Xbox.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "casablanca110.xbox", "Release\src\build\vs11.xbox\casablanca110.Xbox.vcxproj", "{E621C269-D177-4C1B-80EA-C0A274B7A151}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{FA8460FB-E9D5-40D1-BB9D-38E6B816D4F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.ActiveCfg = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Debug|Durango.Build.0 = Debug|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.ActiveCfg = Release|Durango + {E621C269-D177-4C1B-80EA-C0A274B7A151}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/External/cpprestsdk/cpprestsdk120.nonuget b/External/cpprestsdk/cpprestsdk120.nonuget new file mode 100644 index 00000000..e69de29b diff --git a/External/cpprestsdk/cpprestsdk120.sln b/External/cpprestsdk/cpprestsdk120.sln new file mode 100644 index 00000000..59fc89bf --- /dev/null +++ b/External/cpprestsdk/cpprestsdk120.sln @@ -0,0 +1,321 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "Release\src\build\common.vcxitems", "{594DCB5F-07E3-4084-A2CE-268611FA629F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "other", "Release\src\build\other.vcxitems", "{3D5908F7-7673-4229-BC46-2007A7AF9CAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32", "Release\src\build\win32.vcxitems", "{F40F4804-50F9-4257-8D74-B9CBB19AC4C3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrt", "Release\src\build\winrt.vcxitems", "{0A9BA181-7876-4B3D-A5E0-EE673FA51C05}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120", "Release\src\build\vs12\casablanca120.vcxproj", "{01A76234-E6E8-4332-9FE2-1E12C34621BE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.winrt", "Release\src\build\vs12.winrt\casablanca120.winrt.vcxproj", "{9AD285A2-301E-47A0-A299-14AD5D4F2758}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.xp", "Release\src\build\vs12.xp\casablanca120.xp.vcxproj", "{15F3B200-1AED-4B57-AF37-B21CD67914B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wps81", "Release\src\build\vs12.wps81\casablanca120.wps81.vcxproj", "{C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wp81", "Release\src\build\vs12.wp81\casablanca120.wp81.vcxproj", "{E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B27A3D67-1423-48D8-9F6D-D8FD7E682EC7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BingRequest", "BingRequest", "{06A71AA7-132E-4A1B-A353-C36B2779331F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest120", "Release\samples\BingRequest\BingRequest120\BingRequest120.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest120.xp", "Release\samples\BingRequest\BingRequest120.xp\BingRequest120.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SearchFile", "SearchFile", "{CA4D2B5D-D78C-4165-B8E6-0126FF584FCB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile120", "Release\samples\SearchFile\SearchFile120\SearchFile120.vcxproj", "{F03BEE03-BEFB-4B17-A774-D9C8246530D4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CasaLens", "CasaLens", "{BBB2B70F-1D96-4597-96B0-75EA9BE3CA2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CasaLens120", "Release\samples\CasaLens\CasaLens120\CasaLens120.vcxproj", "{FFBFD6C1-B525-4D35-AB64-A2FE9460B147}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BlackJack", "BlackJack", "{843B16ED-DE6A-4541-B700-D65B384D43A0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{E442BD21-6B65-4D0E-A96C-623F605A9517}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{3D3149CF-B1FF-40C0-BD59-1B41FC3522F0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client120", "Release\samples\BlackJack\BlackJack_Client\BlackJack_Client120\BlackJack_Client120.vcxproj", "{830B6E2F-9224-41D1-B9C7-A51FC78B00C7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Server120", "Release\samples\BlackJack\BlackJack_Server\BlackJack_Server120\BlackJack_Server120.vcxproj", "{84350CD1-D406-4A4F-9571-261CA46D77C5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowsLiveAuth", "WindowsLiveAuth", "{052831C4-6B41-4A52-A740-4228EB79CF3B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsLiveAuth120", "Release\samples\WindowsLiveAuth\WindowsLiveAuth120.vcxproj", "{1C20F771-3131-46E8-805F-AA1FE44165C0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UIClient", "UIClient", "{11041CA3-4C29-41E4-9C76-36AF06268C19}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_UIClient120", "Release\samples\BlackJack\BlackJack_UIClient\BlackJack_UIClient120.vcxproj", "{B8D3F85B-DA71-4ACA-87BA-10FED681DC79}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Facebook", "Facebook", "{3E5DF179-3668-49DA-9B6D-38C0632D8F28}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FacebookDemo120", "Release\samples\FacebookDemo\FacebookDemo120.vcxproj", "{43DE4DF3-ACAA-429E-B260-CC6D4FE82658}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wod", "Release\src\build\vs12.wod\casablanca120.wod.vcxproj", "{BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.xp.static", "Release\src\build\vs12.xp.static\casablanca120.xp.static.vcxproj", "{CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Release\src\build\win32.vcxitems*{cf74448d-fe99-4e3c-afa6-a50f3145baf3}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{cf74448d-fe99-4e3c-afa6-a50f3145baf3}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 + Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 + Release\src\build\win32.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 + Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|ARM = Release|ARM + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|ARM.ActiveCfg = Debug|ARM + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|Win32.Build.0 = Debug|Win32 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|x64.ActiveCfg = Debug|x64 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|x64.Build.0 = Debug|x64 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|ARM.ActiveCfg = Release|ARM + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|Win32.ActiveCfg = Release|Win32 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|Win32.Build.0 = Release|Win32 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|x64.ActiveCfg = Release|x64 + {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|x64.Build.0 = Release|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|ARM.ActiveCfg = Debug|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|ARM.Build.0 = Debug|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|Win32.ActiveCfg = Debug|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|Win32.Build.0 = Debug|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x64.ActiveCfg = Debug|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x64.Build.0 = Debug|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|ARM.ActiveCfg = Release|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|ARM.Build.0 = Release|ARM + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|Win32.ActiveCfg = Release|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|Win32.Build.0 = Release|Win32 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x64.ActiveCfg = Release|x64 + {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x64.Build.0 = Release|x64 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|ARM.ActiveCfg = Debug|ARM + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|Win32.ActiveCfg = Debug|Win32 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|Win32.Build.0 = Debug|Win32 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|x64.ActiveCfg = Debug|x64 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|x64.Build.0 = Debug|x64 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|ARM.ActiveCfg = Release|ARM + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|Win32.ActiveCfg = Release|Win32 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|Win32.Build.0 = Release|Win32 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|x64.ActiveCfg = Release|x64 + {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|x64.Build.0 = Release|x64 + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|ARM.ActiveCfg = Debug|ARM + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|ARM.Build.0 = Debug|ARM + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|Win32.Build.0 = Debug|Win32 + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|x64.ActiveCfg = Debug|x64 + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|ARM.ActiveCfg = Release|ARM + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|ARM.Build.0 = Release|ARM + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|Win32.ActiveCfg = Release|Win32 + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|Win32.Build.0 = Release|Win32 + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|x64.ActiveCfg = Release|x64 + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|ARM.ActiveCfg = Debug|ARM + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|ARM.Build.0 = Debug|ARM + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|Win32.ActiveCfg = Debug|Win32 + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|Win32.Build.0 = Debug|Win32 + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|x64.ActiveCfg = Debug|x64 + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|ARM.ActiveCfg = Release|ARM + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|ARM.Build.0 = Release|ARM + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|Win32.ActiveCfg = Release|Win32 + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|Win32.Build.0 = Release|Win32 + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|x64.ActiveCfg = Release|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|ARM.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.Build.0 = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.ActiveCfg = Debug|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.Build.0 = Debug|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|ARM.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.Build.0 = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.ActiveCfg = Release|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|ARM.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.Build.0 = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.ActiveCfg = Debug|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.Build.0 = Debug|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|ARM.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.Build.0 = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.ActiveCfg = Release|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|ARM.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.Build.0 = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.ActiveCfg = Debug|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.Build.0 = Debug|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|ARM.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.Build.0 = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.ActiveCfg = Release|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.Build.0 = Release|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|ARM.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.Build.0 = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.ActiveCfg = Debug|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.Build.0 = Debug|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|ARM.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.Build.0 = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.ActiveCfg = Release|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.Build.0 = Release|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|ARM.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.Build.0 = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.ActiveCfg = Debug|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.Build.0 = Debug|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|ARM.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.Build.0 = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.ActiveCfg = Release|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.Build.0 = Release|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|ARM.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.Build.0 = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.ActiveCfg = Debug|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.Build.0 = Debug|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|ARM.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.Build.0 = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.ActiveCfg = Release|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.Build.0 = Release|x64 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|ARM.ActiveCfg = Debug|ARM + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|ARM.Build.0 = Debug|ARM + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|ARM.Deploy.0 = Debug|ARM + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|Win32.Build.0 = Debug|Win32 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|Win32.Deploy.0 = Debug|Win32 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|x64.ActiveCfg = Debug|x64 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|x64.Build.0 = Debug|x64 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|x64.Deploy.0 = Debug|x64 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|ARM.ActiveCfg = Release|ARM + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|ARM.Build.0 = Release|ARM + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|ARM.Deploy.0 = Release|ARM + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|Win32.ActiveCfg = Release|Win32 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|Win32.Build.0 = Release|Win32 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|Win32.Deploy.0 = Release|Win32 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|x64.ActiveCfg = Release|x64 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|x64.Build.0 = Release|x64 + {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|x64.Deploy.0 = Release|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.ActiveCfg = Debug|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Build.0 = Debug|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Deploy.0 = Debug|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|Win32.ActiveCfg = Debug|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|Win32.Build.0 = Debug|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|Win32.Deploy.0 = Debug|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.ActiveCfg = Debug|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Build.0 = Debug|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Deploy.0 = Debug|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.ActiveCfg = Release|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Build.0 = Release|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Deploy.0 = Release|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|Win32.ActiveCfg = Release|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|Win32.Build.0 = Release|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|Win32.Deploy.0 = Release|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.ActiveCfg = Release|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Build.0 = Release|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Deploy.0 = Release|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.ActiveCfg = Debug|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Build.0 = Debug|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Deploy.0 = Debug|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|Win32.ActiveCfg = Debug|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|Win32.Build.0 = Debug|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|Win32.Deploy.0 = Debug|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.ActiveCfg = Debug|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Build.0 = Debug|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Deploy.0 = Debug|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.ActiveCfg = Release|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Build.0 = Release|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Deploy.0 = Release|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|Win32.ActiveCfg = Release|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|Win32.Build.0 = Release|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|Win32.Deploy.0 = Release|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.ActiveCfg = Release|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Build.0 = Release|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Deploy.0 = Release|x64 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|ARM.ActiveCfg = Debug|ARM + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|ARM.Build.0 = Debug|ARM + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|Win32.ActiveCfg = Debug|Win32 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|Win32.Build.0 = Debug|Win32 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|x64.ActiveCfg = Debug|x64 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|x64.Build.0 = Debug|x64 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|ARM.ActiveCfg = Release|ARM + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|ARM.Build.0 = Release|ARM + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|Win32.ActiveCfg = Release|Win32 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|Win32.Build.0 = Release|Win32 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|x64.ActiveCfg = Release|x64 + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|x64.Build.0 = Release|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|ARM.ActiveCfg = DebugStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|ARM.Build.0 = DebugStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|Win32.ActiveCfg = DebugStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|Win32.Build.0 = DebugStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|x64.ActiveCfg = DebugStatic|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|x64.Build.0 = DebugStatic|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|ARM.ActiveCfg = ReleaseStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|ARM.Build.0 = ReleaseStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|Win32.ActiveCfg = ReleaseStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|Win32.Build.0 = ReleaseStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|x64.ActiveCfg = ReleaseStatic|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|x64.Build.0 = ReleaseStatic|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {65951C40-A332-4B54-89C2-7CDAF30D5F66} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {594DCB5F-07E3-4084-A2CE-268611FA629F} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {3D5908F7-7673-4229-BC46-2007A7AF9CAE} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {F40F4804-50F9-4257-8D74-B9CBB19AC4C3} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {0A9BA181-7876-4B3D-A5E0-EE673FA51C05} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {01A76234-E6E8-4332-9FE2-1E12C34621BE} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {9AD285A2-301E-47A0-A299-14AD5D4F2758} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {15F3B200-1AED-4B57-AF37-B21CD67914B1} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {06A71AA7-132E-4A1B-A353-C36B2779331F} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {06A71AA7-132E-4A1B-A353-C36B2779331F} + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} = {06A71AA7-132E-4A1B-A353-C36B2779331F} + {CA4D2B5D-D78C-4165-B8E6-0126FF584FCB} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} + {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {CA4D2B5D-D78C-4165-B8E6-0126FF584FCB} + {BBB2B70F-1D96-4597-96B0-75EA9BE3CA2A} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {BBB2B70F-1D96-4597-96B0-75EA9BE3CA2A} + {843B16ED-DE6A-4541-B700-D65B384D43A0} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} + {E442BD21-6B65-4D0E-A96C-623F605A9517} = {843B16ED-DE6A-4541-B700-D65B384D43A0} + {3D3149CF-B1FF-40C0-BD59-1B41FC3522F0} = {843B16ED-DE6A-4541-B700-D65B384D43A0} + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {E442BD21-6B65-4D0E-A96C-623F605A9517} + {84350CD1-D406-4A4F-9571-261CA46D77C5} = {3D3149CF-B1FF-40C0-BD59-1B41FC3522F0} + {052831C4-6B41-4A52-A740-4228EB79CF3B} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} + {1C20F771-3131-46E8-805F-AA1FE44165C0} = {052831C4-6B41-4A52-A740-4228EB79CF3B} + {11041CA3-4C29-41E4-9C76-36AF06268C19} = {843B16ED-DE6A-4541-B700-D65B384D43A0} + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79} = {11041CA3-4C29-41E4-9C76-36AF06268C19} + {3E5DF179-3668-49DA-9B6D-38C0632D8F28} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} = {3E5DF179-3668-49DA-9B6D-38C0632D8F28} + {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + EndGlobalSection +EndGlobal diff --git a/External/cpprestsdk/cpprestsdk140.nonuget b/External/cpprestsdk/cpprestsdk140.nonuget new file mode 100644 index 00000000..e69de29b diff --git a/External/cpprestsdk/cpprestsdk140.sln b/External/cpprestsdk/cpprestsdk140.sln new file mode 100644 index 00000000..4a9087e9 --- /dev/null +++ b/External/cpprestsdk/cpprestsdk140.sln @@ -0,0 +1,292 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "Release\src\build\common.vcxitems", "{594DCB5F-07E3-4084-A2CE-268611FA629F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "other", "Release\src\build\other.vcxitems", "{3D5908F7-7673-4229-BC46-2007A7AF9CAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32", "Release\src\build\win32.vcxitems", "{F40F4804-50F9-4257-8D74-B9CBB19AC4C3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrt", "Release\src\build\winrt.vcxitems", "{0A9BA181-7876-4B3D-A5E0-EE673FA51C05}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{64F2F240-04BE-43B2-97BE-DA47FDFE8393}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B572F8D5-9728-409C-AB5E-063C7D3CA781}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BingRequest", "BingRequest", "{00EF03C1-74A9-4832-B26B-E6478C2A96AC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BlackJack", "BlackJack", "{B6F7411C-FE75-4CD2-A384-083A526FE6DF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CasaLens", "CasaLens", "{76FA5645-FF99-44C0-87DB-B96AFAC2F800}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SearchFile", "SearchFile", "{22309B46-EE6F-45D0-A993-2F45D98DEF22}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140", "Release\samples\BingRequest\BingRequest140\BingRequest140.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{8E54A174-9108-45BF-8080-92A916C43A54}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{DADA0A65-A970-4114-8F9C-EA3327F90712}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client140", "Release\samples\BlackJack\BlackJack_Client\BlackJack_Client140\BlackJack_Client140.vcxproj", "{830B6E2F-9224-41D1-B9C7-A51FC78B00C7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Server140", "Release\samples\BlackJack\BlackJack_Server\BlackJack_Server140\BlackJack_Server140.vcxproj", "{84350CD1-D406-4A4F-9571-261CA46D77C5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CasaLens140", "Release\samples\CasaLens\CasaLens140\CasaLens140.vcxproj", "{FFBFD6C1-B525-4D35-AB64-A2FE9460B147}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile140", "Release\samples\SearchFile\SearchFile140\SearchFile140.vcxproj", "{F03BEE03-BEFB-4B17-A774-D9C8246530D4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.android", "Release\src\build\vs14.android\casablanca140.android.vcxproj", "{AFB49019-965B-4C10-BAFF-C86C16D58010}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.vcxproj", "{36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp.staticlib", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.staticlib.vcxproj", "{47A5CFDC-C244-45A6-9830-38CB303CB495}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.static", "Release\src\build\vs14.static\casablanca140.static.vcxproj", "{79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.xp", "Release\src\build\vs14.xp\casablanca140.xp.vcxproj", "{39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140.xp", "Release\samples\BingRequest\BingRequest140.xp\BingRequest140.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 + Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 + Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 + Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|ARM.ActiveCfg = Debug|ARM + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|Win32.ActiveCfg = Debug|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|Win32.Build.0 = Debug|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.ActiveCfg = Debug|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.Build.0 = Debug|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.ActiveCfg = Debug|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.Build.0 = Debug|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|ARM.ActiveCfg = Release|ARM + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|Win32.ActiveCfg = Release|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|Win32.Build.0 = Release|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.ActiveCfg = Release|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.Build.0 = Release|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.ActiveCfg = Release|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.Build.0 = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|ARM.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.Build.0 = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.ActiveCfg = Debug|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.Build.0 = Debug|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.Build.0 = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|ARM.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.Build.0 = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.ActiveCfg = Release|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.Build.0 = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|ARM.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.Build.0 = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.ActiveCfg = Debug|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.Build.0 = Debug|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.Build.0 = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|ARM.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.Build.0 = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.ActiveCfg = Release|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.Build.0 = Release|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.Build.0 = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|ARM.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.Build.0 = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.ActiveCfg = Debug|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.Build.0 = Debug|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.Build.0 = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|ARM.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.Build.0 = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.ActiveCfg = Release|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.Build.0 = Release|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.Build.0 = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|ARM.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.Build.0 = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.ActiveCfg = Debug|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.Build.0 = Debug|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.Build.0 = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|ARM.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.Build.0 = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.ActiveCfg = Release|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.Build.0 = Release|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.Build.0 = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|ARM.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.Build.0 = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.ActiveCfg = Debug|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.Build.0 = Debug|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.Build.0 = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|ARM.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.Build.0 = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.ActiveCfg = Release|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.Build.0 = Release|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.Build.0 = Release|Win32 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.ActiveCfg = Debug|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.Build.0 = Debug|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|Win32.ActiveCfg = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|Win32.Build.0 = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x64.ActiveCfg = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.ActiveCfg = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.Build.0 = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.ActiveCfg = Release|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.Build.0 = Release|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|Win32.ActiveCfg = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|Win32.Build.0 = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x64.ActiveCfg = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.ActiveCfg = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.Build.0 = Release|x86 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.ActiveCfg = Debug|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.Build.0 = Debug|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|Win32.ActiveCfg = Debug|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|Win32.Build.0 = Debug|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.ActiveCfg = Debug|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.Build.0 = Debug|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.ActiveCfg = Debug|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.Build.0 = Debug|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.ActiveCfg = Release|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.Build.0 = Release|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|Win32.ActiveCfg = Release|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|Win32.Build.0 = Release|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.ActiveCfg = Release|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.Build.0 = Release|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.ActiveCfg = Release|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.Build.0 = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|ARM.ActiveCfg = Debug|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|ARM.Build.0 = Debug|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|Win32.ActiveCfg = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|Win32.Build.0 = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x64.ActiveCfg = Debug|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x64.Build.0 = Debug|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x86.ActiveCfg = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x86.Build.0 = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|ARM.ActiveCfg = Release|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|ARM.Build.0 = Release|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|Win32.ActiveCfg = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|Win32.Build.0 = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.ActiveCfg = Release|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.Build.0 = Release|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.ActiveCfg = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.Build.0 = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.ActiveCfg = Debug|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.Build.0 = Debug|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.ActiveCfg = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.Build.0 = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x64.ActiveCfg = Debug|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x64.Build.0 = Debug|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x86.ActiveCfg = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x86.Build.0 = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|ARM.ActiveCfg = Release|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|ARM.Build.0 = Release|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|Win32.ActiveCfg = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|Win32.Build.0 = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x64.ActiveCfg = Release|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x64.Build.0 = Release|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x86.ActiveCfg = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x86.Build.0 = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|ARM.ActiveCfg = Debug|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|ARM.Build.0 = Debug|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|Win32.ActiveCfg = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|Win32.Build.0 = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x64.ActiveCfg = Debug|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x64.Build.0 = Debug|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x86.ActiveCfg = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x86.Build.0 = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|ARM.ActiveCfg = Release|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|ARM.Build.0 = Release|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|Win32.ActiveCfg = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|Win32.Build.0 = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x64.ActiveCfg = Release|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x64.Build.0 = Release|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x86.ActiveCfg = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x86.Build.0 = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|ARM.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.Build.0 = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.ActiveCfg = Debug|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.Build.0 = Debug|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x86.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x86.Build.0 = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|ARM.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.Build.0 = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.ActiveCfg = Release|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1014C621-BC2D-4813-B8C1-6D83AD6F9249} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {65951C40-A332-4B54-89C2-7CDAF30D5F66} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {594DCB5F-07E3-4084-A2CE-268611FA629F} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {3D5908F7-7673-4229-BC46-2007A7AF9CAE} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {F40F4804-50F9-4257-8D74-B9CBB19AC4C3} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {0A9BA181-7876-4B3D-A5E0-EE673FA51C05} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {00EF03C1-74A9-4832-B26B-E6478C2A96AC} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} + {B6F7411C-FE75-4CD2-A384-083A526FE6DF} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} + {76FA5645-FF99-44C0-87DB-B96AFAC2F800} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} + {22309B46-EE6F-45D0-A993-2F45D98DEF22} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {00EF03C1-74A9-4832-B26B-E6478C2A96AC} + {8E54A174-9108-45BF-8080-92A916C43A54} = {B6F7411C-FE75-4CD2-A384-083A526FE6DF} + {DADA0A65-A970-4114-8F9C-EA3327F90712} = {B6F7411C-FE75-4CD2-A384-083A526FE6DF} + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {8E54A174-9108-45BF-8080-92A916C43A54} + {84350CD1-D406-4A4F-9571-261CA46D77C5} = {DADA0A65-A970-4114-8F9C-EA3327F90712} + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {76FA5645-FF99-44C0-87DB-B96AFAC2F800} + {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {22309B46-EE6F-45D0-A993-2F45D98DEF22} + {AFB49019-965B-4C10-BAFF-C86C16D58010} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {47A5CFDC-C244-45A6-9830-38CB303CB495} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} = {00EF03C1-74A9-4832-B26B-E6478C2A96AC} + EndGlobalSection +EndGlobal diff --git a/External/cpprestsdk/license.txt b/External/cpprestsdk/license.txt new file mode 100644 index 00000000..fb805d97 --- /dev/null +++ b/External/cpprestsdk/license.txt @@ -0,0 +1,25 @@ +C++ REST SDK + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/External/cpprestsdk/setup_ps_env_VS2013.ps1 b/External/cpprestsdk/setup_ps_env_VS2013.ps1 new file mode 100644 index 00000000..08517586 --- /dev/null +++ b/External/cpprestsdk/setup_ps_env_VS2013.ps1 @@ -0,0 +1,22 @@ +function Get-Batchfile ($file) { + $cmd = "`"$file`" & set" + cmd /c $cmd | Foreach-Object { + $p, $v = $_.split('=') + Set-Item -path env:$p -value $v + } +} + +function VsVars32() +{ + $vs120comntools = (Get-ChildItem env:VS120COMNTOOLS).Value + $batchFile = [System.IO.Path]::Combine($vs120comntools, "vsvars32.bat") + Get-Batchfile $BatchFile +} + +"Initializing C++ REST SDK Powershell VS2013 Environment" + +# get VS tools +VsVars32 + +$Env:VisualStudioVersion = "12.0" +$Env:DevToolsVersion = "120" diff --git a/External/cpprestsdk/setup_ps_env_VS2015.ps1 b/External/cpprestsdk/setup_ps_env_VS2015.ps1 new file mode 100644 index 00000000..297f210e --- /dev/null +++ b/External/cpprestsdk/setup_ps_env_VS2015.ps1 @@ -0,0 +1,17 @@ +"Initializing C++ REST SDK Powershell VS2015 Environment" + +# Add MSBuild to the path. +if (Test-Path "Env:ProgramFiles(x86)") +{ + $msbuildLocation = (Get-ChildItem "Env:ProgramFiles(x86)").Value +} +else +{ + $msbuildLocation = (Get-ChildItem "Env:ProgramFiles").Value +} + +$msbuildLocation = [System.IO.Path]::Combine($msbuildLocation, "MSBuild", "14.0", "Bin") +$Env:Path += ";" + $msbuildLocation + +$Env:VisualStudioVersion = "14.0" +$Env:DevToolsVersion = "140" diff --git a/Include/xsapi/achievements.h b/Include/xsapi/achievements.h new file mode 100644 index 00000000..3d9954ab --- /dev/null +++ b/Include/xsapi/achievements.h @@ -0,0 +1,810 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xbox_live_app_config.h" + +namespace xbox { namespace services { + class xbox_live_context_impl; + + /// + /// Contains classes and enumerations that let you retrieve + /// information about player achievements from Xbox Live. + /// + namespace achievements { + +/// Enumeration values that indicate the achievement type. +enum class achievement_type +{ + /// The achievement type is unknown. + unknown, + + /// Used as a request input parameter. + /// All means to get all achievements regardless of type. + all, + + /// A persistent achievement that may be unlocked at any time. + /// Persistent achievements can give Gamerscore as a reward. + persistent, + + /// A challenge achievement that may only be unlocked within a certain time period. + /// Challenge achievements can't give Gamerscore as a reward. + challenge +}; + +/// Enumeration values that indicate the achievement sort order. +enum class achievement_order_by +{ + /// Default order does not guarantee sort order. + default_order, + + /// Sort by title id. + title_id, + + /// Sort by achievement unlock time. + unlock_time +}; + +/// Enumeration values that indicate the state of a player's progress towards unlocking an achievement. +enum class achievement_progress_state +{ + /// Achievement progress is unknown. + unknown, + + /// Achievement has been earned. + achieved, + + /// Achievement progress has not been started. + not_started, + + /// Achievement progress has started. + in_progress +}; + +/// +/// Enumeration values that indicate the media asset type associated with +/// the achievement. +/// +enum class achievement_media_asset_type +{ + /// The media asset type is unknown. + unknown, + + /// An icon media asset. + icon, + + /// An art media asset. + art +}; + +/// Enumeration values that indicate the participation type for an achievement. +enum class achievement_participation_type +{ + /// The participation type is unknown. + unknown, + + /// An achievement that can be earned as an individual participant. + individual, + + /// An achievement that can be earned as a group participant. + group +}; + +/// Enumeration values that indicate the reward type for an achievement. +enum class achievement_reward_type +{ + /// The reward type is unknown. + unknown, + + /// A Gamerscore reward. + gamerscore, + + /// An in-app reward, defined and delivered by the title. + in_app, + + /// A digital art reward. + art +}; + + +/// +/// Represents the association between a title and achievements. +/// +class achievement_title_association +{ +public: + achievement_title_association(); + + achievement_title_association( + _In_ string_t name, + _In_ uint32_t id + ); + + /// + /// The localized name of the title. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The title ID. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_name; + uint32_t m_id; +}; + +/// +/// Represents requirements for unlocking the achievement. +/// +class achievement_requirement +{ +public: + achievement_requirement(); + + /// + /// Internal function + /// + achievement_requirement( + _In_ string_t id, + _In_ string_t currentProgressValue, + _In_ string_t targetProgressValue + ); + + /// + /// The achievement requirement ID. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// A value that indicates the current progress of the player towards meeting + /// the requirement. + /// + _XSAPIIMP const string_t& current_progress_value() const; + + /// + /// The target progress value that the player must reach in order to meet + /// the requirement. + /// + _XSAPIIMP const string_t& target_progress_value() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_id; + string_t m_currentProgressValue; + string_t m_targetProgressValue; +}; + +/// +/// Represents progress details about the achievement, including requirements. +/// +class achievement_progression +{ +public: + achievement_progression(); + + /// + /// Internal function + /// + achievement_progression( + _In_ std::vector requirements, + _In_ utility::datetime timeUnlocked + ); + + /// + /// The actions and conditions that are required to unlock the achievement. + /// + _XSAPIIMP const std::vector& requirements() const; + + /// + /// The timestamp when the achievement was first unlocked. + /// + _XSAPIIMP const utility::datetime& time_unlocked() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::vector m_requirements; + utility::datetime m_timeUnlocked; +}; + +/// +/// Represents an interval of time during which an achievement can be unlocked. +/// This class is only used when the achievement_type enumeration is set to challenge. +/// +class achievement_time_window +{ +public: + achievement_time_window(); + + /// + /// Internal function + /// + achievement_time_window( + _In_ utility::datetime startDate, + _In_ utility::datetime endDate + ); + + /// + /// The start date and time of the achievement time window. + /// + _XSAPIIMP const utility::datetime& start_date() const; + + /// + /// The end date and time of the achievement time window. + /// + _XSAPIIMP const utility::datetime& end_date() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + utility::datetime m_startDate; + utility::datetime m_endDate; +}; + +/// +/// Represents a media asset for an achievement. +/// +class achievement_media_asset +{ +public: + achievement_media_asset(); + + /// + /// Internal function + /// + achievement_media_asset( + _In_ string_t name, + _In_ achievement_media_asset_type type, + _In_ web::uri m_url + ); + + /// + /// The name of the media asset, such as "tile01". + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The type of media asset. + /// + _XSAPIIMP achievement_media_asset_type media_asset_type() const; + + /// + /// The URL of the media asset. + /// + _XSAPIIMP const web::uri& url() const; + + /// + /// Internal function + /// + static achievement_media_asset_type _Convert_string_to_media_asset_type( + _In_ const string_t& value + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_name; + achievement_media_asset_type m_type; + web::uri m_url; +}; + +/// +/// Represents a reward that is associated with the achievement. +/// +class achievement_reward +{ +public: + achievement_reward(); + + /// + /// Internal function + /// + achievement_reward( + _In_ string_t name, + _In_ string_t description, + _In_ string_t value, + _In_ achievement_reward_type type, + _In_ string_t valuePropertyType, + _In_ achievement_media_asset mediaAsset + ); + + /// + /// The localized reward name. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The description of the reward. + /// + _XSAPIIMP const string_t& description() const; + + /// + /// The title-defined reward value (data type and content varies by reward type). + /// + _XSAPIIMP const string_t& value() const; + + /// + /// The reward type. + /// + _XSAPIIMP achievement_reward_type reward_type() const; + + /// + /// The property type of the reward value string. + /// + _XSAPIIMP const string_t& value_type() const; + + /// + /// The media asset associated with the reward. + /// If the reward type is gamerscore, this will be nullptr. + /// If the reward type is in_app, this will be a media asset. + /// If the reward type is art, this may be a media asset or nullptr. + /// + _XSAPIIMP const achievement_media_asset& media_asset() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + static achievement_reward_type convert_string_to_reward_type( + _In_ const string_t& value + ); + + string_t m_name; + string_t m_description; + string_t m_value; + achievement_reward_type m_rewardType; + string_t m_valuePropertyType; + achievement_media_asset m_mediaAsset; +}; + + +/// +/// Represents an achievement, a system-wide mechanism for directing and +/// rewarding users' in-game actions consistently across all games. +/// +class achievement +{ +public: + achievement(); + + /// + /// Internal function + /// + achievement( + _In_ string_t id, + _In_ string_t serviceConfigurationId, + _In_ string_t name, + _In_ std::vector titleAssociations, + _In_ achievement_progress_state progressState, + _In_ std::vector mediaAssets, + _In_ std::vector platformsAvailableOn, + _In_ bool isSecret, + _In_ string_t unlockedDescription, + _In_ string_t lockedDescription, + _In_ string_t productId, + _In_ achievement_type achievementType, + _In_ achievement_participation_type participationType, + _In_ achievement_time_window available, + _In_ std::vector rewards, + _In_ std::chrono::seconds estimatedUnlockTime, + _In_ string_t deepLink, + _In_ bool isRevoked, + _In_ achievement_progression progression + ); + + /// + /// The achievement ID. Can be a uint or a guid. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// The ID of the service configuration set associated with the achievement. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The localized achievement name. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The game/app titles associated with the achievement. + /// + _XSAPIIMP const std::vector& title_associations() const; + + /// + /// The state of a user's progress towards the earning of the achievement. + /// + _XSAPIIMP achievement_progress_state progress_state() const; + + /// + /// The progression object containing progress details about the achievement, + /// including requirements. + /// + _XSAPIIMP const achievement_progression& progression() const; + + /// + /// The media assets associated with the achievement, such as image IDs. + /// + _XSAPIIMP const std::vector& media_assets() const; + + /// + /// The collection of platforms that the achievement is available on. + /// + _XSAPIIMP const std::vector& platforms_available_on() const; + + /// + /// Whether or not the achievement is secret. + /// + _XSAPIIMP bool is_secret() const; + + /// + /// The description of the unlocked achievement. + /// + _XSAPIIMP const string_t& unlocked_description() const; + + /// + /// The description of the locked achievement. + /// + _XSAPIIMP const string_t& locked_description() const; + + /// + /// The product_id the achievement was released with. This is a globally unique indentifier that + /// may correspond to an application, downloadable content, etc. + /// + _XSAPIIMP const string_t& product_id() const; + + /// + /// The type of achievement, such as a challenge achievement. + /// + _XSAPIIMP achievement_type type() const; + + /// + /// The participation type for the achievement, such as group or individual. + /// + _XSAPIIMP achievement_participation_type participation_type() const; + + /// + /// The time window during which the achievement is available. Applies to Challenges. + /// + _XSAPIIMP const achievement_time_window& available() const; + + /// + /// The collection of rewards that the player earns when the achievement is unlocked. + /// + _XSAPIIMP const std::vector& rewards() const; + + /// + /// The estimated time that the achievement takes to be earned. + /// + _XSAPIIMP const std::chrono::seconds& estimated_unlock_time() const; + + /// + /// A deeplink for clients that enables the title to lauch at a desired starting point + /// for the achievement. + /// + _XSAPIIMP const string_t& deep_link() const; + + /// + /// A value that indicates whether or not the achievement is revoked by enforcement. + /// + _XSAPIIMP bool is_revoked() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_id; + string_t m_serviceConfigurationId; + string_t m_name; + std::vector m_titleAssociations; + achievement_progress_state m_progressState; + std::vector m_mediaAssets; + std::vector m_platformsAvailableOn; + bool m_isSecret; + string_t m_unlockedDescription; + string_t m_lockedDescription; + string_t m_productId; + achievement_type m_achievementType; + achievement_participation_type m_participationType; + achievement_time_window m_available; + std::vector m_rewards; + std::chrono::seconds m_estimatedUnlockTime; + string_t m_deepLink; + bool m_isRevoked; + achievement_progression m_progression; +}; + +/// +/// Represents a collection of Achievement class objects returned by a request. +/// +class achievements_result +{ +public: + /// + /// Creates a new achievement result object. + /// + _XSAPIIMP achievements_result(); + + /// + /// Internal function + /// + void _Init_next_page_info( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::weak_ptr xboxLiveContextImpl, + _In_ string_t xboxUserId, + _In_ std::vector titleIds, + _In_ achievement_type type, + _In_ bool unlockedOnly, + _In_ achievement_order_by orderBy + ); + + /// + /// The collection of achievement objects returned by a request. + /// + _XSAPIIMP const std::vector& items() const; + + /// + /// Returns a boolean value that indicates if there are more pages of achievements to retrieve. + /// + /// True if there are more pages, otherwise false. + _XSAPIIMP bool has_next(); + + /// + /// Returns an achievements_result object that contains the next page of achievements. + /// + /// The maximum number of items that the result can contain. Pass 0 to attempt + /// to retrieve all items. + /// An achievements_result object that contains a list of achievement objects. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// This method calls V2 GET /users/xuid({xuid})/achievements. + /// + _XSAPIIMP pplx::task> get_next( + _In_ uint32_t maxItems + ); + + /// + /// Internal function + /// + static xbox::services::xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::weak_ptr m_xboxLiveContextImpl; + + string_t m_xboxUserId; + std::vector m_titleIds; + achievement_type m_achievementType; + bool m_unlockedOnly; + achievement_order_by m_orderBy; + std::vector m_items; + string_t m_continuationToken; +}; + +/// +/// Represents an endpoint that you can use to access the Achievement service. +/// +class achievement_service +{ +public: + /// + /// Allow achievement progress to be updated and achievements to be unlocked. + /// This API will work even when offline. On PC and Xbox One, updates will be + /// posted by the system when connection is re-established even if the title isn't running. + /// + /// The Xbox User ID of the player. + /// The achievement ID as defined by XDP or Dev Center. + /// The completion percentage of the achievement to indicate progress. + /// Valid values are from 1 to 100. Set to 100 to unlock the achievement. + /// Progress will be set by the server to the highest value sent + /// + /// Returns a task<T> object that represents the state of the asynchronous operation. + /// + /// This method calls V2 POST /users/xuid({xuid})/achievements/{scid}/update + /// + _XSAPIIMP pplx::task> update_achievement( + _In_ const string_t& xboxUserId, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ); + + /// + /// Allow achievement progress to be updated and achievements to be unlocked. + /// This API will work even when offline. On PC and Xbox One, updates will be + /// posted by the system when connection is re-established even if the title isn't running. + /// + /// The Xbox User ID of the player. + /// The title ID. + /// The service configuration ID (SCID) for the title. + /// The achievement ID as defined by XDP or Dev Center. + /// The completion percentage of the achievement to indicate progress. + /// Valid values are from 1 to 100. Set to 100 to unlock the achievement. + /// Progress will be set by the server to the highest value sent + /// + /// Returns a task<T> object that represents the state of the asynchronous operation. + /// + /// This method calls V2 POST /users/xuid({xuid})/achievements/{scid}/update + /// + _XSAPIIMP pplx::task> update_achievement( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ); + + /// + /// Returns an achievements_result object containing the first page of achievements + /// for a player of the specified title. + /// + /// The Xbox User ID of the player. + /// The title ID. + /// The achievement type to retrieve. + /// Indicates whether to return unlocked achievements only. + /// Controls how the list of achievements is ordered. + /// The number of achievements to skip. + /// The maximum number of achievements the result can contain. Pass 0 to attempt + /// to retrieve all items. + /// An AchievementsResult object that contains a list of Achievement objects. + /// + /// Returns a task<T> object that represents the state of the asynchronous operation. + /// + /// See achievements_result:get_next to page in the next set of results. + /// + /// This method calls V2 GET /users/xuid({xuid})/achievements + /// + _XSAPIIMP pplx::task> get_achievements_for_title_id( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId, + _In_ achievement_type type, + _In_ bool unlockedOnly, + _In_ achievement_order_by orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ); + + /// + /// Returns a specific achievement object for a specified player. + /// + /// The Xbox User ID of the player. + /// The service configuration ID (SCID) for the title. + /// The unique identifier of the Achievement as defined by XDP or Dev Center. + /// The requested achievement object if it exists. + /// If the achievement does not exist, the method returns xbox_live_error_code::runtime_error . + /// + /// Returns a task<T> object that represents the state of the asynchronous operation. + /// + /// This method calls V2 GET /users/xuid({xuid})/achievements/{scid}/{achievementId}. + /// + _XSAPIIMP pplx::task> get_achievement( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& achievementId + ); + + achievement_service() {}; + + achievement_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::weak_ptr xboxLiveContextImpl + ); + +private: + pplx::task> get_achievements( + _In_ const string_t& xboxUserId, + _In_ const std::vector& titleIds, + _In_ achievement_type type, + _In_ bool unlockedOnly, + _In_ achievement_order_by orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ); + + // Achievements endpoints + static const string_t achievements_sub_path( + _In_ const string_t& xboxUserId, + _In_ const std::vector& titleIds, + _In_ const string_t& types, + _In_ bool unlockedOnly, + _In_ const string_t& orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ); + + static const string_t update_achievement_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId + ); + + static const string_t achievement_by_id_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& achievementId + ); + + static xbox_live_result convert_type_to_string( + _In_ achievement_type type + ); + + static xbox_live_result convert_order_by_to_string( + _In_ achievement_order_by orderBy + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::weak_ptr m_xboxLiveContextImpl; + +#if TV_API + static xbox::services::xbox_live_result write_offline_update_achievement( + _In_ std::shared_ptr xboxLiveContextImpl, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ); + + static ULONG event_write_achievement_update( + _In_ PCWSTR userId, + _In_ PCWSTR achievementId, + _In_ const uint32_t percentComplete + ); + +#elif UWP_API + static xbox::services::xbox_live_result write_offline_update_achievement( + _In_ std::shared_ptr xboxLiveContextImpl, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ); +#endif + +#if TV_API || UNIT_TEST_SERVICES + static std::mutex m_initLock; + static bool s_bHasInitialized; + static std::string s_eventProviderName; + static GUID s_eventPlayerSessionId; +#endif + + friend class xbox_live_context_impl; + friend class achievements_result; +}; + +}}} diff --git a/Include/xsapi/contextual_search_service.h b/Include/xsapi/contextual_search_service.h new file mode 100644 index 00000000..b361833d --- /dev/null +++ b/Include/xsapi/contextual_search_service.h @@ -0,0 +1,800 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that perform contextual search on Xbox Live. + /// + namespace contextual_search { + +/// Enumerates the visibility of a contextual search statistic. +enum class contextual_search_stat_visibility +{ + /// Unknown visibility. + unknown, + + /// This is important, as third party applications like Twitch will only be able to view OPEN stats. + public_visibility, + + /// If a stat is private, only the title itself, or a companion application that has special privileges, can access this information. + private_visibility +}; + +/// Enumerates the display type of a contextual search statistic. +enum class contextual_search_stat_display_type +{ + /// Unknown type. + unknown, + + /// This stat should be displayed as a undefined range. + undefined_range, + + /// This stat should be displayed as a defined range. + defined_range, + + /// This stat should be displayed using the value_to_display_name_map. + set +}; + +/// Enumerates the operators of a contextual search filter. +enum class contextual_search_filter_operator +{ + /// Matches if filter name is equals to filter value. + equal, + + /// Matches if filter name is not equal to filter value. + not_equal, + + /// Matches if filter name is greater than filter value. + greater_than, + + /// Matches if filter name is greater than or equal to filter value. + greater_than_or_equal, + + /// Matches if filter name is less than filter value. + less_than, + + /// Matches if filter name is less than or equal to filter value. + less_than_or_equal, +}; + +/// Contains information about a contextual search stat. +class contextual_search_configured_stat +{ +public: + /// + /// The actual name of the configured stat. This is what you will use as a parameter in the search API. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The data type of the stat. It should align with the values you are passing for the stat into the Search API. + /// + _XSAPIIMP const string_t& data_type() const; + + /// + /// The visibility of the stat + /// + _XSAPIIMP contextual_search_stat_visibility visibility() const; + + /// + /// This is the localizable string exposed to the end user. Depending on the language / culture you + /// pass up in the header, you will get a localized version of this string. + /// + _XSAPIIMP const string_t& display_name() const; + + /// + /// Boolean on whether you can use this stat in a filter + /// + _XSAPIIMP bool can_be_filtered() const; + + /// + /// Boolean on whether you can make sort queries + /// + _XSAPIIMP bool can_be_sorted() const; + + /// + /// How this Stat should be represented, as either a Set, Defined Range, or Undefined Range + /// + _XSAPIIMP contextual_search_stat_display_type display_type() const; + + /// + /// If the representation type is set, this contains a map to convert values to display names + /// + _XSAPIIMP const std::unordered_map& value_to_display_name_map() const; + + /// + /// If the representation type is defined range, this is the min range + /// + _XSAPIIMP uint64_t range_min() const; + + /// + /// If the representation type is defined range, this is the max range + /// + _XSAPIIMP uint64_t range_max() const; + + contextual_search_configured_stat(); + + /// + /// Internal function + /// + contextual_search_configured_stat( + _In_ string_t name, + _In_ string_t dataType, + _In_ contextual_search_stat_visibility visibility, + _In_ string_t displayName, + _In_ bool canBeFiltered, + _In_ bool canBeSorted, + _In_ contextual_search_stat_display_type displayType, + _In_ std::unordered_map valueToDisplayNameMap, + _In_ uint64_t rangeMin, + _In_ uint64_t rangeMax + ); + +private: + string_t m_name; + string_t m_dataType; + contextual_search_stat_visibility m_visibility; + string_t m_displayName; + bool m_canBeFiltered; + bool m_canBeSorted; + contextual_search_stat_display_type m_displayType; + std::unordered_map m_valueToDisplayNameMap; + uint64_t m_rangeMin; + uint64_t m_rangeMax; +}; + +/// Contains information about a contextual search broadcast. +class contextual_search_broadcast +{ +public: + /// + /// The Xbox user ID of the player. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Returns the broadcast provider, for example "Twitch". + /// This is leveraged to enable differing logic to handle content from different providers + /// + _XSAPIIMP const string_t& provider() const; + + /// + /// The identifier of the broadcaster on the provider. This is leveraged to created deeplinks to the broadcast. + /// In the example of Twitch, this is the Twitch user id. + /// + _XSAPIIMP const string_t& broadcaster_id_from_provider() const; + + /// + /// The current number of viewers in the broadcast, per the last update from Presence. + /// + _XSAPIIMP uint64_t viewers() const; + + /// + /// The date value of when the broadcast started + /// + _XSAPIIMP const utility::datetime& started_date() const; + + /// + /// The current stats the title has configured for Contextual Search and what their current values are. + /// Additional information on how to surface the information is contained in the configuration handler. + /// + _XSAPIIMP const std::unordered_map& current_stats() const; + + contextual_search_broadcast(); + + /// + /// Internal function + /// + contextual_search_broadcast( + _In_ string_t xboxUserId, + _In_ string_t provider, + _In_ string_t broadcasterIdFromProvider, + _In_ uint64_t viewers, + _In_ utility::datetime startedDate, + _In_ std::unordered_map currentStats + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + string_t m_xboxUserId; + string_t m_provider; + string_t m_broadcasterIdFromProvider; + uint64_t m_viewers; + utility::datetime m_startedDate; + std::unordered_map m_currentStats; +}; + +/// Describes the type of game clip +enum class contextual_search_game_clip_type +{ + /// Game clip type is unknown or not set. (not valid for upload or queries) + none, + + /// Game clip is initiated by a developer / title + developer_initiated, + + /// Game clip is an achievement type + achievement, + + /// Game clip is a user-generated type + user_generated +}; + +/// Describes the type of thumbnail +enum class contextual_search_game_clip_thumbnail_type +{ + /// Thumbnail type is not specified. This is an invalid value in most cases. + none, + + /// Specifies a small thumbnail. Small is 370 pixels in height by 208 pixels in width. + small_thumbnail, + + /// Specifies a large thumbnail. Large is 754 pixels in height by 424 pixels in width. + large_thumbnail +}; + +/// Describes the type of game clip URI. +enum class contextual_search_game_clip_uri_type +{ + /// Game clip URI type is not known or not set. + none, + + /// Game clip URI is the location of the original game clip in unprocessed form. + original, + + /// Game clip URI is the location of the clip available for download. + download, + + /// Game clip URI is the IIS Smooth Streaming URL(manifest pointer). + smooth_streaming, + + /// Game clip URI is the Apple HTTP Live Streaming URL. + http_live_streaming +}; + +/// +/// The information related to an instance of a game clip video asset. +/// Since there can be multiple representations for a clip, it is up to the client to select the most appropriate one for playback. +/// +class contextual_search_game_clip_uri_info +{ +public: + /// + /// The URI to the location of the video asset. + /// + _XSAPIIMP const web::uri& url() const; + + /// + /// The file size at the location of the URL for formats that are downloaded + /// This is 0 for streaming formats + /// + _XSAPIIMP uint64_t file_size() const; + + /// + /// Specifies the type of the URI. + /// + _XSAPIIMP contextual_search_game_clip_uri_type uri_type() const; + + /// + /// The expiration time of the URI that is included in this response. + /// + _XSAPIIMP const utility::datetime& expiration() const; + + /// + /// Internal function + /// + contextual_search_game_clip_uri_info(); + + /// + /// Internal function + /// + contextual_search_game_clip_uri_info( + _In_ web::uri url, + _In_ uint64_t fileSize, + _In_ contextual_search_game_clip_uri_type uriType, + _In_ utility::datetime expiration + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + static contextual_search_game_clip_uri_type convert_string_to_clip_uri_type(_In_ const string_t& value); + + web::uri m_url; + uint64_t m_fileSize; + contextual_search_game_clip_uri_type m_uriType; + utility::datetime m_expiration; +}; + +/// +/// Contains the information related to an individual thumbnail. +/// There can be multiple sizes per clip and it is up to the client to select the proper one for display. +/// +class contextual_search_game_clip_thumbnail +{ +public: + /// + /// The URI for the thumbnail image. + /// + _XSAPIIMP const web::uri& url() const; + + /// + /// The total file size of the thumbnail image. + /// + _XSAPIIMP uint64_t file_size() const; + + /// + /// The type of thumbnail image. + /// + _XSAPIIMP contextual_search_game_clip_thumbnail_type thumbnail_type() const; + + /// + /// Internal function + /// + contextual_search_game_clip_thumbnail(); + + /// + /// Internal function + /// + contextual_search_game_clip_thumbnail( + _In_ web::uri url, + _In_ uint64_t fileSize, + _In_ contextual_search_game_clip_thumbnail_type thumbnailType + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + static contextual_search_game_clip_thumbnail_type convert_string_to_thumbnail_type(_In_ const string_t& value); + + web::uri m_url; + uint64_t m_fileSize; + contextual_search_game_clip_thumbnail_type m_thumbnailType; +}; + +class contextual_search_game_clip_stat +{ +public: + /// + /// Name of the stat + /// + _XSAPIIMP const string_t& stat_name() const; + + /// + /// Value of the stat for string stats and integer stats representing a set value. + /// If the stat changed during the clip, the field will have multiple values separated by a comma. + /// If the "value" field is present, "min", "max" and "delta" fields will not be present. + /// + _XSAPIIMP const string_t& value() const; + + /// + /// The minimum value the stat had during the recording of the game clip. + /// If the "min" field is present, the "value" field will not be present. + /// + _XSAPIIMP const string_t& min_value() const; + + /// + /// The maximum value the stat had during the recording of the game clip. + /// If the "max" field is present, the "value" field will not be present. + /// + _XSAPIIMP const string_t& max_value() const; + + /// + /// "max"–"min". If the delta field is present, the "value" field will not be present. + /// + _XSAPIIMP const string_t& delta_value() const; + + /// + /// Internal function + /// + contextual_search_game_clip_stat(); + + /// + /// Internal function + /// + contextual_search_game_clip_stat( + _In_ string_t statName, + _In_ string_t value, + _In_ string_t minValue, + _In_ string_t maxValue, + _In_ string_t deltaValue + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + string_t m_statName; + string_t m_value; + string_t m_minValue; + string_t m_maxValue; + string_t m_deltaValue; +}; + + +/// +/// Contains all the relevant metadata for a video. +/// +class contextual_search_game_clip +{ +public: + /// + /// The localized version of the clip’s name based on the input locale of the request as looked up from the title management system. + /// + _XSAPIIMP const string_t& clip_name() const; + + /// + /// Specifies the duration of the game clip in seconds. + /// + _XSAPIIMP uint64_t duration_in_seconds() const; + + /// + /// The ID assigned to the game clip. + /// + _XSAPIIMP const string_t& game_clip_id() const; + + /// + /// The locale the game clip was created under. + /// + _XSAPIIMP const string_t& game_clip_locale() const; + + /// + /// Array of playback options for this clip. + /// + _XSAPIIMP const std::vector& game_clip_uris() const; + + /// + /// Array of thumbnails for this clip. + /// + _XSAPIIMP const std::vector& thumbnails() const; + + /// + /// The type of clip. Can be multiple values and if so will be comma delimited. + /// + _XSAPIIMP contextual_search_game_clip_type game_clip_type() const; + + /// + /// The number of views associated with a game clip. + /// + _XSAPIIMP uint64_t views() const; + + /// + /// The XUID of the owner of the game clip + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Stats associated with the game clip. + /// This contains the initial values of stats at the start of the game clip and any new value a stat had during the recording of the game clip. + /// Note that these are only the stats configured for intermedia in the title configuration. + /// + _XSAPIIMP const std::vector& stats() const; + + /// + /// Internal function + /// + contextual_search_game_clip(); + + /// + /// Internal function + /// + contextual_search_game_clip( + _In_ string_t clipName, + _In_ uint64_t durationInSeconds, + _In_ string_t gameClipId, + _In_ string_t gameClipLocale, + _In_ std::vector gameClipUris, + _In_ std::vector thumbnails, + _In_ contextual_search_game_clip_type gameClipType, + _In_ uint64_t views, + _In_ string_t xboxUserId, + _In_ std::vector stats + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + static string_t convert_xuid_to_string(_In_ uint64_t xuid, _In_ string_t xuidName); + static contextual_search_game_clip_type convert_string_to_clip_type(_In_ const string_t& value); + + string_t m_clipName; + uint64_t m_durationInSeconds; + string_t m_gameClipId; + string_t m_gameClipLocale; + std::vector m_gameClipUris; + std::vector m_thumbnails; + contextual_search_game_clip_type m_gameClipType; + uint64_t m_views; + string_t m_xboxUserId; + std::vector m_stats; +}; + +// Returns the list of returned game clips along with the corresponding paging information +class contextual_search_game_clips_result +{ +public: + /// + /// Returns the next page of game clips. + /// + /// The maximum number of game clips the result can contain. Pass 0 to attempt to retrieve the top 100 items. + _XSAPIIMP pplx::task> get_next( + _In_ uint32_t maxItems + ); + + /// + /// Array of game clips returned. + /// + _XSAPIIMP const std::vector& items() const; + + /// + /// Internal function + /// + contextual_search_game_clips_result(); + + /// + /// Internal function + /// + contextual_search_game_clips_result( + _In_ std::vector clips + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + /// + /// Internal function + /// + void _Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ uint32_t titleId, + _In_ uint32_t skipItems + ); + +private: + std::vector m_clips; + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + uint32_t m_titleId; + uint32_t m_skipItems; +}; + +/// +/// Provides methods to perform Xbox Live contextual search. +/// +class contextual_search_service +{ +public: + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast + /// + /// The title ID. + /// + /// The result contains information to hydrate a UI. + /// + /// Calls V1 GET /titles/{titleid}/configuration + _XSAPIIMP pplx::task>> get_configuration( + _In_ uint32_t titleId + ); + + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast. Defaults to the top 100 broadcasts ordered by viewers descending with no filter + /// + /// The title ID. + /// + /// The result is a contextual_search_broadcasts_result object which contains information about broadcasts. + /// + /// Calls V1 GET /titles/{titleId}/broadcasts + _XSAPIIMP pplx::task>> get_broadcasts( + _In_ uint32_t titleId + ); + + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast + /// + /// The title ID. + /// The number of broadcasts to skip. + /// The maximum number of broadcasts the result can contain. Pass 0 to attempt to retrieve the top 100 items. + /// This specifies a stat to sort the broadcasts by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// This specifies a OData Filter Expressions string that specifies the stats to filter on. + /// For example "stats:maptype eq 1" means filtering by the stat "maptype" to the value 1. + /// Be sure to wrap any user data values in single quotes and escape single quotes with 2 single quotes. + /// For example, "player eq 'Killer''s Hand'" + /// + /// The result is a contextual_search_broadcasts_result object which contains information about broadcasts. + /// + /// Calls V1 GET /titles/{titleId}/broadcasts + _XSAPIIMP pplx::task>> get_broadcasts( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ); + + /// + // Get information to hydrate a UI that allows end users to filter or sort broadcasts + /// + /// The title ID. + /// The number of broadcasts to skip. + /// The maximum number of broadcasts the result can contain. Pass 0 to attempt to retrieve the top 100 items. + /// This specifies a stat to sort the broadcasts by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// This specifies the stat to filter on. Pass empty string for no filter + /// This specifies operator to apply for the filter. + /// This specifies the value to filter on. Pass empty string for no filter + /// + /// The result is a contextual_search_broadcasts_result object which contains information about broadcasts. + /// + /// Calls V1 GET /titles/{titleId}/broadcasts + _XSAPIIMP pplx::task>> get_broadcasts( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filterStatName, + _In_ contextual_search_filter_operator filterOperator, + _In_ const string_t& filterStatValue + ); + + /// + /// Get information to hydrate a UI that allows end users to filter or sort game clips + /// + /// The title ID. + /// The number of game clips to skip. + /// The maximum number of game clips the result can contain. Pass 0 to attempt to retrieve the top 10 items. The max is 20 + /// This specifies a stat to sort the game clips by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// This specifies the stat to filter on. Pass empty string for no filter. For example, "gametype.value". + /// The "value" property is only available for string stats and integer stats. + /// The "min", "max" and "delta" properties are only available for double stats and integer stats. + /// + /// This specifies operator to apply for the filter. + /// This specifies the value to filter on. The stat properties that can be used to search with are 'value', 'min', 'max', and 'delta'. Pass empty string for no filter + /// + /// The result is an object which contains information about game clips. + /// + /// Calls V1 GET /titles/{titleId}/gameclips + _XSAPIIMP pplx::task> get_game_clips( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filterStatName, + _In_ contextual_search_filter_operator filterOperator, + _In_ const string_t& filterStatValue + ); + + /// + /// Get information to hydrate a UI that allows end users to filter or sort game clips + /// + /// The title ID. + /// The number of game clips to skip. + /// The maximum number of game clips the result can contain. Pass 0 to attempt to retrieve the top 10 items. The max is 20 + /// This specifies a stat to sort the game clips by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// + /// The search query. + /// The query syntax is an OData like syntax with only the following operators supported EQ, NE, GE, GT, LE and LT along with the logical operators of AND and OR. You can also use grouping operator ‘()’. The stat properties that can be used to search with are "value", "min", "max", and "delta". + /// + /// Example 1: + /// To search for game clips during which the "gametype" stat had a value of 1 use + /// "stats:gametype.value eq 1" + /// + /// Example 2: + /// To search for game clips during which the "rank" stat jumped more than 2. + /// "stats:rank.value gt 2" + /// + /// Example 3: + /// To search for game clips during which the "rank" stat jumped more than 2 and the "gametype" stat had a value of 1 use + /// "stats:rank.value gt 2 and stat:gametype.value eq 1" + /// + /// Note: + /// - The "value" property is only available for string stats and integer stats that are used with a Set. + /// - The "min", "max" and "delta" properties are only available for double stats and integer stats that are not used with a Set. + /// + /// + /// The result is an object which contains information about game clips. + /// + /// Calls V1 GET /titles/{titleId}/gameclips + _XSAPIIMP pplx::task> get_game_clips( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ); + +private: + contextual_search_service() {} + + pplx::task> get_game_clips_internal( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ); + + xbox_live_result create_broadcasts_url( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filter + ); + + static xbox_live_result create_game_clips_url( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filter + ); + + static xbox_live_result> + deserialize_broadcasts_result(_In_ const web::json::value& inputJson); + + static xbox_live_result> + deserialize_configuration_result(_In_ const web::json::value& inputJson); + + static string_t convert_operator_to_string( + _In_ contextual_search_filter_operator filterOperator + ); + + contextual_search_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr settings, + _In_ std::shared_ptr appConfig + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_settings; + std::shared_ptr m_appConfig; + + friend xbox_live_context_impl; + friend class contextual_search_game_clips_result; +}; + + +}}} diff --git a/Include/xsapi/entertainment_profile.h b/Include/xsapi/entertainment_profile.h new file mode 100644 index 00000000..225a1509 --- /dev/null +++ b/Include/xsapi/entertainment_profile.h @@ -0,0 +1,147 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#if TV_API || UNIT_TEST_SERVICES +#pragma once +#include "xbox_live_app_config.h" +#include "xsapi/marketplace.h" + +namespace xbox { namespace services { + /// + /// Classes for managing the entertainment profile + /// + namespace entertainment_profile { + +class entertainment_profile_list_contains_item_result +{ +public: + _XSAPIIMP bool is_contained() const; + + _XSAPIIMP const string_t& provider_id() const; + + _XSAPIIMP const string_t& provider() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + bool m_isContained; + string_t m_providerId; + string_t m_provider; +}; + +/// +/// Represents an endpoint that you can use to access the Entertainment Profile. +/// +class entertainment_profile_list_xbox_one_pins +{ +public: + + /// + /// Adds an item to the end of the video queue. + /// + /// The type of item being added to the video queue (Movie, TelevisionShow, TelevisionSeries, or TelevisionSeason). + /// The Id that a provider (3rd party app) uses to identify a piece of content. + /// The string used to identify the provider of the content. + /// A Url pointing to a box shot, cover art, etc that is representative of the content. (Optional) + /// A Url for the provider's logo image. (Optional) + /// The title of the item. (Optional) + /// The subtitle of the item. (Optional) + /// The locale of the item. + /// Calls V2 POST /users/xuid({xuid})/lists/PINS/XBLPins + pplx::task> add_item( + _In_ xbox::services::marketplace::media_item_type itemType, + _In_ const string_t& providerId, + _In_ const string_t& provider, + _In_ const web::uri& imageUrl, + _In_ const web::uri& providerLogoImageUrl, + _In_ const string_t& title, + _In_ const string_t& subTitle, + _In_ const string_t& locale + ); + + /// + /// Removes an item from the video queue. + /// + /// The Id that a provider (3rd party app) uses to identify a piece of content. + /// The string used to identify the provider of the content. + /// Calls V2 POST /users/xuid({xuid})/lists/PINS/XBLPins/RemoveItems + pplx::task> remove_item( + _In_ const string_t& providerId, + _In_ const string_t& provider + ); + + /// + /// Determines if an item exists in the video queue. + /// + /// The Id that a provider (3rd party app) uses to identify a piece of content. + /// The string used to identify the provider of the content. + /// Calls V2 POST /users/xuid({xuid})/lists/PINS/XBLPins/ContainsItems + pplx::task> contains_item( + _In_ const string_t& providerId, + _In_ const string_t& provider + ); +private: + entertainment_profile_list_xbox_one_pins() {}; + + entertainment_profile_list_xbox_one_pins( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + // Entertainment Profile endpoints + static string_t entertainment_profile_list_xbox_one_pins_add_item_sub_path( + _In_ const string_t& xboxUserId + ); + + static string_t entertainment_profile_list_xbox_one_pins_remove_item_sub_path( + _In_ const string_t& xboxUserId + ); + + static string_t entertainment_profile_list_xbox_one_pins_contains_item_sub_path( + _In_ const string_t& xboxUserId + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend class entertainment_profile_list_service; +}; + +/// +/// Represents an endpoint that you can use to access the Entertainment Profile. +/// +class entertainment_profile_list_service +{ +public: + entertainment_profile_list_xbox_one_pins& xbox_one_pins(); + +private: + entertainment_profile_list_service() {}; + + entertainment_profile_list_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + entertainment_profile_list_xbox_one_pins m_xboxOnePins; + + friend class xbox_live_context_impl; +}; + +}}} +#endif diff --git a/Include/xsapi/errors.h b/Include/xsapi/errors.h new file mode 100644 index 00000000..e4f561c7 --- /dev/null +++ b/Include/xsapi/errors.h @@ -0,0 +1,1523 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include + +#ifndef _NOEXCEPT +#ifdef XSAPI_U +#define _NOEXCEPT noexcept +#endif +#endif + +namespace xbox { + /// + /// Contains classes, enumerations, and namespaces used to indicate error conditions for Xbox Live service components. + /// + namespace services { + + /// + /// Enumeration values that define the Xbox Live API error conditions. + /// + /// + /// A best practice is to test the returned std::error_code against these error conditions. + /// For more detail about std::error_code vs std::error_condition, see + /// http://en.cppreference.com/w/cpp/error/error_condition + /// + /// + /// For example: + /// + /// if( result.err() == xbox::services::xbox_live_error_condition::auth ) + /// { + /// // ... + /// } + /// + /// or + /// + /// switch (result.err().default_error_condition().value()) + /// { + /// case xbox::services::xbox_live_error_condition::auth: + /// // ... + /// break; + /// } + /// + /// + enum class xbox_live_error_condition + { + /// + /// No error. + /// + no_error = 0, + + /// + /// A generic error condition. + /// + generic_error, + + /// + /// An error condition related to an object being out of range. + /// + generic_out_of_range, + + /// + /// An error condition related to attempting to authenticate. + /// + auth, + + /// + /// An error condition related to network connectivity. + /// + network, + + /// + /// An error condition related to an HTTP method call. + /// + http, + + /// + /// The requested resource was not found. + /// + http_404_not_found, + + /// + /// The precondition given in one or more of the request-header fields evaluated + /// to false when it was tested on the server. + /// + http_412_precondition_failed, + + /// + /// Client is sending too many requests + /// + http_429_too_many_requests, + + /// + /// The service timed out while attempting to process the request. + /// + http_service_timeout, + + /// + /// An error related to real time activity. + /// + rta + }; + + /// + /// These are XSAPI specific error codes. + /// Only the HTTP codes and errors that are commonly seen when calling Xbox LIVE are called out with guidance about the cause. + /// The best practice to test for and react to using the xbox_live_error_condition enum instead of these error codes. + /// + enum class xbox_live_error_code + { + /// + /// 0 + /// No error + /// + no_error = 0, + + ////////////////////////////////////////////////////////////////////////// + // HTTP errors + ////////////////////////////////////////////////////////////////////////// + + /// + /// The 204 response indicates that the content data was not found. + /// This code is returned when you are trying to access or write to a session that has been deleted. + /// + http_status_204_resource_data_not_found = 204, + + /// + /// 0x8019012C + /// The 300 response indicates there are multiple choices. Not returned by Xbox Live services + /// + http_status_300_multiple_choices = 300, + + /// + /// 0x8019012D + /// The 301 response indicates that the request should be directed at a new URI + /// + http_status_301_moved_permanently = 301, + + /// + /// 0x8019012E + /// The 302 response indicates found. + /// + http_status_302_found = 302, + + /// + /// 0x8019012F + /// The 303 response indicates see other. Not returned by Xbox Live services + /// + http_status_303_see_other = 303, + + /// + /// 0x80190130 + /// The 304 response indicates resource has not been modified. + /// + http_status_304_not_modified = 304, + + /// + /// 0x80190131 + /// The 305 response indicates you must a use proxy. Not typically returned by Xbox Live services + /// + http_status_305_use_proxy = 305, + + /// + /// 0x80190133 + /// The 307 response indicates a temporary redirect. + /// + http_status_307_temporary_redirect = 307, + + /// + /// 0x80190190 + /// The request could not be understood by the server due to malformed syntax. + /// The client should not repeat this request without modification. + /// + /// This code is returned by the following methods: + /// Social services + /// GetUserProfileAsync: + /// The list of XUIDs returned from a leaderboard read operation and passed to this method has failed + /// due to one or more invalid XUID values. + /// + /// Data services + /// GetSingleUserStatisticsAsync: + /// Corresponds to a general HTTP error code: HTTP 400 Bad Request. + /// + /// Server Platform services + /// AllocateClusterAsync: + /// Matchmaking request failure, typically due to QoS (where the requirement is all-or-nothing). + /// + /// Marketplace services + /// GetCatalogItemDetailsAsync: + /// The Details service can only support 10 CatalogItems per request (MAX_DETAILS_ITEMS). + /// BrowseCatalogAsync: Typically an error of setting maxItems too large. The catalog service only supports a max of + /// 25 items per call. + /// + http_status_400_bad_request = 400, + + /// + /// 0x80190191 + /// The 401 response typically indicates that authorization has been refused for provided credentials. + /// This code is returned when the user(s) or the device is not authorized to access the requested data + /// or perform the requested action. + /// + http_status_401_unauthorized = 401, + + /// + /// 0x80190192 + /// 402 Payment Required + /// + http_status_402_payment_required = 402, + + /// + /// 0x80190193 + /// Corresponds to general HTTP error code HTTP 403 - Forbidden. + /// The server understood the request but is refusing to fulfill. Authorization will not resolve the issue + /// and the request should not be repeated. + /// + /// General + /// This is typically a service configuration issue or a malformed HTTP request. To resolve, make sure that + /// your service configuration is correct, that your console is in the right sandbox, and that you are using + /// the correct title id and SCID. Using fiddler to examine the failing HTTP request will often help root cause the issue. + /// + /// Multiplayer services + /// The user doesn't have multiplayer privileges, or the session is private/reserved and the user isn't a member. + /// + http_status_403_forbidden = 403, + + /// + /// 0x80190194 + /// This typically indicates that the server has not found anything matching the provided URI. + /// The root cause of the 404 will depend on the API you are using. + /// For example many of the "Get Leaderboard" + /// APIs return a 404 error if you request a stat that does not exist, or if the leader board is empty, + /// CreateSessionAsync returns a 404 error if you call it with an invalid Session Template name, and + /// GetPartyViewAsync fails with a 404 if the multiplayer session times out. Using fiddler to examine the failing + /// HTTP request will often help root cause the issue. + /// + http_status_404_not_found = 404, + + /// + /// 0x80190195 + /// The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. + /// For example, the request is a POST where a PUT is needed. + /// + http_status_405_method_not_allowed = 405, + + /// + /// 0x80190196 + /// The resource identified by the request is only capable for generating response entities which have + /// content characteristics not acceptable according to the accept headers sent in the Request. + /// + http_status_406_not_acceptable = 406, + + /// + /// 0x80190197 + /// This code is similar to HTTP 401 (Unauthorized), but indicates that the client must first + /// authenticate itself with the proxy. + /// + http_status_407_proxy_authentication_required = 407, + + /// + /// 0x80190198 + /// The client did not produce a request within the time the server was prepared to wait. The client MAY + /// repeat the request without modifications at a later time. + /// + http_status_408_request_timeout = 408, + + /// + /// 0x80190199 + /// This typically indicates that the request could not be completed due to a conflict with the current + /// state of the resource. This code is only allowed in situations where it is expected that a user might + /// be able to resolve the conflict and re-submit the request. + /// + /// Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being + /// used and the entity being PUT included changes to a resource which conflict with those made by an earlier + /// (third-party) request, the server might use the 409 response to indicate that it can't complete the request. + /// In this case, the response entity would likely contain a list of the differences between the two versions in a + /// format defined by the Response-ContentType. + /// + /// Multiplayer services: + /// Incorrect session or matchmaking query syntax or re-setting properties that are already pre-defined in the session template. + /// The session couldn't be updated because the request is incompatible with the session. For example: + /// Constants in the request conflict with constants in the session or session template. + /// Members other than the caller are added to, or removed, from a large session. + /// + http_status_409_conflict = 409, + + /// + /// 0x8019019A + /// This typically indicates that the requested resource is no longer available at the server and no forwarding address + /// is known. The expectation is that this condition is considered to be permanent. + /// + http_status_410_gone = 410, + + /// + /// 0x8019019B + /// The server refuses to accept the request without a defined Content-Length. The client MAY repeat the request if it + /// adds a valid Content-Length header field containing the length of the message-body in the request. + /// + http_status_411_length_required = 411, + + /// + /// 0x8019019C + /// The precondition given in one or more of the request-header fields evaluated to false when it was tested on the + /// server. This response code allows the client to place preconditions on the current resource meta information + /// (header field data) to prevent the requested method from being applied to a resource other than the one intended. + /// + /// Multiplayer services + /// The If-Match header, or (other than on a GET) the If-None-Match header couldn't be satisfied. + /// The If-Match header couldn't be satisfied on a PUT or DELETE to an existing session. The current state of the session + /// is returned along with the current ETag. + /// + http_status_412_precondition_failed = 412, + + /// + /// 0x8019019D + /// The server is refusing to process a request because the request entity is larger than the server is willing, or able, + /// to process. The server MAY close the connection to prevent the client from continuing with the request. + /// + http_status_413_request_entity_too_large = 413, + + /// + /// 0x8019019E + /// The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret. + /// This rare condition is only likely to occur when a client has improperly converted a POST Request to a GET Request with long query information. + /// + http_status_414_request_uri_too_long = 414, + + /// + /// 0x8019019F + /// The server is refusing to service the request because the entity of the request is in a format not supported by the + /// requested resource for the requested method. + /// + http_status_415_unsupported_media_type = 415, + + /// + /// 0x801901A0 + /// A server SHOULD return a response with this status code if a requested included in a Range request-header field, and none of + /// the range-specifier values in this field overlap the current extent of the selected resource, and the request did not + /// include an If-Range request-header field. + /// + http_status_416_requested_range_not_satisfiable = 416, + + /// + /// 0x801901A1 + /// Expect-request header failure + /// + http_status_417_expectation_failed = 417, + + /// + /// 0x801901A5 + /// The request was misdirected + /// + http_status_421_misdirected_request = 421, + + /// + /// 0x801901A6 + /// The request was not processable + /// + http_status_422_unprocessable_entity = 422, + + /// + /// 0x801901A7 + /// The resource was locked + /// + http_status_423_locked = 423, + + /// + /// 0x801901A8 + /// The request failed due to dependency + /// + http_status_424_failed_dependency = 424, + + /// + /// 0x801901AA + /// The client should upgrade to later protocol + /// + http_status_426_upgrade_required = 426, + + /// + /// 0x801901AC + /// The server requires a precondition + /// + http_status_428_precondition_required = 428, + + /// + /// 0x801901AD + /// Client is sending too many requests + /// + http_status_429_too_many_requests = 429, + + /// + /// 0x801901AF + /// The request headers are too large + /// + http_status_431_request_header_fields_too_large = 431, + + /// + /// 0x801901C1 + /// The request should be retried after doing the appropriate action + /// + http_status_449_retry_with = 449, + + /// + /// 0x801901C3 + /// The request was unavailable for legal reasons + /// + http_status_451_unavailable_for_legal_reasons = 451, + + /// + /// 0x801901F4 + /// Corresponds to HTTP 500 Internal Server Error.This error can occur when invalid parameters are provided to the web service + /// via a RESTful API call, or if the web service encounters a crash or other unexpected error state. Using fiddler to examine + /// the failing HTTP request will often help root cause the issue. + /// + http_status_500_internal_server_error = 500, + + /// + /// 0x801901F5 + /// The requested service is not implemented. + /// + http_status_501_not_implemented = 501, + + /// + /// 0x801901F6 + /// The request got an invalid response to the gateway + /// + http_status_502_bad_gateway = 502, + + /// + /// 0x801901F7 + /// The requested service is not available. + /// + http_status_503_service_unavailable = 503, + + /// + /// 0x801901F8 + /// The HTTP gateway has timed out. + /// + http_status_504_gateway_timeout = 504, + + /// + /// 0x801901F9 + /// This version of HTTP is not supported by the endpoint. + /// + http_status_505_http_version_not_supported = 505, + + /// + /// 0x801901FA + /// Internal configuration error + /// + http_status_506_variant_also_negotiates = 506, + + /// + /// 0x801901FB + /// The service was unable complete the request due to storage + /// + http_status_507_insufficient_storage = 507, + + /// + /// 0x801901FC + /// The service detected an infinite loop while processing + /// + http_status_508_loop_detected = 508, + + /// + /// 0x801901FE + /// The request requires more extensions to complete + /// + http_status_510_not_extended = 510, + + /// + /// 0x801901FF + /// The client needs to authenticate to gain network access. Not used by Xbox Live services. + /// + http_status_511_network_authentication_required = 511, + + ////////////////////////////////////////////////////////////////////////// + // Errors from exception enabled components such as Casablanca + ////////////////////////////////////////////////////////////////////////// + /// + /// 0x8007000e + /// xbox_live_error_code 1000 + /// Bad alloc + /// + bad_alloc = 1000, + + /// + /// 0x80004002 + /// xbox_live_error_code 1001 + /// Bad cast + /// + bad_cast, + + /// + /// 0x80070057 + /// xbox_live_error_code 1002 + /// Invalid argument + /// + invalid_argument, + + /// + /// 0x8000000b + /// xbox_live_error_code 1003 + /// Out of range + /// + out_of_range, + + /// + /// 0x80070018 + /// xbox_live_error_code 1004 + /// Length error + /// + length_error, + + /// + /// 0x8000000b + /// xbox_live_error_code 1005 + /// Range error + /// + range_error, + + /// + /// 0x8000ffff + /// xbox_live_error_code 1006 + /// Logic error + /// + logic_error, + + /// + /// 0x80004005 + /// xbox_live_error_code 1007 + /// Runtime error + /// + runtime_error, + + /// + /// 0x83750007 + /// xbox_live_error_code 1008 + /// JSON error + /// + json_error, + + /// + /// 0x83750005 + /// xbox_live_error_code 1009 + /// Websocket error + /// + websocket_error, + + /// + /// 0x83750005 + /// xbox_live_error_code 1010 + /// URI error + /// + uri_error, + + /// + /// 0x80004005 + /// xbox_live_error_code 1011 + /// Generic error + /// + generic_error, + + ////////////////////////////////////////////////////////////////////////// + // RTA errors + ////////////////////////////////////////////////////////////////////////// + /// + /// 0x80004005 + /// xbox_live_error_code 1500 + /// RTA generic error + /// + rta_generic_error = 1500, + + /// + /// 0x80004005 + /// xbox_live_error_code 1501 + /// RTA subscription limit reached + /// + rta_subscription_limit_reached, + + /// + /// 0x80004005 + /// xbox_live_error_code 1502 + /// RTA access denied + /// + rta_access_denied, + + ////////////////////////////////////////////////////////////////////////// + // Auth errors + ////////////////////////////////////////////////////////////////////////// + + /// + /// 0x80004005 + /// xbox_live_error_code 2000 + /// Unknown auth error + /// + auth_unknown_error = 2000, + + /// + /// 0x8086000c + /// xbox_live_error_code 2001 + /// User interaction required + /// + auth_user_interaction_required, + + /// + /// 0x80070525 + /// xbox_live_error_code 2002 + /// User interaction required + /// + auth_user_switched, + + /// + /// 0x80070525 + /// xbox_live_error_code 2003 + /// User cancelled + /// + auth_user_cancel, + + /// + /// 0x80070525 + /// xbox_live_error_code 2004 + /// User not signed in + /// + auth_user_not_signed_in, + + /// + /// 0x80004005 + /// xbox_live_error_code 2005 + /// Auth runtime error + /// + auth_runtime_error, + + /// + /// 0x80070525 + /// xbox_live_error_code 2006 + /// Auth no token error + /// + auth_no_token_error, + + ////////////////////////////////////////////////////////////////////////// + // Xbox Live SDK errors + ////////////////////////////////////////////////////////////////////////// + /// + /// 0x8007064a + /// xbox_live_error_code 3000 + /// Could not read the xboxservices.config. Ensure it is deployed in the package at + /// Windows::ApplicationModel::Package::Current->InstalledLocation + "\xboxservices.config" + /// + invalid_config = 3000, + + /// + /// 0x80004001 + /// xbox_live_error_code 3001 + /// API is not supported + /// + unsupported = 3001, + + ////////////////////////////////////////////////////////////////////////// + // xbox live auth errors + ////////////////////////////////////////////////////////////////////////// + /// + /// 0x80072EE2 + /// This error is typically returned by Xbox::Services APIs, GetTokenAndSignatureAsync, + /// and CheckLicense. It indicates that the Internet connection or a server response was + /// interrupted; possibly the result of a incorrectly configured NSAL. Pending requests + /// should be retried when this error is encountered. + /// + HR_ERROR_INTERNET_TIMEOUT = (int)0x80072EE2, + + /// + /// 0x87DD0003 + /// XASD returned an unexpected response. + /// + AM_E_XASD_UNEXPECTED = (int)0x87DD0003, + + /// + /// 0x87DD0004 + /// XASU returned an unexpected response. + /// + AM_E_XASU_UNEXPECTED = (int)0x87DD0004, + + /// + /// 0x87DD0005 + /// XAST returned an unexpected response. + /// Cause: Your NSAL configuration is set up correctly for your service, however the + /// Relying Party certificate is not yet trusted by Xbox Live. + /// + /// Resolution : Relying Party configuration on XDP and provide the Relying Party + /// certificate in the XSTS token certificate for your endpoint. + /// If you are using the NSAL.json file, double check that the Relying Party name is + /// correct in the 'target' field of your NSAL.json file on the console and ensure that + /// the certificate has been specified in XDP. + /// + /// If you are developing a UWP title and performing service configuration in XDP, then + /// you may have not completed the Application ID binding step correctly. For more + /// information, please see the "Troubleshooting Sign-in" article in the Xbox Live documentation. + /// + AM_E_XAST_UNEXPECTED = (int)0x87DD0005, + + /// + /// 0x87DD0006 + /// Cause : Your NSAL configuration is set up correctly for your service, however the + /// Relying Party certificate is not yet trusted by Xbox Live. + /// + /// Resolution : Relying Party configuration on XDP and provide the Relying Party + /// certificate in the XSTS token certificate for your endpoint. + /// If you are using the NSAL.json file, double check that the Relying Party name is + /// correct in the 'target' field of your NSAL.json file on the console and ensure + /// that the certificate has been specified in XDP. + /// + AM_E_XSTS_UNEXPECTED = (int)0x87DD0006, + + /// + /// 0x87DD0007 + /// XDevice returned an unexpected response. + /// + AM_E_XDEVICE_UNEXPECTED = (int)0x87DD0007, + + /// + /// 0x87DD0008 + /// The console is not authorized to enable development mode. + /// + AM_E_DEVMODE_NOT_AUTHORIZED = (int)0x87DD0008, + + /// + /// 0x87DD0009 + /// The operation was not authorized. + /// Cause: The user is not authorized to get an XSTS token with the current TitleID or + /// SandboxID setup on the console for the provided URL. + /// + /// Resolution: + /// Ensure that your console is in the proper SandboxID for the TitleID you are using. + /// See this forum thread for instructions on changing your SandboxID and which SandboxID + /// to use for samples. + /// + /// Ensure that the test account you are using is partitioned to a group in XDP that has + /// access to the TitleID and SandboxID for your title(Note that all accounts are able to + /// access the samples while in the sample SandboxID). + /// + AM_E_NOT_AUTHORIZED = (int)0x87DD0009, + + /// + /// 0x87DD000A + /// The operation was forbidden. The server responded with a 403, and a more detailed error is not available. + /// + AM_E_FORBIDDEN = (int)0x87DD000A, + + /// + /// 0x87DD000B + /// The URL specified does not match a known target. + /// + /// Cause: + /// The URL you are attempting to get a token for was not found within your NSAL configuration. + /// + /// Resolution: + /// Ensure that the Relying Party and server name are properly set up as an endpoint + /// on your console and in your NSAL. + /// + /// Try calling a known Xbox Service such as https ://social.xboxlive.com/users/xuid(user's xuid)/people + /// to ensure that you can get tokens for the Xbox services. If you are using the NSAL.json file, make sure + /// that the 'target' field in the file has your Relying Party name ending with '/' and + /// that the server name is set up correctly. + /// + AM_E_UNKNOWN_TARGET = (int)0x87DD000B, + + /// + /// 0x87DD000C + /// There were problems with the JSON data downloaded from the server. + /// + AM_E_INVALID_NSAL_DATA = (int)0x87DD000C, + + /// + /// 0x87DD000D + /// The title has not yet been successfully authenticated. + /// Cause: This will be returned when a title token is required, but has not been cached. For example, + /// attempting to retrieve an X token with title claims will fail with this error if AuthenticateTitle + /// hasn't been called successfully. + /// + /// Resolution: Check your TitleID, SOCID, and SandboxID, or check your title's configuration on XDP. + /// + AM_E_TITLE_NOT_AUTHENTICATED = (int)0x87DD000D, + + /// + /// 0x87DD000E + /// XAST returned 401 when attempting to retrieve the T token. Double-check that your device is set to the + /// proper development sandbox and that the user has access to the sandbox. + /// + /// For more information, please see the "Troubleshooting Sign-in" article in the Xbox Live documentation. + /// + AM_E_TITLE_NOT_AUTHORIZED = (int)0x87DD000E, + + /// + /// 0x87DD0011 + /// The user hash value for the specified user hasn't been recorded, so a valid token can't be generated. + /// + AM_E_USER_HASH_MISSING = (int)0x87DD0011, + + /// + /// 0x87DD0013 + /// The Authentication Manager can't find the user for which an authentication token is being retrieved. + /// One possible scenario is that the User signed out, but the title still has a reference to the User object. + /// + AM_E_USER_NOT_FOUND = (int)0x87DD0013, + + /// + /// 0x87DD0015 + /// The environment configured or specified is not valid. + /// + AM_E_INVALID_ENVIRONMENT = (int)0x87DD0015, + + /// + /// 0x87DD0016 + /// The XASD authentication server has timed out. + /// + AM_E_XASD_TIMEOUT = (int)0x87DD0016, + + /// + /// 0x87DD0017 + /// The XASU authentication server has timed out. + /// + AM_E_XASU_TIMEOUT = (int)0x87DD0017, + + /// + /// 0x87DD0018 + /// The XAST authentication server has timed out. + /// + AM_E_XAST_TIMEOUT = (int)0x87DD0018, + + /// + /// 0x87DD0019 + /// The XSTS authentication server has timed out. + /// + AM_E_XSTS_TIMEOUT = (int)0x87DD0019, + + /// + /// 0x87DD001A + /// Title authentication failed because a connection to Xbox Live is required, by policy, and none is present. + /// + AM_E_LIVE_CONNECTION_REQUIRED = (int)0x87DD001A, + + /// + /// 0x87dd001e + /// There is no network connection. + /// + AM_E_NO_NETWORK = (int)0x87dd001e, + + /// + /// 0x87dd0020 + /// The Network Security Authorization List(NSAL) returned an unexpected response. + /// + AM_E_XTITLE_UNEXPECTED = (int)0x87dd0020, + + /// + /// 0x87dd0021 + /// The endpoint does not require an authorization token, but the application is attempting to + /// retrieve a token via GetTokenAndSignatureAsync. + /// + AM_E_NO_TOKEN_REQUIRED = (int)0x87dd0021, + + /// + /// 0x87dd0022 + /// Timeouts were received from the various authorization servers. + /// + AM_E_XTITLE_TIMEOUT = (int)0x87dd0022, + + /// + /// 0x8015DC00 + /// Developer mode is not authorized for the client device. + /// + XO_E_DEVMODE_NOT_AUTHORIZED = (int)0x8015DC00, + + /// + /// 0x8015DC01 + /// A system update is required before this action can be performed. + /// + XO_E_SYSTEM_UPDATE_REQUIRED = (int)0x8015DC01, + + /// + /// 0x8015DC02 + /// A content update is required before this action can be performed. + /// + XO_E_CONTENT_UPDATE_REQUIRED = (int)0x8015DC02, + + /// + /// 0x8015DC03 + /// The device or user was banned. + /// + XO_E_ENFORCEMENT_BAN = (int)0x8015DC03, + + /// + /// 0x8015DC04 + /// The device or user was banned. + /// + XO_E_THIRD_PARTY_BAN = (int)0x8015DC04, + + /// + /// 0x8015DC05 + /// Access to this resource has been parentally restricted. + /// + XO_E_ACCOUNT_PARENTALLY_RESTRICTED = (int)0x8015DC05, + + /// + /// 0x8015DC08 + /// Access to this resource requires that the account billing information + /// is updated. + /// + XO_E_ACCOUNT_BILLING_MAINTENANCE_REQUIRED = (int)0x8015DC08, + + /// + /// 0x8015DC0A + /// The user has not accepted the terms of use for this resource. + /// + XO_E_ACCOUNT_TERMS_OF_USE_NOT_ACCEPTED = (int)0x8015DC0A, + + /// + /// 0x8015DC0B + /// This resource is not available in the country associated with the user. + /// + XO_E_ACCOUNT_COUNTRY_NOT_AUTHORIZED = (int)0x8015DC0B, + + /// + /// 0x8015DC0C + /// Access to this resource requires age verification. + /// + XO_E_ACCOUNT_AGE_VERIFICATION_REQUIRED = (int)0x8015DC0C, + + /// + /// 0x8015DC0D + /// + XO_E_ACCOUNT_CURFEW = (int)0x8015DC0D, + + /// + /// 0x8015DC0E + /// + XO_E_ACCOUNT_CHILD_NOT_IN_FAMILY = (int)0x8015DC0E, + + /// + /// 0x8015DC0F + /// + XO_E_ACCOUNT_CSV_TRANSITION_REQUIRED = (int)0x8015DC0F, + + /// + /// 0x8015DC09 + /// + XO_E_ACCOUNT_CREATION_REQUIRED = (int)0x8015DC09, + + /// + /// 0x8015DC10 + /// + XO_E_ACCOUNT_MAINTENANCE_REQUIRED = (int)0x8015DC10, + + /// + /// 0x8015DC11 + /// The call was blocked because there was a conflict with the sandbox, console, application, or + /// your account.Verify your account, console and title settings in XDP, and check the current + /// Sandbox on the device. + /// + XO_E_ACCOUNT_TYPE_NOT_ALLOWED = (int)0x8015DC11, + + /// + /// 0x8015DC12 + /// Your device does not have access to the Sandbox it is set to, or the account you are signed + /// in with does not have access to the Sandbox.Check that you are using the correct Sandbox. + /// + /// Note: All XDK samples use XDKS.1 SandboxID, which allow all user accounts to access and run + /// the samples.SandboxID's are case sensitive- Not matching the case of your SandboxID exactly may + /// result in errors. If you are still having issues running the sample, please work with your + /// Developer Account Manager and provide a fiddler trace to help with troubleshooting. + /// + /// For more information on handling this error, please see the "Troubleshooting Sign-in" article + /// in the Xbox Live documentation + /// + XO_E_CONTENT_ISOLATION = (int)0x8015DC12, + + /// + /// 0x8015DC13 + /// + XO_E_ACCOUNT_NAME_CHANGE_REQUIRED = (int)0x8015DC13, + + /// + /// 0x8015DC14 + /// + XO_E_DEVICE_CHALLENGE_REQUIRED = (int)0x8015DC14, + + /// + /// 0x8015DC16 + /// The account was signed in on another device. + /// + XO_E_SIGNIN_COUNT_BY_DEVICE_TYPE_EXCEEDED = (int)0x8015DC16, + + /// + /// 0x8015DC17 + /// + XO_E_PIN_CHALLENGE_REQUIRED = (int)0x8015DC17, + + /// + /// 0x8015DC18 + /// + XO_E_RETAIL_ACCOUNT_NOT_ALLOWED = (int)0x8015DC18, + + /// + /// 0x8015DC19 + /// The current sandbox is not allowed to access the SCID. Please ensure that your current + /// sandbox is set to your development sandbox. If you are running on a Windows 10 PC, then + /// you can change your current sandbox using the SwitchSandbox.cmd script in the Xbox Live SDK + /// tools directory. If you are using an Xbox One, you can switch the sandbox using Xbox One + /// Manager. + /// + /// For more information on handling this error, please see the "Troubleshooting Sign-in" article + /// in the Xbox Live documentation. + /// + XO_E_SANDBOX_NOT_ALLOWED = (int)0x8015DC19, + + /// + /// 0x8015DC1A + /// + XO_E_ACCOUNT_SERVICE_UNAVAILABLE_UNKNOWN_USER = (int)0x8015DC1A, + + /// + /// 0x8015DC1B + /// + XO_E_GREEN_SIGNED_CONTENT_NOT_AUTHORIZED = (int)0x8015DC1B, + + /// + /// 0x8015DC1C + /// + XO_E_CONTENT_NOT_AUTHORIZED = (int)0x8015DC1C, + + ////////////////////////////////////////////////////////////////////////// + // Generic errors + ////////////////////////////////////////////////////////////////////////// + + /// + /// 0x800C0002 + /// The URL is invalid. + /// + HR_INET_E_INVALID_URL = (int)0x800C0002, + + /// + /// 0x800C0003 + /// No session. + /// + HR_INET_E_NO_SESSION = (int)0x800C0003, + + /// + /// 0x800C0004 + /// WinINet cannot connect to the requested resource. + /// + HR_INET_E_CANNOT_CONNECT = (int)0x800C0004, + + /// + /// 0x800C0005 + /// The requested resource was not found. + /// + HR_INET_E_RESOURCE_NOT_FOUND = (int)0x800C0005, + + /// + /// 0x800C0006 + /// The requested resource was not found. + /// + HR_INET_E_OBJECT_NOT_FOUND = (int)0x800C0006, + + /// + /// 0x800C0007 + /// The requested resource was not found. + /// + HR_INET_E_DATA_NOT_AVAILABLE = (int)0x800C0007, + + /// + /// 0x800C0008 + /// Operation restricted by the current inability to discover or join the multiplayer session, or + /// the player does not have the multiplayer privilege. + /// + HR_INET_E_DOWNLOAD_FAILURE = (int)0x800C0008, + + /// + /// 0x800C0009 + /// Authentication is required to access this resource. + /// + HR_INET_E_AUTHENTICATION_REQUIRED = (int)0x800C0009, + + /// + /// 0x800C000A + /// No valid media + /// + HR_INET_E_NO_VALID_MEDIA = (int)0x800C000A, + + /// + /// 0x800C000B + /// The connection has timed out. + /// + HR_INET_E_CONNECTION_TIMEOUT = (int)0x800C000B, + + /// + /// 0x800C000C + /// Invalid request + /// + HR_INET_E_INVALID_REQUEST = (int)0x800C000C, + + /// + /// 0x800C000D + /// The requested protocol is unknown. + /// + HR_INET_E_UNKNOWN_PROTOCOL = (int)0x800C000D, + + /// + /// 0x800C000E + /// Security problem + /// + HR_INET_E_SECURITY_PROBLEM = (int)0x800C000E, + + /// + /// 0x800C000F + /// Cannot load data + /// + HR_INET_E_CANNOT_LOAD_DATA = (int)0x800C000F, + + /// + /// 0x800C0010 + /// Cannot instantiate object + /// + HR_INET_E_CANNOT_INSTANTIATE_OBJECT = (int)0x800C0010, + + /// + /// 0x800C0019 + /// The certificate presented for the request is invalid. + /// + HR_INET_E_INVALID_CERTIFICATE = (int)0x800C0019, + + /// + /// 0x800C0014 + /// The redirect to a different endpoint has failed. + /// + HR_INET_E_REDIRECT_FAILED = (int)0x800C0014, + + /// + /// 0x800C0015 + /// A resource request has been directed to a directory rather than an individual resource. + /// + HR_INET_E_REDIRECT_TO_DIR = (int)0x800C0015, + + /// + /// 0x800704cf + /// The network location cannot be reached. + /// + HR_ERROR_NETWORK_UNREACHABLE = (int)0x800704cf + }; + + /// + /// Category error type for XSAPI error codes. + /// + class xbox_services_error_code_category_impl : public std::error_category + { + public: + /// + /// Gets the error category name. + /// + /// A string identifying the category. + _XSAPIIMP const char* name() const _NOEXCEPT override { return "XBL"; } + + /// + /// Converts an error value into a string that describes the error. + /// + /// A string that describes the error. + _XSAPIIMP std::string message(_In_ int errorCode) const _NOEXCEPT override; + }; + + /// + /// Category error type for XSAPI error conditions. + /// + class xbox_services_error_condition_category_impl : public std::error_category + { + public: + /// + /// Gets the error category name. + /// + /// A string identifying the category. + _XSAPIIMP const char* name() const _NOEXCEPT override { return "XBL CONDITION"; } + + /// + /// Converts an error value into a string that describes the error. + /// + /// A string that describes the error. + _XSAPIIMP std::string message(_In_ int errorCode) const _NOEXCEPT override; + + /// + /// Used to establish equivalence between arbitrary error_codes in + /// the current category with arbitrary error_conditions. + /// + /// An error code. + /// An error condition. + /// True if the error code and the error condition are related; otherwise false. + _XSAPIIMP bool equivalent( + _In_ const std::error_code& arbitraryErrorCode, + _In_ int xboxLiveErrorCondition) const _NOEXCEPT override; + }; + + /// + /// Gets the one global instance of the error code category. + /// + /// An error category instance. + _XSAPIIMP const xbox_services_error_code_category_impl& xbox_services_error_code_category(); + + /// + /// Gets the one global instance of the error condition category. + /// + /// An error category instance. + _XSAPIIMP const xbox_services_error_condition_category_impl& xbox_services_error_condition_category(); + } +}; + +#if XSAPI_U +namespace xbox { + namespace services { + inline std::error_code make_error_code(xbox::services::xbox_live_error_code e) + { + return std::error_code(static_cast(e), xbox::services::xbox_services_error_code_category()); + } + + inline std::error_condition make_error_condition(xbox::services::xbox_live_error_condition e) + { + return std::error_condition(static_cast(e), xbox::services::xbox_services_error_condition_category()); + } + } +} +#endif + +namespace std +{ + inline std::error_code make_error_code(xbox::services::xbox_live_error_code e) + { + return std::error_code(static_cast(e), xbox::services::xbox_services_error_code_category()); + } + + inline std::error_condition make_error_condition(xbox::services::xbox_live_error_condition e) + { + return std::error_condition(static_cast(e), xbox::services::xbox_services_error_condition_category()); + } + + template <> + struct is_error_code_enum : public true_type{}; + + template <> + struct is_error_condition_enum : public true_type{}; +} + +namespace xbox { namespace services { + +template +class xbox_live_result +{ +public: + xbox_live_result(); + xbox_live_result(_In_ T payload); + xbox_live_result(_In_ std::error_code errorCode, _In_ std::string errorMessage = std::string()); + xbox_live_result(_In_ T payload, _In_ std::error_code errorCode, _In_ std::string errorMessage = std::string()); + + xbox_live_result(_In_ const xbox_live_result&); + xbox_live_result& operator=(_In_ const xbox_live_result&); + xbox_live_result(_In_ xbox_live_result&& other); + xbox_live_result& operator=(_In_ xbox_live_result&& other); + + /// + /// The payload of the result. It may be empty if there was an error + /// + _XSAPIIMP T& payload(); + + /// + /// The payload of the result. It may be empty if there was an error + /// + _XSAPIIMP const T& payload() const; + + /// + /// Sets the payload. + /// + _XSAPIIMP void set_payload(T payload); + + /// + /// The error returned by the operation. + /// To test for and potentially react to in your code, use the values in xbox_error_condition + /// To see the specific error value returned by the operation, use err_code().value() but testing for these values is discouraged. + /// For more detail about std::error_code vs std::error_condition, see + /// http://en.cppreference.com/w/cpp/error/error_condition + /// + _XSAPIIMP const std::error_code& err() const; + + /// + /// Sets the error. + /// To test for and potentially react to in your code, use the values in xbox_error_condition + /// To see the specific error value returned by the operation, use err_code().value() but testing for these values is discouraged. + /// For more detail about std::error_code vs std::error_condition, see + /// http://en.cppreference.com/w/cpp/error/error_condition + /// + void _Set_err(std::error_code errc); + + /// + /// Returns call specific debug information. + /// It is not localized, so only use for debugging purposes. + /// + _XSAPIIMP const std::string& err_message() const; + + /// + /// Sets error code debug information. + /// It is not localized, so only use for debugging purposes. + /// + void _Set_err_message(std::string errMessage); + +private: + T m_payload; + std::error_code m_errorCode; + std::string m_errorMessage; +}; + +template<> +class xbox_live_result +{ +public: + xbox_live_result() + : m_errorMessage(std::string()) + { + m_errorCode = std::make_error_code(xbox_live_error_code::no_error); + } + + xbox_live_result(_In_ std::error_code errorCode, _In_ std::string errorMessage = std::string()) : + m_errorCode(std::move(errorCode)), + m_errorMessage(std::move(errorMessage)) + { + } + + xbox_live_result(_In_ const xbox_live_result& other) + { + *this = other; + } + + xbox_live_result& operator=(_In_ const xbox_live_result& other) + { + m_errorCode = other.m_errorCode; + m_errorMessage = other.m_errorMessage; + return *this; + } + + xbox_live_result(_In_ xbox_live_result&& other) + { + *this = std::move(other); + } + + xbox_live_result& operator=(_In_ xbox_live_result&& other) + { + if (this != &other) + { + m_errorCode = std::move(other.m_errorCode); + m_errorMessage = std::move(other.m_errorMessage); + } + + return *this; + } + + /// + /// The error returned by the operation. + /// To test for and potentially react to in your code, use the values in xbox_error_condition + /// To see the specific error value returned by the operation, use err_code().value() but testing for these values is discouraged. + /// For more detail about std::error_code vs std::error_condition, see + /// http://en.cppreference.com/w/cpp/error/error_condition + /// + _XSAPIIMP const std::error_code& err() + { + return m_errorCode; + } + + /// + /// Returns call specific debug information. + /// It is not localized, so only use for debugging purposes. + /// + _XSAPIIMP const std::string& err_message() + { + return m_errorMessage; + } + + /// + /// Returns call specific debug information. + /// It is not localized, so only use for debugging purposes. + /// + void _Set_err(std::error_code errCode) + { + m_errorCode = std::move(errCode); + } + + /// + /// Sets error code debug information. + /// It is not localized, so only use for debugging purposes. + /// + void _Set_err_message(std::string errMessage) + { + m_errorMessage = std::move(errMessage); + } + +private: + std::error_code m_errorCode; + std::string m_errorMessage; +}; + +template +xbox_live_result::xbox_live_result() : + m_errorCode(xbox_live_error_code::no_error), + m_errorMessage(std::string()) +{ +} + +template +xbox_live_result::xbox_live_result(_In_ T payload) : + m_payload(std::move(payload)), + m_errorCode(xbox_live_error_code::no_error), + m_errorMessage(std::string()) +{ +} + +template +xbox_live_result::xbox_live_result( + _In_ std::error_code errorCode, + _In_ std::string errorMessage + ) : + m_errorCode(std::move(errorCode)), + m_errorMessage(std::move(errorMessage)) +{ +} + +template +xbox_live_result::xbox_live_result( + _In_ T payload, + _In_ std::error_code errorCode, + _In_ std::string errorMessage + ) : + m_payload(std::move(payload)), + m_errorCode(std::move(errorCode)), + m_errorMessage(std::move(errorMessage)) +{ +} + +template +T& xbox_live_result::payload() +{ + return m_payload; +} + +template +const T& xbox_live_result::payload() const +{ + return m_payload; +} + +template +void xbox_live_result::set_payload(T payload) +{ + m_payload = std::move(payload); +} + +template +const std::error_code& xbox_live_result::err() const +{ + return m_errorCode; +} + +template +void xbox_live_result::_Set_err(std::error_code errCode) +{ + m_errorCode = std::move(errCode); +} + +template +const std::string& xbox_live_result::err_message() const +{ + return m_errorMessage; +} + +template +void xbox_live_result::_Set_err_message(std::string errorMsg) +{ + m_errorMessage = std::move(errorMsg); +} + +template +xbox_live_result::xbox_live_result(_In_ const xbox_live_result& other) +{ + *this = other; +} + +template +xbox_live_result& +xbox_live_result::operator=(_In_ const xbox_live_result& other) +{ + m_payload = other.m_payload; + m_errorCode = other.m_errorCode; + m_errorMessage = other.m_errorMessage; + return *this; +} + +template +xbox_live_result::xbox_live_result(_In_ xbox_live_result&& other) +{ + *this = std::move(other); +} + +template +xbox_live_result& xbox_live_result::operator=(_In_ xbox_live_result&& other) +{ + if (this != &other) + { + m_payload = std::move(other.m_payload); + m_errorCode = std::move(other.m_errorCode); + m_errorMessage = std::move(other.m_errorMessage); + } + + return *this; +} + +}} + diff --git a/Include/xsapi/events.h b/Include/xsapi/events.h new file mode 100644 index 00000000..9c63b0ab --- /dev/null +++ b/Include/xsapi/events.h @@ -0,0 +1,100 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#if UWP_API || XSAPI_U +namespace xbox { namespace services { + /// + /// Contains classes that let you send an in-game event. + /// + namespace events { + + /// +/// Represents a service class that provides APIs that you can use to write in-game events. +/// +class events_service +{ +public: + events_service() {}; + + events_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr localConfig + ); + + /// + /// Write a simple in-game event without providing any data fields. + /// + /// Event name + /// + /// The name of the event must match the event name declared in the title's service configuration. + /// The names are case insensitive. + /// If the API writes an event with a name that does not match a name in the service configuration, the + /// service drops the event with no notification. + /// + _XSAPIIMP xbox_live_result write_in_game_event(_In_ const string_t& eventName); + + /// + /// Write an in-game event that includes "dimensions" and "measurement" data fields. + /// + /// Dimensions include event fields with a finite number of defined numeric or string values. + /// Examples of dimensions: map id, difficulty level, character or weapon class, game mode, boolean settings, etc. + /// + /// Measurements include event fields that represent scalar numeric metrics. + /// Examples of measurements: score, time, counters, position, etc. + /// + /// Example: for an in-game event that tracks the highest match score for a particular difficulty level: + /// The difficulty level should be included in dimensions, and the score should be included in measurements. + /// + /// Event name + /// Dimensions data fields + /// Measurement data fields + /// + /// The name of the event, and the names of the event fields (both dimensions and measurements), must match + /// the names declared in the title's service configuration. The names are case insensitive. + /// If the API writes an event with a name that does not match a name in the service configuration, the + /// service drops the event with no notification. + /// + _XSAPIIMP xbox_live_result write_in_game_event( + _In_ const string_t& eventName, + _In_ const web::json::value& dimensions, + _In_ const web::json::value& measurement + ); + +private: + std::shared_ptr m_userContext; + std::shared_ptr m_appConfig; + + string_t m_playSession; +#if UWP_API + string_t m_appInsightsKey; + + void add_value_pair( + _In_ Windows::Foundation::Diagnostics::LoggingFields^ fields, + _In_ const std::pair& pair + ); + + Windows::Foundation::Diagnostics::LoggingFields^ create_logging_field( + _In_ const string_t& eventName, + _In_ const web::json::value& properties, + _In_ const web::json::value& measurement + ); + + string_t load_app_insights_key(); + + void add_common_logging_field(_In_ Windows::Foundation::Diagnostics::LoggingFields^ fields); + Windows::Foundation::Diagnostics::LoggingOptions^ m_loggingOptions; + Windows::Foundation::Diagnostics::LoggingChannel^ m_loggingChannel; +#endif +}; + +}}} + +#endif \ No newline at end of file diff --git a/Include/xsapi/game_server_platform.h b/Include/xsapi/game_server_platform.h new file mode 100644 index 00000000..77ad6d56 --- /dev/null +++ b/Include/xsapi/game_server_platform.h @@ -0,0 +1,920 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Classes for managing and referencing server resources allocated by the game server platform. + /// + namespace game_server_platform { + +/// Defines a set of values used to indicate the the fulfillment state. +enum class game_server_fulfillment_state +{ + /// The fulfillment state is unknown. + unknown, + + /// Indicates that the allocate cluster request is fulfilled and the cluster is available. + fulfilled, + + /// Indicates that the allocate cluster request is queued. + queued, + + /// Indicates that the cluster request was aborted. This will only be returned if "abortIfQueued" is set to true. + aborted +}; + +/// Defines a set of values used to indicate the host state. +enum class game_server_host_status +{ + /// The fulfillment state is unknown. + unknown, + + /// Indicates that the cluster request is active. + active, + + /// Indicates that the cluster request is queued. + queued, + + /// Indicates that the cluster request was aborted. This will only be returned if "abortIfQueued" is set to true. + aborted, + + /// Indicates that the cluster request had an error. + error +}; + +/// +/// Represents a mapping between the port numbers requested for the game server to use, and the port numbers exposed by load-balancing hardware. +/// +class game_server_port_mapping +{ + // Example: + // "portMappings": { + // "GameData1": { + // "internal": 8347, + // "external": 30002 + // }, + // "GameData2": { + // "internal": 8348, + // "external": 31002 + // }, + // "Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp": { + // "internal": 3389, + // "external": 3389 + // }, + // "Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput": { + // "internal": 20000, + // "external": 3389 + // } + // } + +public: + game_server_port_mapping(); + + /// + /// Internal function + /// + game_server_port_mapping( + _In_ string_t portName, + _In_ uint32_t internalPortNumber, + _In_ uint32_t externalPortNumber + ); + + /// + /// The name of the port, which is specified in your Azure project cscfg. + /// + _XSAPIIMP const string_t& port_name() const; + + /// + /// The internal port number for the named port. This is the port that the server will open using the socket API. + /// + _XSAPIIMP uint32_t internal_port_number() const; + + /// + /// The external port number clients should use when connecting. This port is mapped by networking hardware to the internal port number. + /// + _XSAPIIMP uint32_t external_port_number() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_portName; + uint32_t m_internalPortNumber; + uint32_t m_externalPortNumber; +}; + +/// +/// Represents a game server cluster result. +/// +class cluster_result +{ +public: + cluster_result(); + + /// + /// Internal function + /// + cluster_result( + _In_ std::chrono::milliseconds pollInterval, + _In_ game_server_fulfillment_state fulfillmentState, + _In_ string_t hostName, + _In_ string_t region, + _In_ std::vector< game_server_port_mapping > portMappings, + _In_ string_t secureDeviceAddress + ); + + /// + /// Recommended interval to poll for completion. Note that this is not an estimate of when + /// the cluster will be ready, but rather a recommendation for how frequently the caller should + /// poll for a session status update. + /// + _XSAPIIMP const std::chrono::milliseconds& poll_interval() const; + + /// + /// Indicates if the cluster is available if or the caller should wait or if the request was aborted. + /// + _XSAPIIMP game_server_fulfillment_state fulfillment_state() const; + + /// + /// The host name of the cluster. + /// + _XSAPIIMP const string_t& host_name() const; + + /// + /// The region of the cluster. + /// + _XSAPIIMP const string_t& region() const; + + /// + /// The port mappings of the cluster. + /// + _XSAPIIMP const std::vector< game_server_port_mapping >& port_mappings() const; + + /// + /// The secure context which is the secure device address of the cluster + /// + _XSAPIIMP const string_t& secure_device_address() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + static game_server_fulfillment_state convert_string_to_fulfillment_state(_In_ const string_t& value); + + std::chrono::milliseconds m_pollInterval; + game_server_fulfillment_state m_fulfillmentState; + string_t m_secureDeviceAddress; + string_t m_hostName; + string_t m_region; + std::vector< game_server_port_mapping > m_portMappings; +}; + +/// +/// Represents status information for the allocation request previously sent to the game server. +/// +class game_server_ticket_status +{ + // Example: + // { + // "ticketId": "12341234-1234-1234-1234-123412341234", + // "clusterId": "12341234-1234-1234-1234-123412341234", + // "titleId": "1234", + // "hostName": "cloudapp.net", + // "status": "Active", + // "description": "", + // "secureContext": "", + // "portMappings": {}, + // "gameHostId": "abc.Cloud.Gaming.Bootstrap_IN_0.0" + // "region": "Central US" + // } + +public: + /// + /// Internal function + /// + game_server_ticket_status(); + + /// + /// Internal function + /// + game_server_ticket_status( + _In_ string_t ticket_id, + _In_ string_t cluster_id, + _In_ uint32_t title_id, + _In_ string_t host_name, + _In_ game_server_host_status status, + _In_ string_t description, + _In_ string_t secure_context, + _In_ std::vector< game_server_port_mapping > port_mappings, + _In_ string_t game_host_id, + _In_ string_t region + ); + + /// + /// The ID of the ticket whose status is being checked. + /// + _XSAPIIMP const string_t& ticket_id() const; + + /// + /// The cluster ID of the server allocated for this ticket. + /// + _XSAPIIMP const string_t& cluster_id() const; + + /// + /// The title ID of the requesting title. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The host name of the server which was allocated to support this request. + /// + _XSAPIIMP const string_t& host_name() const; + + /// + /// The status of the server. + /// + _XSAPIIMP game_server_host_status status() const; + + /// + /// Description of the allocation request. + /// + _XSAPIIMP const string_t& description() const; + + /// + /// The secure device address information for the assigned server. + /// + _XSAPIIMP const string_t& secure_context() const; + + /// + /// The list of GameServerPortMapping for this server. + /// + _XSAPIIMP std::vector< game_server_port_mapping > port_mappings() const; + + /// + /// The ID of the game host. + /// + _XSAPIIMP const string_t& game_host_id() const; + + /// + /// The region of the game host. + /// + _XSAPIIMP const string_t& region() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + static game_server_host_status convert_string_to_host_status(_In_ const string_t& value); + + string_t m_ticketId; + string_t m_clusterId; + uint32_t m_titleId; + string_t m_hostName; + game_server_host_status m_status; + string_t m_description; + string_t m_secureContext; + std::vector< game_server_port_mapping > m_portMappings; + string_t m_gameHostId; + string_t m_region; +}; + +/// +/// Represents a game variant schema. +/// +class game_variant_schema +{ + // Example: + // { + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // "schemaContent":"\r\n \r\n\r\n \r\n ", + // "name":"Example Variant" + // } + +public: + /// + /// Internal function + /// + game_variant_schema(); + + /// + /// Internal function + /// + game_variant_schema( + _In_ string_t schema_id, + _In_ string_t schema_content, + _In_ string_t schema_name + ); + + /// + /// ID of a schema. + /// + _XSAPIIMP const string_t& schema_id() const; + + /// + /// Content of the schema. + /// + _XSAPIIMP const string_t& schema_content() const; + + /// + /// Name of the schema. + /// + _XSAPIIMP const string_t& schema_name() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_schemaId; + string_t m_schemaContent; + string_t m_schemaName; +}; + +/// +/// Represents a game variant. +/// +class game_variant +{ + // Example: + // { + // "gamevariantId":"041aae97-d359-4244-9b93-2d23ba27cd19", + // "name":"Example Variant", + // "rank":"100", + // "isPublisher":"False" + // "gameVariantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // } + +public: + /// + /// Internal function + /// + game_variant(); + + /// + /// Internal function + /// + game_variant( + _In_ string_t id, + _In_ string_t name, + _In_ bool isPublisher, + _In_ uint64_t rank, + _In_ string_t schemaId + ); + + /// + /// ID of a variant. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// Name of variant. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// A boolean field to indicate whether the variant was user-created or publisher-created. + /// + _XSAPIIMP bool is_publisher() const; + + /// + /// A boolean field to indicate whether the variant was user-created or publisher-created. + /// + _XSAPIIMP uint64_t rank() const; + + /// + /// Content of the variant's schema. + /// + _XSAPIIMP const string_t& schema_content() const; + + /// + /// Name of the variant's schema. + /// + _XSAPIIMP const string_t& schema_name() const; + + /// + /// ID of the variant's schema. + /// + _XSAPIIMP const string_t& schema_id() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + void _Set_schema(_In_ game_variant_schema schema); + +private: + string_t m_id; + string_t m_name; + bool m_isPublisher; + uint64_t m_rank; + game_variant_schema m_schema; + string_t m_schemaId; +}; + +/// +/// Represents a set of game server images. +/// +class game_server_image_set +{ + // Example: + // { + // "gsiSetId":"7efdf3a7-9ce4-4d28-b889-4aeea98727c1", + // "minRequiredPlayers":"2", + // "maxAllowedPlayers":"50", + // "selectionOrder":"1", + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806" + // "tags": + // [ + // { + // "name": "tagName1", + // "value": "tagValue1" + // }, + // { + // "name": "tagName2", + // "value": "tagValue2" + // } + // ] + // } + +public: + /// + /// Internal function + /// + game_server_image_set(); + + /// + /// Internal function + /// + game_server_image_set( + _In_ uint64_t minPlayers, + _In_ uint64_t maxPlayers, + _In_ string_t id, + _In_ string_t name, + _In_ uint64_t selectionOrder, + _In_ string_t schemaId, + _In_ std::map tags + ); + + /// + /// The minimum number of players for the variant. + /// + _XSAPIIMP const uint64_t min_players() const; + + /// + /// The maximum number of players for the variant. + /// + _XSAPIIMP uint64_t max_players() const; + + /// + /// The set ID of the variant. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// The set Name of the variant. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// Selection order for this set. + /// + _XSAPIIMP uint64_t selection_order() const; + + /// + /// Content of this set's schema. + /// + _XSAPIIMP const string_t& schema_content() const; + + /// + /// Name of this set's schema. + /// + _XSAPIIMP const string_t& schema_name() const; + + /// + /// ID of this set's schema. + /// + _XSAPIIMP const string_t& schema_id() const; + + /// + /// Tags are key value metadata on game variant that can be set at the time of ingestion and then use them as filters or additional metadata. + /// + _XSAPIIMP const std::map& tags() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + void _Set_schema(_In_ game_variant_schema schema); + +private: + uint64_t m_minPlayers; + uint64_t m_maxPlayers; + string_t m_id; + string_t m_name; + uint64_t m_selectionOrder; + string_t m_schemaId; + game_variant_schema m_schema; + std::map m_tags; +}; + +/// +/// Represents information on game server image sets and game variants. +/// +class game_server_metadata_result +{ + // Example: + //{ + // "variants" : + // [ + // { + // "gamevariantId":"041aae97-d359-4244-9b93-2d23ba27cd19", + // "name":"Example Variant", + // "rank":"100", + // "isPublisher":"False" + // "gameVariantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // } + // ], + // + // "variantSchemas" : + // [ + // { + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // "schemaContent":"\r\n \r\n\r\n \r\n ", + // "name":"Example Variant" + // } + // ], + // + // "gsiSets" : + // [ + // { + // "gsiSetId":"7efdf3a7-9ce4-4d28-b889-4aeea98727c1", + // "minRequiredPlayers":"2", + // "maxAllowedPlayers":"50", + // "selectionOrder":"1", + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806" + // "tags": + // [ + // { + // "name": "tagName1", + // "value": "tagValue1" + // }, + // { + // "name": "tagName2", + // "value": "tagValue2" + // } + // ] + // } + // ] + //} + +public: + /// + /// Internal function + /// + game_server_metadata_result(); + + /// + /// Internal function + /// + game_server_metadata_result( + _In_ std::vector< game_variant > gameVariants, + _In_ std::vector< game_variant_schema > gameVariantSchemas, + _In_ std::vector< game_server_image_set > gameServerImageSets + ); + + /// + /// The collection of game variants. + /// + _XSAPIIMP const std::vector< game_variant >& game_variants(); + + /// + /// The collection of game server image sets. + /// + _XSAPIIMP const std::vector< game_server_image_set >& game_server_image_sets() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::vector< game_variant > m_gameVariants; + std::vector< game_variant_schema > m_gameVariantSchemas; + std::vector< game_server_image_set > m_gameServerImageSets; +}; + +/// +/// Represents the server used to measure network quality of service (QoS) for the session. +/// +class quality_of_service_server +{ + // Example: + // + // { + // "qosServers" : + // [ + // { + // "serverFqdn":"microsoft.com", + // "serverSecureDeviceAddress":"r5Y=", + // "targetLocation":"North Central US" + // }, + // { + // "serverFqdn":"microsoft.com", + // "serverSecureDeviceAddress":"r5Y=", + // "targetLocation":"West US" + // } + // ] + // } + +public: + /// + /// Internal function + /// + quality_of_service_server(); + + /// + /// Internal function + /// + quality_of_service_server( + _In_ string_t serverFullQualifiedDomainName, + _In_ string_t secureDeviceAddressBase64, + _In_ string_t targetLocation + ); + + /// + /// The full qualified domain name of the server. + /// + _XSAPIIMP const string_t& server_full_qualified_domain_name() const; + + /// + /// The secure device address in base64 of the server. + /// + _XSAPIIMP const string_t& secure_device_address_base64() const; + + /// + /// The target location. + /// + _XSAPIIMP const string_t& target_location() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_serverFullQualifiedDomainName; + string_t m_secureDeviceAddressBase64; + string_t m_targetLocation; +}; + + +class allocation_result +{ +public: + /// + /// Internal function + /// + allocation_result(); + + /// + /// Internal function + /// + allocation_result( + _In_ game_server_fulfillment_state fulfillmentState, + _In_ string_t hostName, + _In_ string_t sessionHostId, + _In_ string_t region, + _In_ std::vector< game_server_port_mapping > portMappings, + _In_ string_t secureDeviceAddress + ); + + /// + /// Indicates if the allocation is available + /// + _XSAPIIMP game_server_fulfillment_state fulfillment_state() const; + + /// + /// The host name of the session host + /// + _XSAPIIMP const string_t& host_name() const; + + /// + /// The ID of the session host. It is responsible for hosting the session. + /// A session host can only host one session at a time, but over its life time, will host several sessions. + /// + _XSAPIIMP const string_t& session_host_id() const; + + /// + /// The region of the session host + /// + _XSAPIIMP const string_t& region() const; + + /// + /// The port mappings of the session host + /// + _XSAPIIMP const std::vector& port_mappings() const; + + /// + /// The secure device address of the session host + /// + _XSAPIIMP const string_t& secure_device_address() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + static game_server_fulfillment_state convert_string_to_fulfillment_state(_In_ const string_t& value); + + game_server_fulfillment_state m_fulfillmentState; + string_t m_hostName; + string_t m_sessionHostId; + string_t m_region; + std::vector< game_server_port_mapping > m_portMappings; + string_t m_secureDeviceAddress; +}; + + +class game_server_platform_service +{ +public: + /// + /// Allocates a new Game Server Cluster using an existing Game Server Image. + /// + /// Title ID of the game server. + /// Service configuration ID (SCID). This can come from the MatchTicket. + /// Session template name. This can come from the MatchTicket. + /// Session name. This can come from the MatchTicket. + /// Indicates if the allocate should aborted if the operation is queued. + /// ClusterResult object + /// Calls V1 POST /titles/{gameServerTitleId}/clusters. + _XSAPIIMP pplx::task> allocate_cluster( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& sessionName, + _In_ bool abortIfQueued + ); + + /// + /// Allocates a new Game Server Cluster using an existing Game Server Image, without interacting with MPSD. + /// + /// Title ID of the game server. + /// Service configuration ID (SCID). + /// The sandbox you wish the cluster to be allocated in. + /// Unique id for this request. The ticket id should be the same for all members of the group. + /// The GSI Set id to use for this request. Comes from GetGameServerMetadataAsync. + /// Which game variant to use. Comes from GetGameServerMetadataAsync. + /// The maximum players allowed by this variant. + /// Which datacenter to use for allocation. This information should come from QoS probes. + /// Indicates if the allocate should aborted if the operation is queued. + /// ClusterResult object + /// Calls V2 POST /titles/{gameServerTitleId}/inlineclusters. + _XSAPIIMP pplx::task> allocate_cluster_inline( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sandboxId, + _In_ const string_t& ticketId, + _In_ const string_t& gsiSetId, + _In_ const string_t& gameVariantId, + _In_ uint64_t maxAllowedPlayers, + _In_ const string_t& location, + _In_ bool abortIfQueued + ); + + /// + /// Allocates a new Game Server Cluster using an existing Game Server Image, without interacting with MPSD. + /// + /// Title ID of the game server. + /// Unique id for this request. The ticket id should be the same for all members of the group. + /// GameServerTicketStatus object + /// Calls V6 GET titles/{titleId}/tickets/{ticketId}/status. + _XSAPIIMP pplx::task> get_ticket_status( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& ticketId + ); + + /// + /// Retrieves a list of game variants for the specified title Id. + /// + /// The title ID. + /// The maximum players the variant allows. + /// Indicates whether to filter on publisher-created variants; otherwise user-created variants. + /// The maximum number of variants to return. + /// The locale of variants to return. (Optional) + /// Tags are key value metadata on game variant, that a game developer sets at the time of ingestion and then use it as filters or + /// additional metadata. The developer can use this value to filter which game variants they want to see. (Optional) + /// GameServerMetadataResult object + /// Calls V1 POST /titles/{titleId}/variants. + _XSAPIIMP pplx::task> get_game_server_metadata( + _In_ uint32_t titleId, + _In_ uint32_t maxAllowedPlayers, + _In_ bool publisherOnly, + _In_ uint32_t maxVariants, + _In_ const std::map& filterTags + ); + + /// + /// Retrieves a collection of Quality of Service (QoS) servers. + /// + /// A collection of QualityOfServiceServer object + /// Calls V1 GET /qosservers/ + _XSAPIIMP pplx::task>> get_quality_of_service_servers(); + + /// + /// Allocates a new session host + /// + /// Title ID of the game server + /// The ordered list of preferred location you wish the session host to be allocated from. + /// This is the caller specified identifier.It is assigned to the session host that is allocated and returned.Later on you can reference the specific sessionhost by this identifier.It must be globally unique(i.e.GUID). + /// The cloud game identifier (GUID), otherwise known as the GSI Set ID. + /// The game mode identifier otherwise known as game variant IDs. + /// This is a caller specified opaque string.It too is assign to the sessionhost and can be referenced in your game code.Use this to pass a small amount of information from the client to the server.Max size is 32KB + /// allocation_result object + /// Calls V8 POST /titles/{gameServerTitleId}/allocationStatus + _XSAPIIMP pplx::task> allocate_session_host( + _In_ uint32_t gameServerTitleId, + _In_ const std::vector& locations, + _In_ const string_t& sessionId, + _In_ const string_t& cloudGameId, + _In_opt_ const string_t& gameModeId, + _In_opt_ const string_t& sessionCookie + ); + + /// + /// Get allocation status for a previous allocate session host request + /// + /// Title ID of the game server + /// This is the caller specified identifier.It is assigned to the session host that is allocated and returned.Later on you can reference the specific sessionhost by this identifier.It must be globally unique(i.e.GUID). + /// allocation_result object + /// Calls V8 POST /titles/{gameServerTitleId}/sessionhosts + _XSAPIIMP pplx::task> get_session_host_allocation_status( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& sessionId + ); + +private: + game_server_platform_service() {} + + game_server_platform_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static string_t pathandquery_game_server_create_cluster_subpath( + _In_ uint32_t gameServerTitleId, + _In_ bool inlineAlloc + ); + + static string_t pathandquery_game_server_gamevariant_list_subpath( + _In_ uint32_t titleId + ); + + static string_t pathandquery_game_server_ticket_status_subpath( + _In_ uint32_t titleId, + _In_ const string_t& ticketId + ); + + static string_t game_server_session_id_path( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& sessionName + ); + + static string_t pathandquery_game_server_allocate_session_host_subpath( + _In_ uint32_t titleId + ); + + static string_t pathandquery_game_server_allocation_status_subpath( + _In_ uint32_t titleId, + _In_ const string_t& sessionId + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend xbox_live_context_impl; +}; + +}}} diff --git a/Include/xsapi/http_call.h b/Include/xsapi/http_call.h new file mode 100644 index 00000000..4488f5a3 --- /dev/null +++ b/Include/xsapi/http_call.h @@ -0,0 +1,362 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + +/// +/// Enumerates the type of structured data contained in the http response body. +/// +enum class http_call_response_body_type +{ + /// + /// The response body consists of a string. + /// + string_body, + + /// + /// The response body consists of a vector of bytes. + /// + vector_body, + + /// + /// The response body consists of a JavaScript Object Notation (JSON) object. + /// + json_body +}; + +// Forward declare +enum class xbox_live_api; + +/// +/// Represents an http response from the Xbox Live service. +/// +class http_call_response +{ +public: + /// + /// Internal function + /// + http_call_response( + _In_ const string_t& xboxUserId, + _In_ const std::shared_ptr& xboxLiveContextSettings, + _In_ const string_t& baseUrl, + _In_ const web::http::http_request& request, + _In_ const http_call_request_message& requestBody, + _In_ xbox_live_api xboxLiveApi, + _In_ const web::http::http_response& response + ); + +#ifndef DEFAULT_MOVE_ENABLED + http_call_response(http_call_response&& other); + http_call_response& operator=(http_call_response&& other); +#endif + + /// + /// Gets the body type of the response. + /// + _XSAPIIMP http_call_response_body_type body_type() const { return m_httpCallResponseBodyType; } + + /// + /// Gets the response body of the response as a string. + /// + _XSAPIIMP const string_t& response_body_string() const { return m_responseBodyString; } + + /// + /// Gets the response body of the response as a JSON value. + /// + _XSAPIIMP const web::json::value& response_body_json() const { return m_responseBodyJson; } + + /// + /// Gets the response body of the response as a byte vector. + /// + _XSAPIIMP const std::vector& response_body_vector() const { return m_responseBodyVector; } + + /// + /// Gets the http headers of the response. + /// + _XSAPIIMP const web::http::http_headers& response_headers() const { return m_responseHeaders; } + + /// + /// Gets the http status of the response. + /// + _XSAPIIMP uint32_t http_status() const { return m_httpStatus; } + + /// + /// Gets the error code of the response. + /// + _XSAPIIMP const std::error_code& err_code() const { return m_errorCode; } + + /// + /// Gets the error message of the response. + /// + _XSAPIIMP const std::string& err_message() const { return m_errorMessage; } + + /// + /// Gets the eTag of the response. + /// + _XSAPIIMP const string_t& e_tag() const { return m_eTag; } + + /// + /// Gets the response date of the response. + /// + _XSAPIIMP const string_t& response_date() const { return m_responseDate; } + + /// + /// Gets the "retry after" value found in the response. + /// + _XSAPIIMP const std::chrono::seconds& retry_after() const { return m_retryAfter; } + + /// + /// Internal function + /// + void _Set_error(_In_ const std::error_code& errCode, _In_ const std::string& errMessage) + { + m_errorCode = errCode; + m_errorMessage = errMessage; + } + + /// + /// Internal function + /// + void _Add_response_header(_In_ const string_t& headerName, _In_ const string_t& headerValue) + { + m_responseHeaders.add(headerName, headerValue); + } + + /// + /// Internal function + /// + void _Remove_response_header(_In_ const string_t& headerName) + { + m_responseHeaders.remove(headerName); + } + + /// + /// Internal function + /// + void _Set_response_body(_In_ const string_t& responseBodyString); + + /// + /// Internal function + /// + void _Set_response_body(_In_ const std::vector& responseBodyVector); + + /// + /// Internal function + /// + void _Set_response_body(_In_ const web::json::value& responseBodyJson); + + /// + /// Internal function + /// + void _Set_timing( + _In_ const chrono_clock_t::time_point& requestTime, + _In_ const chrono_clock_t::time_point& responseTime + ); + + /// + /// Internal function + /// + void _Set_error_info( + _In_ const std::error_code& errCode, + _In_ const std::string& errMessage + ); + + /// + /// Internal function + /// + void _Route_service_call() const; + + /// + /// Internal function + /// + const chrono_clock_t::time_point& _Local_response_time() const; + + /// + /// Internal function + /// + std::shared_ptr _Context_settings() const; + + /// + /// Internal function + /// + const web::http::http_request& _Request() const; + + /// + /// Internal function + /// + void _Set_full_url(_In_ const string_t& url); + +private: + void record_service_result() const; + std::string get_throttling_error_message() const; + + http_call_response_body_type m_httpCallResponseBodyType; + std::vector m_responseBodyVector; + string_t m_responseBodyString; + web::json::value m_responseBodyJson; + + uint32_t m_httpStatus; + std::error_code m_errorCode; + std::string m_errorMessage; + + web::http::http_headers m_responseHeaders; + string_t m_eTag; + string_t m_responseDate; + std::chrono::seconds m_retryAfter; + chrono_clock_t::time_point m_requestTime; + chrono_clock_t::time_point m_responseTime; + static volatile long s_responseCount; + + string_t m_xboxUserId; + std::shared_ptr m_xboxLiveContextSettings; + string_t m_fullUrl; + web::http::http_request m_request; + http_call_request_message m_requestBody; + xbox_live_api m_xboxLiveApi; + + string_t response_body_to_string() const; + + static std::chrono::seconds extract_retry_after_from_header( + _In_ const web::http::http_headers& responseHeaders + ); +}; + + +class http_call +{ +public: + /// + /// Attach the Xbox Live token, sign the request, send the request to the service, and return the response. + /// + virtual pplx::task> get_response_with_auth( + _In_ const std::shared_ptr& userContext, + _In_ http_call_response_body_type httpCallResponseBodyType = http_call_response_body_type::json_body, + _In_ bool allUsersAuthRequired = false + ) = 0; + + virtual pplx::task> get_response_with_auth( + _In_ http_call_response_body_type httpCallResponseBodyType = http_call_response_body_type::json_body + ) = 0; + + virtual pplx::task> _Internal_get_response_with_auth( + _In_ const std::shared_ptr& userContext, + _In_ http_call_response_body_type httpCallResponseBodyType = http_call_response_body_type::json_body, + _In_ bool allUsersAuthRequired = false + ) = 0; + + /// + /// Send the request without authentication and get the response. + /// + virtual pplx::task< std::shared_ptr > get_response( + _In_ http_call_response_body_type httpCallResponseBodyType + ) = 0; + + /// + /// Sets the request body using a string. + /// + virtual void set_request_body(_In_ const string_t& value) = 0; + + /// + /// Sets the request body using a JSON value. + /// + virtual void set_request_body(_In_ const web::json::value& value) = 0; + + /// + /// Sets the request body using a byte array value. + /// + virtual void set_request_body(_In_ const std::vector& value) = 0; + + /// + /// Sets a custom header. + /// + virtual void set_custom_header( + _In_ const string_t& headerName, + _In_ const string_t& headerValue) = 0; + + /// + /// Sets if this is a long http call, and should use the long_http_timeout setting. + /// + virtual void set_long_http_call(_In_ bool value) = 0; + + /// + /// Gets if this is a long http call, and should use the long_http_timeout setting. + /// + virtual bool long_http_call() const = 0; + + /// + /// Sets if retry is allowed during this call. + /// + virtual void set_retry_allowed(_In_ bool value) = 0; + + /// + /// Get if retry is allowed during this call. + /// + virtual bool retry_allowed() const = 0; + + /// + /// Sets the content type header value for this call. + /// + virtual void set_content_type_header_value(_In_ const string_t& value) = 0; + + /// + /// Gets the content type header value for this call. + /// + virtual const string_t& content_type_header_value() const = 0; + + /// + /// Sets the Xbox Live contract version header value for this call. + /// + virtual void set_xbox_contract_version_header_value(_In_ const string_t& value) = 0; + + /// + /// Gets the Xbox Live contract version header value for this call. + /// + virtual const string_t& xbox_contract_version_header_value() const = 0; + + /// + /// Gets the server name for this call. + /// + virtual const string_t& server_name() const = 0; + + /// + /// Gets the path for this call. + /// + virtual const web::uri& path_query_fragment() const = 0; + + /// + /// Gets the http method for this call. + /// + virtual const string_t& http_method() const = 0; + + /// + /// Sets a flag indicating if default headers should be added or not. + /// + virtual void set_add_default_headers(_In_ bool value) = 0; + + /// + /// Returns a flag inidicating if default headers should be added or not. + /// + virtual bool add_default_headers() const = 0; + + virtual ~http_call(){} +}; + +_XSAPIIMP std::shared_ptr create_xbox_live_http_call( + _In_ const std::shared_ptr& xboxLiveContextSettings, + _In_ const string_t& httpMethod, + _In_ const string_t& serverName, + _In_ const web::uri& pathQueryFragment + ); + +} } + + diff --git a/Include/xsapi/http_call_request_message.h b/Include/xsapi/http_call_request_message.h new file mode 100644 index 00000000..7cc5aa1b --- /dev/null +++ b/Include/xsapi/http_call_request_message.h @@ -0,0 +1,77 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + +/// +/// Enumerates the type of data contained in the http request body. +/// +enum http_request_message_type +{ + /// + /// No message. + /// + empty_message, + + /// + /// The message is of type string. + /// + string_message, + + /// + /// The message is of type vector, and acts as a memory buffer. + /// + vector_message +}; + +/// +/// Represents an http request message. +/// +class http_call_request_message +{ +public: + /// + /// Internal function + /// + http_call_request_message(); + + /// + /// Internal function + /// + http_call_request_message(_In_ string_t messageString); + + /// + /// Internal function + /// + http_call_request_message(_In_ std::vector messageVector); + + /// + /// The http request message if it is a string type. + /// + _XSAPIIMP const string_t& request_message_string() const; + + /// + /// The http request message if it is a buffer. + /// + _XSAPIIMP const std::vector& request_message_vector() const; + + /// + /// The type of message. + /// + _XSAPIIMP http_request_message_type get_http_request_message_type() const; + +private: + std::vector m_requestMessageVector; + string_t m_requestMessageString; + http_request_message_type m_httpRequestMessageType; +}; + +}} \ No newline at end of file diff --git a/Include/xsapi/leaderboard.h b/Include/xsapi/leaderboard.h new file mode 100644 index 00000000..02f879ce --- /dev/null +++ b/Include/xsapi/leaderboard.h @@ -0,0 +1,584 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "types.h" +#include +#include +#include "xbox_live_app_config.h" + +#define NO_SKIP_XUID (_T("")) +#define NO_XUID (_T("")) +#define NO_SOCIAL_GROUP (_T("")) +#define NO_SKIP_RANK (0) +#define NO_MAX_ITEMS (0) +#define NO_CONTINUATION (_T("")) +#define NO_SORT_ORDER (_T("")) + + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that let you retrieve + /// leaderboard information from Xbox Live. + /// + namespace leaderboard { + +struct leaderboard_global_query; +struct leaderboard_social_query; +class leaderboard_result; + +/// Enumerates the data type of a leaderboard statistic. +enum class leaderboard_stat_type +{ + /// Unsigned 64 bit integer. + stat_uint64, + + /// Boolean. + stat_boolean, + + /// Double. + stat_double, + + /// String. + stat_string, + + /// + /// DEPRECATED + /// DateTime. + /// + stat_datetime, + + /// Unknown. + stat_other +}; + +/// +/// Represents a column in a collection of leaderboard items. +/// +class leaderboard_column +{ +public: + leaderboard_column( + _In_ string_t display_name, + _In_ string_t statName, + _In_ leaderboard_stat_type stat_type); + + /// + /// DEPRECATED + /// The display name of the column. + /// + _XSAPIIMP const string_t& display_name() const; + + /// + /// The name the statistic displayed in the column. + /// + _XSAPIIMP const string_t& stat_name() const; + + /// + /// The property type of the statistic in the column. + /// + _XSAPIIMP leaderboard_stat_type stat_type() const; + +private: + string_t m_displayName; + string_t m_statName; + leaderboard_stat_type m_stat_type; +}; + +/// +/// Represents a row in a collection of leaderboard items. +/// +class leaderboard_row +{ +public: + /// + /// Internal function + /// + leaderboard_row( + _In_ string_t gamertag, + _In_ string_t xboxUserId, + _In_ double percentile, + _In_ uint32_t rank, + _In_ std::vector columnValues, + _In_ string_t metadata); + + /// + /// The Gamertag of the player. + /// + _XSAPIIMP const string_t& gamertag() const; + + /// + /// The Xbox user ID of the player. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The percentile rank of the player. + /// + _XSAPIIMP double percentile() const; + + /// + /// The rank of the player. + /// + _XSAPIIMP uint32_t rank() const; + + /// + /// Values for each column in the leaderboard row for the player. + /// + _XSAPIIMP const std::vector& column_values() const; + +private: + string_t m_gamertag; + string_t m_xboxUserId; + double m_percentile; + uint32_t m_rank; + std::vector m_columnValues; + web::json::value m_metadata; + + friend leaderboard_result; +}; + +/// +/// Represents the results of a leaderboard request. +/// +class leaderboard_result +{ +public: + /// + /// Creates a new leaderboard_result object. + /// + leaderboard_result(); + + /// + /// Internal function + /// + leaderboard_result( + _In_ string_t displayName, + _In_ uint32_t totalRowCount, + _In_ string_t continuationToken, + _In_ std::vector columns, + _In_ std::vector rows, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + /// + /// DEPRECATED + /// The display name of the leaderboard results. + /// + _XSAPIIMP const string_t& display_name() const; + + /// + /// The total number of rows in the leaderboard results. + /// + _XSAPIIMP uint32_t total_row_count() const; + + /// + /// The collection of columns in the leaderboard results. + /// + _XSAPIIMP const std::vector& columns() const; + + /// + /// The collection of rows in the leaderboard results. + /// + _XSAPIIMP const std::vector& rows() const; + + /// + /// Indicates whether there is a next page of results. + /// + /// True if there is another page of results; otherwise false. + _XSAPIIMP bool has_next() const; + + /// + /// Get the next page of a previous leaderboard call using the same service config Id and leaderboard name. + /// + /// The maximum number of items to return. + /// A leaderboard_results object that contains the next set of results. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /scids/{scid}/leaderboards/{leaderboardname}? + /// [maxItems={maxItems}] + /// [continuationToken={token}] + /// + _XSAPIIMP pplx::task> get_next(_In_ uint32_t maxItems) const; + + /// + /// Internal function + /// + void _Set_next_query(std::shared_ptr query); + + /// + /// Internal function + /// + void _Set_next_query(std::shared_ptr query); + + /// + /// Internal function + /// + void _Parse_additional_columns(const std::vector& additionalColumnNames); + +private: + string_t m_displayName; + uint32_t m_totalRowCount; + string_t m_continuationToken; + std::vector m_columns; + std::vector m_rows; + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + std::shared_ptr m_globalQuery; + std::shared_ptr m_socialQuery; +}; + +/// +/// Represents the leaderboard service. +/// +class leaderboard_service +{ +public: + /// + /// Get a leaderboard for a single leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The name of the stats for the additionalColumns. (Optional) + /// + /// A leaderboard_result object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /scids/{scid}/leaderboards/{leaderboardname} + /// + _XSAPIIMP pplx::task> get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + /// + /// Get a leaderboard for a single leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The name of the stats for the additionalColumns. (Optional) + /// + /// A leaderboard_result object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V3 GET /scids/{scid}/leaderboards/{leaderboardname}?include=valuemetadata&xuid={xuid}&viewTarget=people&view=people + /// + _XSAPIIMP pplx::task> get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems = 0, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + /// + /// Get a page of leaderboard results for a single leaderboard given a service configuration ID + /// and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The number of ranks to skip before returning results. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// The name of the stats for the additionalColumns. (Optional) + /// A leaderboard_result object containing a collection of the leaderboard columns and rows. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipItems={skipItems}][&maxItems={maxItems}] + /// + _XSAPIIMP pplx::task> get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ uint32_t maxItems = 0, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + /// + /// Get a page of leaderboard results for a single leaderboard given a service configuration ID + /// and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The number of ranks to skip before returning results. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// The name of the stats for the additionalColumns. (Optional) + /// A leaderboard_result object containing a collection of the leaderboard columns and rows. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipItems={skipItems}][&maxItems={maxItems}]&include=valuemetadata&xuid={xuid}&viewTarget=people&view=people + /// + _XSAPIIMP pplx::task> get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems = 0, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + /// + /// Get a leaderboard starting at a specified player, regardless of the player's rank or score, ordered by + /// the player's percentile rank. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the player to skip to before retrieving results. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// The name of the stats for the additionalColumns. (Optional) + /// + /// A leaderboard_result object containing a collection of the leaderboard columns and rows. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// There is no continuation Token provided for this query. + /// + /// Calls V1 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipToUser={xuid}][&maxItems={maxItems}] + /// + _XSAPIIMP pplx::task> get_leaderboard_skip_to_xuid( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const string_t& skipToXuid = string_t(), + _In_ uint32_t maxItems = 0, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + + /// + /// Get a leaderboard starting at a specified player, regardless of the player's rank or score, ordered by + /// the player's percentile rank. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The Xbox user ID of the player to skip to before retrieving results. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// The name of the stats for the additionalColumns. (Optional) + /// + /// A leaderboard_result object containing a collection of the leaderboard columns and rows. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// There is no continuation Token provided for this query. + /// + /// Calls V1 GET + // /scids/{scid}/leaderboards/{leaderboardname}?[&skipToUser={xuid}][&maxItems={maxItems}] + /// + _XSAPIIMP pplx::task> get_leaderboard_skip_to_xuid( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ const string_t& skipToXuid, + _In_ uint32_t maxItems = 0, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + /// + /// Get an unsorted leaderboard that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites} + /// + _XSAPIIMP pplx::task> get_leaderboard_for_social_group( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems = 0 + ); + + /// + /// Get a sorted leaderboard that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// An object containing a collection of the leaderboard columns and rows + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites}[?sort=descending|ascending] + /// + _XSAPIIMP pplx::task> get_leaderboard_for_social_group( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems = 0 + ); + + /// + /// Get a sorted leaderboard, starting at a specified rank, that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The number of ranks to skip before retrieving results. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// The name of the stats for the additionalColumns. (Optional) + /// + /// A leaderboard_result object containing a collection of the leaderboard columns and rows. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites}[?sort=descending|ascending]&skipToRank={skipToUser} + /// + _XSAPIIMP pplx::task> get_leaderboard_for_social_group_skip_to_rank( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t skipToRank, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems = 0 + ); + + /// + /// Get a sorted leaderboard, starting at a specified player, that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The Xbox user ID of the player to skip to before retrieving results. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. If this value is 0, the server defaults to 10. (Optional) + /// + /// A leaderboard_result object that contains a page of leaderboard results around the specifed player regardless + /// of that player's rank or score. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites}[?sort=descending|ascending]&skipToUser={skipToUser} + /// + _XSAPIIMP pplx::task> get_leaderboard_for_social_group_skip_to_xuid( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ const string_t& skipToXuid, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems = 0 + ); + +private: + leaderboard_service() {} + + leaderboard_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + pplx::task> get_leaderboard_for_social_group_internal( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t skipToRank, + _In_ const string_t& skipToXuid, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ); + + pplx::task> get_leaderboard_internal( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ const string_t& skipToXuid, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ const std::vector& additionalColumnNames = std::vector() + ); + + pplx::task> get_leaderboard_for_url( + _In_ string_t url + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend leaderboard_result; + friend xbox_live_context_impl; +}; + +}}} \ No newline at end of file diff --git a/Include/xsapi/marketplace.h b/Include/xsapi/marketplace.h new file mode 100644 index 00000000..a11af01f --- /dev/null +++ b/Include/xsapi/marketplace.h @@ -0,0 +1,1487 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#if TV_API || UNIT_TEST_SERVICES + +namespace xbox { +namespace services { +/// +/// Contains classes and enumerations used to represent products and itemized product catalogs available for purchase. +/// +namespace marketplace { + +/// Enumeration values that indicate the media item type. +enum class media_item_type +{ + /// Unknown media type. + unknown, + + /// Game media type. + game, + + /// GameV2 media type. + game_v2, + + /// Application media type. + application, + + /// Game content media type. + game_content, + + /// Game consumable media type. + game_consumable, + + /// Subscription media type. + subscription, + + /// Movie media type. + movie, + + /// Television Show media type. + television_show, + + /// Television Series media type. + television_series, + + /// Television Season media type. + television_season, + + /// Service detects if media type is an application or a game. + application_or_game_unknown, + + /// Game demo media type. + game_demo, + + /// WebVideo media type. + web_video, + + /// Request All media types for inventory calls. + all +}; + +/// Defines values used to indicate the order of sorted catalog results. +enum class catalog_sort_order +{ + /// + /// Sort by count of free and paid purchases, for the most recent day. + /// + free_and_paid_count_daily, + + /// + /// Sort by count of only paid purchases, for all time. + /// + paid_count_all_time, + + /// + /// Sort by count of only paid purchases, for the most recent day. + /// + paid_count_daily, + + /// + /// Sort by date available for download. + /// + digital_release_date, + + /// + /// Sort by date available in stores, falling back to digital release date (if available). + /// + release_date, + + /// + /// Sort by average user ratings. + /// + user_ratings +}; + +/// Enumeration values that indicate the media item type. +enum class bundle_relationship_type +{ + /// Unknown media type. + unknown, + + /// Find which bundles include this product. + bundles_with_product, + + /// Find which products are included in a specified bundle. + products_in_bundle +}; + +/// Enumeration values that indicate the inventory item state. +enum class inventory_item_state +{ + /// Unknown item state. + unknown, + + /// All is used to request inventory items for all states. + all, + + /// Enabled item state. + enabled, + + /// Suspended item state. + suspended, + + /// Expired item state. + expired, + + /// Canceled item state. This state pertains to subscriptions that have been canceled. + canceled +}; + +/// Enumeration values that indicate the current availability inventory items. +enum class inventory_item_availability +{ + /// + /// All items should be returned regardless of availability. + /// + all, + + /// + /// Item is available. The current date falls between the start and end date of the item. + /// + available, + + /// + /// Item is unavailable. The current date falls outside the start and end date of the item. + /// + unavailable +}; + +/// Represents an image associated with a catalog item. +class catalog_item_image +{ + // { + // "ID":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944", + // "ResizeUrl":"http://images.xboxlive.com/image?url=etc", + // "Purposes": + // [ + // "Box_Art" + // ], + // "Purpose":"Box_Art", + // "Height":1080, + // "Width":1080 + // } + +public: + /// + /// Internal function + /// + catalog_item_image(); + + /// + /// Internal function + /// + catalog_item_image( + _In_ string_t id, + _In_ web::uri resizeUrl, + _In_ std::vector purposes, + _In_ string_t purpose, + _In_ uint32_t height, + _In_ uint32_t width + ); + + /// + /// Returns the URI of the catalog item image. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// Returns the URI of the catalog item image. + /// + _XSAPIIMP const web::uri& resize_url() const; + + /// + /// A collection of purposes. + /// + _XSAPIIMP const std::vector& purposes() const; + + /// + // The default purpose of the catalog item image. + /// + _XSAPIIMP const string_t& purpose() const; + + /// + // The height of the image. + /// + _XSAPIIMP uint32_t height() const; + + /// + // The width of the image. + /// + _XSAPIIMP uint32_t width() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_id; + web::uri m_resizeUrl; + std::vector m_purposes; + string_t m_purpose; + uint32_t m_height; + uint32_t m_width; +}; + +/// Represents a catalog item. +class catalog_item +{ + //{ + // "desiredMediaItemTypes":"Subscription.DGame.DGameDemo.DDurable.DConsumable.DApp", + // "MediaItemType":"DConsumable", + // "ID":"44c99601-7db8-4ad6-9610-218bbff99daf", + // "Name":"Gold Coins", + // "ReleaseDate":"2013-05-15T00:00:00Z", + // "TitleId":"521617E4", + // "VuiDisplayName":"Gold Coins V", + // + // "Genres": + // [ + // { + // "Name":"Educational" + // } + // ], + // + // "Images": + // [ + // { + // "ID":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944", + // "ResizeUrl":"http://images.xboxlive.com/image?url=etc", + // "Purposes": + // [ + // "Box_Art" + // ], + // "Purpose":"Box_Art", + // "Height":1080, + // "Width":1080 + // } + // ], + // + // "SortName":"Gold s", + // "KValue":"4", + // "KValueNamespace":"bingbox", + // "LegacyIds": + // [ + // { + // "IdType":"ProductId", + // "Value":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944" + // } + // ], + // + // "Availabilities": + // [ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // } + // ], + // "SandboxId":"DECO.0", + // "IsBundle": true, + // "IsPartOfAnyBundle": true + //} + +public: + catalog_item(); + + catalog_item( + _In_ string_t id, + _In_ string_t name, + _In_ string_t reducedName, + _In_ uint32_t titleId, + _In_ utility::datetime releaseDate, + _In_ string_t productId, + _In_ string_t sandboxId, + _In_ bool isBundle, + _In_ bool isPartOfAnyBundle, + _In_ std::vector images, + _In_ std::vector availabilityContentIds, + _In_ media_item_type mediaItemType + ); + + /// + /// The media type of the catalog item. + /// + _XSAPIIMP media_item_type item_type() const; + + /// + /// The catalog ID of the catalog item. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// The name of the catalog item. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The name of the catalog item. + /// + _XSAPIIMP const string_t& reduced_name() const; + + /// + /// The title ID of the catalog item. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The release date of the catalog item. + /// + _XSAPIIMP const utility::datetime& release_date() const; + + /// + /// The product ID of the catalog item. + /// + _XSAPIIMP const string_t& product_id() const; + + /// + /// The sandbox ID of the catalog item. + /// + _XSAPIIMP const string_t& sandbox_id() const; + + /// + /// Is this product a Bundle and includes entitlements to other products. + /// + _XSAPIIMP bool is_bundle() const; + + /// + /// Is this product a member of a bundle in the Marketplace. + /// + _XSAPIIMP bool is_part_of_any_bundle() const; + + /// + /// A collection of images for this catalog item. + /// + _XSAPIIMP const std::vector& images() const; + + /// + /// A collection of availability content IDs for this catalog item. + /// + _XSAPIIMP const std::vector& availability_content_ids() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_id; + string_t m_name; + string_t m_reducedName; + uint32_t m_titleId; + utility::datetime m_releaseDate; + string_t m_productId; + string_t m_sandboxId; + bool m_isBundle; + bool m_isPartOfAnyBundle; + std::vector m_images; + std::vector m_availabilityContentIds; + media_item_type m_mediaItemType; +}; + +/// Contains the results of a browse catalog request. +class browse_catalog_result +{ +public: + // "Items": + // [ + // { + // // ... + // } + // ], + // + // "Totals": + // [ + // { + // "Name":"GameType", + // "Count":126, + // "MediaItemTypes": + // [ + // { + // "Name":"XboxGameConsumable", + // "Count":126 + // } + // ] + // } + // ], + + /// + /// Internal function + /// + browse_catalog_result(); + + /// + /// Internal function + /// + browse_catalog_result( + _In_ string_t parentId, + _In_ media_item_type parentMediaItemType, + _In_ media_item_type childMediaItemType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems, + _In_ string_t productId, + _In_ bundle_relationship_type bundleRelationship, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::vector items, + _In_ uint32_t totalCount, + _In_ string_t continuationToken, + _In_ bool m_isBundleRelated + ); + + /// + /// Collection of XboxCatalogItem objects returned by a request. + /// + _XSAPIIMP const std::vector& items() const; + + /// + // The total count of the items. + /// + _XSAPIIMP uint32_t total_count() const; + + /// + /// Returns an BrowseCatalogResult object containing the next page of BrowseCatalogResult. + /// + /// The maximum number of items the result can contain. Pass 0 to attempt retrieving all items. + /// A BrowseCatalogResult object. + /// Calls V3.2 GET /media/{marketplaceId}/browse + _XSAPIIMP pplx::task> get_next( + _In_ uint32_t maxItems + ); + + /// + /// Indicates if there is additional data to retrieve from a get_next call + /// + _XSAPIIMP bool has_next() const; + + /// + /// Internal function + /// + void _Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ string_t parentId, + _In_ media_item_type parentMediaType, + _In_ media_item_type childItemType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems + ); + + /// + /// Internal function + /// + void _Set_browse_bundles( + _In_ string_t productId, + _In_ bundle_relationship_type relationship + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_parentId; + media_item_type m_parentMediaItemType; + media_item_type m_childMediaItemType; + catalog_sort_order m_orderBy; + uint32_t m_skipItems; + string_t m_productId; + bundle_relationship_type m_bundleRelationship; + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::vector m_items; + uint32_t m_totalCount; + string_t m_continuationToken; + bool m_isBundleRelated; +}; + +/// Indicates availability of content by date, payment methods, currency, and distribution options. +class catalog_item_availability +{ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // "OfferDisplayData": + // { + // "acceptablePaymentInstrumentTypes": + // [ + // "CreditCard", + // "Tokens" + // ], + // "availabilityDescription":"AvailabilityDescription for 3cba007c-50db-4332-89c1-3ebc116fa27b", + // "currencyCode":"USD", + // "displayPrice":"$0.01", + // "displayListPrice":"$5.00", + // "distributionType":"Full", + // "isPurchasable":true, + // "listPrice":5.0, + // "price":0.01, + // "promotionalText":"Need Gold subscription. Click to buy" + // }, + // "SignedOffer":"etc" + // } + +public: + /// + /// Internal function + /// + catalog_item_availability(); + + /// + /// Internal function + /// + catalog_item_availability( + _In_ string_t contentId, + _In_ string_t signedOffer + ); + + /// + /// Internal function + /// + catalog_item_availability( + _In_ string_t contentId, + _In_ std::vector acceptablePaymentInstrumentTypes, + _In_ string_t availabilityTitle, + _In_ string_t availabilityDescription, + _In_ string_t currencyCode, + _In_ string_t displayPrice, + _In_ string_t displayListPrice, + _In_ string_t distributionType, + _In_ bool isPurchasable, + _In_ double listPrice, + _In_ double price, + _In_ uint32_t consumableQuantity, + _In_ string_t promotionalText, + _In_ string_t signedOffer, + _In_ string_t offerId, + _In_ string_t offerDisplayDataJson + ); + + /// + /// The content ID. + /// + _XSAPIIMP const string_t& content_id() const; + + /// + /// A collection of acceptable payment instrument types. + /// + _XSAPIIMP const std::vector& acceptable_payment_Instrument_types() const; + + /// + /// The title of the availability. + /// + _XSAPIIMP const string_t& availability_title() const; + + /// + /// The description of the availability. + /// + _XSAPIIMP const string_t& availability_description() const; + + /// + /// The currency code. + /// + _XSAPIIMP const string_t& currency_code() const; + + /// + /// The display price + /// + _XSAPIIMP const string_t& display_price() const; + + /// + /// The display list price. + /// + _XSAPIIMP const string_t& display_list_price() const; + + /// + /// The distribution type. + /// + _XSAPIIMP const string_t& distribution_type() const; + + /// + /// Indicates if the availability is purchasable. + /// + _XSAPIIMP bool is_purchasable() const; + + /// + /// The list price in numeric form. + /// + _XSAPIIMP double list_price() const; + + /// + /// The price in numeric form. + /// + _XSAPIIMP double price() const; + + /// + /// The quantity of the catalog item. + /// + _XSAPIIMP uint32_t consumable_quantity() const; + + /// + /// The distribution type. + /// + _XSAPIIMP const string_t& promotional_text() const; + + /// + /// The signed offer. + /// + _XSAPIIMP const string_t& signed_offer() const; + + /// + /// The offer ID. + /// + _XSAPIIMP const string_t& offer_id() const; + + /// + /// Json string that contains the offer display data. + /// + _XSAPIIMP const string_t& offer_display_data_json() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_contentId; + std::vector m_acceptablePaymentInstrumentTypes; + string_t m_availabilityTitle; + string_t m_availabilityDescription; + string_t m_currencyCode; + string_t m_displayPrice; + string_t m_displayListPrice; + string_t m_distributionType; + bool m_isPurchasable; + double m_listPrice; + double m_price; + uint32_t m_consumableQuantity; + string_t m_promotionalText; + string_t m_signedOffer; + string_t m_offerId; + string_t m_offerDisplayDataJson; +}; + +/// Contains information about a catalog item. +class catalog_item_details +{ + //{ + // "desiredMediaItemTypes":"Subscription.DGame.DGameDemo.DDurable.DConsumable.DApp", + // "MediaItemType":"DConsumable", + // "ID":"44c99601-7db8-4ad6-9610-218bbff99daf", + // "Name":"Gold Coins", + // "Description":"Consumable in-game currency", + // "ReleaseDate":"2013-05-15T00:00:00Z", + // "TitleId":"521617E4", + // "VuiDisplayName":"Gold Coins V", + // + // "Genres": + // [ + // { + // "Name":"Educational" + // } + // ], + // + // "Images": + // [ + // { + // "ID":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944", + // "ResizeUrl":"http://images.xboxlive.com/image?url=etc", + // "Purposes": + // [ + // "Box_Art" + // ], + // "Purpose":"Box_Art", + // "Height":1080, + // "Width":1080 + // } + // ], + // + // "SortName":"Gold s", + // "KValue":"4", + // "KValueNamespace":"bingbox", + // "LegacyIds": + // [ + // { + // "IdType":"ProductId", + // "Value":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944" + // } + // ], + // + // "Availabilities": + // [ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // "OfferDisplayData": + // { + // "acceptablePaymentInstrumentTypes": + // [ + // "CreditCard", + // "Tokens" + // ], + // "availabilityDescription":"AvailabilityDescription for 3cba007c-50db-4332-89c1-3ebc116fa27b", + // "currencyCode":"USD", + // "displayPrice":"$0.01", + // "displayListPrice":"$5.00", + // "distributionType":"Full", + // "isPurchasable":true, + // "listPrice":5.0, + // "price":0.01, + // "promotionalText":"Need Gold subscription. Click to buy" + // }, + // "SignedOffer":"Q" + // } + // ], + // "SandboxId":"DECO.0" + // "IsBundle": true, + // "IsPartOfAnyBundle": true + //} + +public: + /// + /// Internal function + /// + catalog_item_details(); + + /// + /// Internal function + /// + catalog_item_details( + _In_ string_t id, + _In_ string_t m_name, + _In_ string_t reducedName, + _In_ string_t description, + _In_ uint32_t titleId, + _In_ utility::datetime releaseDate, + _In_ string_t productId, + _In_ string_t sandboxId, + _In_ bool isBundle, + _In_ bool isPartOfAnyBundle, + _In_ std::vector images, + _In_ std::vector availabilities, + _In_ media_item_type mediaItemType + ); + + /// + /// The media item type of the catalog item. + /// + _XSAPIIMP const media_item_type item_type() const; + + /// + /// The catalog ID of the catalog item. + /// + _XSAPIIMP const string_t& id() const; + + /// + /// The name of the catalog item. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// The reduced name of the catalog item. + /// + _XSAPIIMP const string_t& reduced_name() const; + + /// + /// The description of the catalog item. + /// + _XSAPIIMP const string_t& description() const; + + /// + /// The title ID of the catalog item. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The release date of the catalog item. + /// + _XSAPIIMP const utility::datetime& release_date() const; + + /// + /// The product ID of the catalog item. + /// + _XSAPIIMP const string_t& product_id() const; + + /// + /// The sandbox ID of the catalog item. + /// + _XSAPIIMP const string_t& sandbox_id() const; + + /// + /// Is this product a Bundle and includes entitlements to other products. + /// + _XSAPIIMP bool is_bundle() const; + + /// + /// Is this product a member of a bundle in the Marketplace. + /// + _XSAPIIMP bool is_part_of_any_bundle() const; + + /// + /// A collection of images for this catalog item. + /// + _XSAPIIMP const std::vector& images() const; + + /// + /// A collection of images for this catalog item. + /// + _XSAPIIMP const std::vector& availabilities() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_id; + string_t m_name; + string_t m_reducedName; + string_t m_description; + uint32_t m_titleId; + utility::datetime m_releaseDate; + string_t m_productId; + string_t m_sandboxId; + bool m_isBundle; + bool m_isPartOfAnyBundle; + std::vector m_images; + std::vector m_availabilities; + media_item_type m_mediaItemType; +}; + +/// Indicates the total number of items within a catalog +class catalog_total +{ +public: + /// + /// Internal function + /// + catalog_total(); + + /// + /// Internal function + /// + catalog_total( + _In_ uint32_t total + ); + + /// + /// Total number of items + /// + _XSAPIIMP uint32_t total() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + uint32_t m_total; +}; + +/// Represents a service for managing the catalog. +class catalog_service +{ +public: + /// + /// Browse for catalog items from within a single media group. + /// + /// The product ID of the parent product. + /// The media type of the parent. + /// The media type of the child. + /// Controls how the list is ordered. + /// The number of items to skip. + /// The maximum number of items the result can contain. Pass 0 to attempt retrieve as many items as possible. + /// BrowseCatalogResult object containing the items. + /// Calls V3.2 GET /media/{marketplaceId}/browse + _XSAPIIMP pplx::task> browse_catalog( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ media_item_type childMediaType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ); + + /// + /// Browse the catalog related to bundles an item is a member of or included items of a bundle. + /// + /// The product ID of the parent product. + /// The media type of the parent. + /// The ID of the product we are browsing the relationship for. + /// The relationship to be used in the browse call either included products in a bundle, or bundles the product is a member of. + /// The number of items to skip. + /// The maximum number of items the result can contain. Pass 0 to attempt retrieve as many items as possible. + /// BrowseCatalogResult object containing the items + /// Calls V3.2 GET /media/{marketplaceId}/browse + _XSAPIIMP pplx::task> browse_catalog_bundles( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ const string_t& productId, + _In_ bundle_relationship_type relationship, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ); + + /// + /// Get the product details for a set of ProductIDs. + /// + /// A collection of product IDs to get item details for. A maximum of ten strings may be passed per call to this method. + /// A collection of CatalogItems. + /// Calls V3.2 GET /media/{marketplaceId}/details + _XSAPIIMP pplx::task>> get_catalog_item_details( + _In_ const std::vector& productIds + ); + + static media_item_type _Convert_string_to_media_item_type( + _In_ const string_t& itemType + ); + + /// + /// Internal function + /// + static string_t _Convert_media_item_type_to_string( + _In_ media_item_type itemType + ); +private: + catalog_service(); + + catalog_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static string_t convert_bundle_relationship_type_to_string( + _In_ bundle_relationship_type type + ); + + static xbox_live_result convert_sort_order_to_string( + _In_ catalog_sort_order type + ); + + static string_t marketplace_browse_catalog_subpath( + _In_ const string_t& parentId, + _In_ const string_t& titleType, + _In_ const string_t& desiredMediaItemTypes, + _In_ const string_t& relationship, + _In_ const string_t& orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ); + + static pplx::task> browse_catalog_helper( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ media_item_type childMediaType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ string_t customHeader, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static pplx::task> browse_catalog_bundles_helper( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ const string_t& productId, + _In_ bundle_relationship_type relationship, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ string_t customHeader, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static string_t marketplace_catalog_details_subpath( + _In_ const std::vector& productIds + ); + + static const string_t BROWSE_CATALOG_CONTRACT_HEADER_VALUE; + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend class xbox_live_context_impl; + friend class browse_catalog_result; +}; + +// Helper class for serialization +class consume_inventory_item_request +{ +public: + consume_inventory_item_request(); + + consume_inventory_item_request( + _In_ string_t transactionId, + _In_ uint32_t removeQuantity + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + web::json::value _Serialize(); +private: + string_t m_transactionId; + uint32_t m_removeQuantity; +}; + +/// The results of a consume inventory item request. +class consume_inventory_item_result +{ +public: + /// + /// Internal function + /// + consume_inventory_item_result(); + + /// + /// Internal function + /// + consume_inventory_item_result( + _In_ web::uri consumableUrl, + _In_ uint32_t consumableBalance, + _In_ string_t transactionId + ); + + /// + /// The consumable item Url of the item that was consumed. + /// + _XSAPIIMP const web::uri& consumable_url() const; + + /// + /// The new balance for the consumable item. + /// + _XSAPIIMP uint32_t consumable_balance() const; + + /// + /// The transaction Id that serves to acknowledge receipt of a specific request. + /// + _XSAPIIMP const string_t& transaction_id() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + web::uri m_consumableUrl; + uint32_t m_consumableBalance; + string_t m_transactionId; +}; + +/// Represents an inventory item. +class inventory_item +{ +public: + /// + /// Internal function + /// + inventory_item(); + + /// + /// Internal function + /// + inventory_item( + _In_ web::uri url, + _In_ inventory_item_state inventoryItemState, + _In_ media_item_type mediaItemType, + _In_ string_t productId, + _In_ uint32_t titleId, + _In_ std::vector containerIds, + _In_ utility::datetime rightsObtainedDate, + _In_ utility::datetime startDate, + _In_ utility::datetime endDate, + _In_ web::uri consumableUrl, + _In_ uint32_t consumableBalance, + _In_ bool isTrialEntitlement, + _In_ std::chrono::seconds trialTimeRemaining + ); + + /// + /// The inventory item Url. + /// + _XSAPIIMP const web::uri& url() const; + + /// + /// The state of the inventory item. + /// + _XSAPIIMP inventory_item_state item_state() const; + + /// + /// The media item type of the inventory item. + /// + _XSAPIIMP media_item_type item_type() const; + + /// + /// The unique identifier of the product that this item represents. + /// + _XSAPIIMP const string_t& product_id() const; + + /// + /// The title Id that a durable item is associated with or null for consumable and subscription items. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The list of container Ids that contain this item + /// + _XSAPIIMP const std::vector& container_ids() const; + + /// + /// The date when the rights to the item were obtained. + /// + _XSAPIIMP const utility::datetime& rights_obtained_date() const; + + /// + /// The start date when the item became available for use. + /// + _XSAPIIMP const utility::datetime& start_date() const; + + /// + /// The end date when the item became or will become unusable. + /// + _XSAPIIMP const utility::datetime& end_date() const; + + /// + /// The consumable item Url or null for non-consumable inventory items. + /// + _XSAPIIMP const web::uri& consumable_url() const; + + /// + /// The balance of the consumable inventory item at the time the request was received. For non-consumable items, the quantity will be 0. + /// + _XSAPIIMP uint32_t consumable_balance() const; + + /// + /// True if this entitlement is a trial; otherwise, false. If you buy the trial version of an entitlement and then buy the full version, you will receive both + /// + _XSAPIIMP bool is_trial_entitlement() const; + + /// + /// How much time is remaining on the trial. + /// + _XSAPIIMP const std::chrono::seconds& trial_time_remaining() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + + static inventory_item_state convert_string_to_inventory_item_state( + _In_ const string_t& value + ); + + static media_item_type convert_string_to_media_item_type( + _In_ const string_t& value + ); + + web::uri m_url; + inventory_item_state m_inventoryItemState; + media_item_type m_itemType; + string_t m_productId; + uint32_t m_titleId; + std::vector m_containerIds; + utility::datetime m_rightsObtainedDate; + utility::datetime m_startDate; + utility::datetime m_endDate; + web::uri m_consumableUrl; + uint32_t m_consumableBalance; + bool m_isTrialEntitlement; + std::chrono::seconds m_trialTimeRemaining; +}; + +/// The results of an inventory item request. +class inventory_items_result +{ +public: + /// + /// Internal function + /// + inventory_items_result(); + + /// + /// Internal function + /// + inventory_items_result( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ string_t inventoryItemContainerId, + _In_ bool allUsersAuthRequired, + _In_ std::vector items, + _In_ uint32_t totalItems, + _In_ string_t continuationToken, + _In_ bool expandSatisfyingEntitlements + ); + + /// + /// Collection of InventoryItem objects returned by a request. + /// + _XSAPIIMP const std::vector& items() const; + + /// + /// The total number of inventory items that matched the request. + /// + _XSAPIIMP uint32_t total_items() const; + + /// + /// For paged enumeration requests, the ContinuationToken is used when requesting an additional page of data. + /// + _XSAPIIMP const string_t& continuation_token() const; + + /// + /// Returns the next page of inventory items. + /// + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// InventoryResult object containing the next page of InventoryItem objects. + /// Calls V2 GET /users/me/inventory + _XSAPIIMP pplx::task> get_next( + _In_ uint32_t maxItems + ); + + /// + /// Indicates if there is additional data to retrieve from a get_next call + /// + _XSAPIIMP bool has_next() const; + + /// + /// Internal function + /// + void _Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ string_t inventoryItemContainerId, + _In_ bool allUsersAuthRequired, + _In_ bool expandSatisfyingEntitlements + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + media_item_type m_mediaItemType; + inventory_item_state m_inventoryItemState; + inventory_item_availability m_inventoryItemAvailability; + string_t m_inventoryItemContainerId; + bool m_allUsersAuthRequired; + std::vector m_items; + uint32_t m_totalItems; + string_t m_continuationToken; + bool m_expandSatisfyingEntitlements; +}; + +/// Defines methods and enumerations used to manage the item inventory a signed-in user. +class inventory_service +{ +public: + /// + /// Enumerate user's inventory + /// + /// The media item type to enumerate. + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// Include results of pre-orders and now-unavailable products the user owns + /// inventory_items_result object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + _XSAPIIMP pplx::task> get_inventory_items( + _In_ media_item_type mediaItemType, + _In_ bool expandSatisfyingEntitlements = false, + _In_ bool includeAllItemStatesAndAvailabilities = false + ); + + /// + /// Get the inventory results for a set of product ids for the current user + /// + /// A collection of IDs to query the inventory for + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// inventory_items_result object containing the inventoryItems + /// + /// It is recommended that you limit your ProductIds requested per list to a maximum of 100. + /// + /// Calls V4 GET /users/me/inventory + /// + _XSAPIIMP pplx::task> get_inventory_items( + _In_ const std::vector& productIds, + _In_ bool expandSatisfyingEntitlements = false + ); + + /// + /// Enumerate a user's inventory. + /// + /// The media item type to enumerate. + /// The state of the inventory items to include in the result. + /// The availability of the inventory items to include in the result. + /// The container Id of the inventory items to include in the result. (Optional) + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// inventory_items_result object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + _XSAPIIMP pplx::task> get_inventory_items( + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ uint32_t maxItems, + _In_ bool expandSatisfyingEntitlements = false + ); + + /// + /// Enumerate inventory for all signed-in users for all available items of the specified type that are in the enabled state. + /// + /// The media item type to enumerate + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// Include results of pre-orders and now-unavailable products the user owns + /// inventory_items_result object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + _XSAPIIMP pplx::task> get_inventory_items_for_all_users( + _In_ media_item_type mediaItemType, + _In_ bool expandSatisfyingEntitlements = false, + _In_ bool includeAllItemStatesAndAvailabilities = false + ); + + /// + /// Get the inventory results for a set of product ids for the current user + /// + /// A collection of IDs to query the inventory for + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// inventory_items_result object containing the inventoryItems + /// + /// It is recommended that you limit your ProductIds requested per list to a maximum of 100. + /// + /// Calls V4 GET /users/me/inventory + /// + _XSAPIIMP pplx::task> get_inventory_items_for_all_users( + _In_ const std::vector& productIds, + _In_ bool expandSatisfyingEntitlements = false + ); + + /// + /// Enumerate inventory for all signed-in users. + /// + /// The media item type to enumerate + /// The state of the inventory items to include in the result + /// The availability of the inventory items to include in the result + /// The container Id of the inventory items to include in the result (Optional) + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// inventory_items_result object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + _XSAPIIMP pplx::task> get_inventory_items_for_all_users( + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ uint32_t maxItems, + _In_ bool expandSatisfyingEntitlements = false + ); + + /// + /// Gets a single inventory item for the specified Id. + /// + /// The InventoryItem to get an update for. + /// The requested InventoryItem object + /// Calls V4 GET /users/me/inventory/{inventoryItemId} + _XSAPIIMP pplx::task> get_inventory_item( + _In_ inventory_item inventoryItem + ); + + /// + /// Consumes the specified quantity of a consumable inventory item. + /// + /// The InventoryItem to consume quantity from. + /// The quantity to consume of the specified InventoryItem. + /// A client generated unique Id for the transaction. + /// Transactions with the same Id will only be processed once. + /// A ConsumeInventoryItemResult object. + /// Calls V4 POST /users/me/consumables/{consumableId} + _XSAPIIMP pplx::task> consume_inventory_item( + _In_ inventory_item inventoryItem, + _In_ uint32_t quantityToConsume, + _In_ const string_t& transactionId + ); +private: + inventory_service(); + + inventory_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + pplx::task> get_inventory_items( + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ bool allUsersAuthRequired, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ bool expandSatisfyingEntitlements, + _In_ const std::vector& productIds + ); + + static const xbox_live_result convert_media_item_type_to_string( + _In_ media_item_type mediaItemType + ); + + static const xbox_live_result convert_inventory_item_state_to_string( + _In_ inventory_item_state inventorytItemState + ); + + static const xbox_live_result convert_inventory_item_availability_to_string( + _In_ inventory_item_availability inventorytItemAvailability + ); + + static const string_t inventory_end_point(); + + static const string_t get_inventory_items_sub_path( + _In_ media_item_type mediaItemType, + _In_ const string_t& mediaItemTypeString, + _In_ const string_t& inventoryItemState, + _In_ const string_t& inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ bool expandSatisfyingEntitlements, + _In_ const std::vector& productIds + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend class xbox_live_context_impl; + friend class inventory_items_result; +}; + +} } } + +#endif \ No newline at end of file diff --git a/Include/xsapi/matchmaking.h b/Include/xsapi/matchmaking.h new file mode 100644 index 00000000..17238fa2 --- /dev/null +++ b/Include/xsapi/matchmaking.h @@ -0,0 +1,324 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that let you match + /// players for a multiplayer session. + /// + namespace matchmaking { + +/// +/// Defines values used to indicate whether a match ticket is for a new +/// game session or an existing session. +/// +enum class preserve_session_mode +{ + /// + /// The server returned an unrecognized response. + /// + unknown, + + /// + /// Always use an existing game session. This is for matching more players + /// for a game session that is already created or in progress. + /// + always, + + /// + /// Never use an existing game session. This is for matching players + /// for a new game session. + /// + never +}; + +/// +/// Defines values used to indicate the status of the match request. +/// +enum class ticket_status +{ + /// + /// The status of the match request has not been returned by the server yet + /// or the server returned an unrecognized response. + /// + unknown, + + /// + /// Matchmaking has not found a match and the search + /// request has expired according to its give up duration. + /// + expired, + + /// + /// Matchmaking has not found a match yet and it is + /// still searching. + /// + searching, + + /// + /// Matchmaking has found a match and the ticket contains a + /// reference to the session that is to be created. + /// + found, + + /// + /// Matchmaking has been canceled for this ticket. + /// + canceled +}; + +/// +/// Represents a server response to a create match ticket request. +/// +class create_match_ticket_response +{ +public: + create_match_ticket_response(); + + create_match_ticket_response( + _In_ string_t matchTicketId, + _In_ std::chrono::seconds estimatedWaitTime + ); + + /// + /// Ticket ID of a match request. + /// + _XSAPIIMP const string_t& match_ticket_id() const; + + /// + /// Estimated wait time for a match request to be matched with other players. + /// + _XSAPIIMP const std::chrono::seconds& estimated_wait_time() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_matchTicketId; + std::chrono::seconds m_estimatedWaitTime; +}; + +/// +/// Represents a server response to a request for match ticket details. +/// +class match_ticket_details_response +{ +public: + /// + /// Internal function + /// + match_ticket_details_response(); + + /// + /// Internal function + /// + match_ticket_details_response( + _In_ ticket_status matchStatus, + _In_ std::chrono::seconds estimatedWaitTime, + _In_ preserve_session_mode preserveSession, + _In_ xbox::services::multiplayer::multiplayer_session_reference ticketSession, + _In_ xbox::services::multiplayer::multiplayer_session_reference targetSession, + _In_ web::json::value ticketAttributes + ); + + /// + /// Status of a match request. + /// + _XSAPIIMP ticket_status match_status() const; + + /// + /// Estimated wait time for a match request to be matched with other players. + /// + _XSAPIIMP const std::chrono::seconds& estimated_wait_time() const; + + /// + /// An enum value to specify whether the match should preserve the session on which the match has been requested. + /// + _XSAPIIMP preserve_session_mode preserve_session() const; + + /// + /// The session on which the match was requested. + /// + _XSAPIIMP const xbox::services::multiplayer::multiplayer_session_reference& ticket_session() const; + + /// + /// The session on which a match request has been found. + /// + _XSAPIIMP const xbox::services::multiplayer::multiplayer_session_reference& target_session() const; + + /// + /// The attributes of a match request. + /// + _XSAPIIMP const web::json::value& ticket_attributes() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + static ticket_status convert_string_to_ticket_status(_In_ const string_t& value); + + static preserve_session_mode convert_string_to_preserve_session_mode(_In_ const string_t& value); + + ticket_status m_matchStatus; + std::chrono::seconds m_estimatedWaitTime; + preserve_session_mode m_preserveSession; + xbox::services::multiplayer::multiplayer_session_reference m_ticketSession; + xbox::services::multiplayer::multiplayer_session_reference m_targetSession; + web::json::value m_ticketAttributes; +}; + +/// +/// Represents a server response to a hopper statistics request. +/// +class hopper_statistics_response +{ +public: + hopper_statistics_response(); + + hopper_statistics_response( + _In_ string_t hopperName, + _In_ std::chrono::seconds estimatedWaitTime, + _In_ uint32_t playersWaitingToMatch + ); + + /// + /// Name of the hopper in which a match was requested. + /// + _XSAPIIMP const string_t& hopper_name() const; + + /// + /// Estimated wait time for a match request to be matched with other players. + /// + _XSAPIIMP const std::chrono::seconds& estimated_wait_time() const; + + /// + /// The number of players in the hopper waiting to be matched. + /// + _XSAPIIMP uint32_t players_waiting_to_match() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_hopperName; + std::chrono::seconds m_estimatedWaitTime; + uint32_t m_playersWaitingToMatch; +}; + +/// +/// Represents the Matchmaking Service. +/// +class matchmaking_service +{ +public: + /// + /// Sends a matchmaking request to the server and returns the match ticket with a ticket id. + /// + /// The multiplayer session to use for the match. + /// The service configuration ID for the match. + /// The name of the hopper. + /// The maximum time to wait for players to join the session. + /// Indicates if the session should be preserved. + /// The ticket attributes for the session. (Optional) + /// The async object for notifying when the operation is completed. With the handler, a new match ticket + /// object is returned. The match ticket object contains server returned information such as ticket id and wait + /// time, and also contains copies of the title specified data from the ticket data object. + /// Calls V103 POST /serviceconfigs/{serviceConfigId}/hoppers/{hopperName} + _XSAPIIMP pplx::task> create_match_ticket( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& ticketSessionReference, + _In_ const string_t& matchmakingServiceConfigurationId, + _In_ const string_t& hopperName, + _In_ const std::chrono::seconds& ticketTimeout, + _In_ preserve_session_mode preserveSession, + _In_ const web::json::value& ticketAttributesJson = web::json::value() + ); + + /// + /// Deletes a the match ticket on the server. + /// + /// The service config id that is specific for the title. + /// The name of the hopper where the match ticket is located. + /// The id of the ticket to delete on the server. + /// The async object for notifying when the operation has been completed. + /// Calls V103 DELETE /serviceconfigs/{serviceConfigId}/hoppers/{hopperName}/tickets/{ticketId} + _XSAPIIMP pplx::task> delete_match_ticket( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& hopperName, + _In_ const string_t& ticketId + ); + + /// + /// Retrieves the properties of a match ticket from the server. + /// + /// The service config id that is specific for the title. + /// The name of the hopper where the match ticket is located. + /// The ticket id of the match ticket to retrieve. + /// The async object for notifying when the operation is completed. With the handler, the match + /// ticket object with the data for the ticket, including ticket id and wait time information, is returned + /// returned from the server. + /// Calls V103 GET /serviceconfigs/{serviceConfigId}/hoppers/{hopperName}/tickets/{ticketId} + _XSAPIIMP pplx::task> get_match_ticket_details( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& hopperName, + _In_ const string_t& ticketId + ); + + /// + /// Gets statistics about a hopper such as how many players are in it. + /// + /// The service config id that is specific for the title. + /// The name of the hopper to query stats for. + /// The async object for notifying when the operation is completed. With the handler, an object + /// containing statistics about the hopper is returned. + /// Calls V103 GET /serviceconfigs/{serviceConfigId}/hoppers/{hopperName}/stats + _XSAPIIMP pplx::task> get_hopper_statistics( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& hopperName + ); +private: + matchmaking_service() {} + + matchmaking_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static string_t matchmaking_sub_path( + _In_ const string_t& serviceConfigId, + _In_ const string_t& hopperName, + _In_ const string_t& ticketId + ); + + static string_t hopper_sub_path( + _In_ const string_t& serviceConfigId, + _In_ const string_t& hopperName + ); + + static string_t convert_preserve_session_mode_to_string( + _In_ preserve_session_mode preserve_session + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend xbox_live_context_impl; +}; + +}}} diff --git a/Include/xsapi/mem.h b/Include/xsapi/mem.h new file mode 100644 index 00000000..7e70b22c --- /dev/null +++ b/Include/xsapi/mem.h @@ -0,0 +1,145 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#include +#include "xsapi/system.h" + +namespace xbox { namespace services { namespace system { + +class xsapi_memory +{ +public: + static _Ret_maybenull_ _Post_writable_byte_size_(dwSize) void* mem_alloc( + _In_ size_t dwSize + ); + + static void mem_free( + _In_ void* pAddress + ); + +private: + xsapi_memory(); + xsapi_memory(const xsapi_memory&); + xsapi_memory& operator=(const xsapi_memory&); +}; + +class xsapi_memory_buffer +{ +public: + xsapi_memory_buffer(_In_ size_t dwSize) + { + m_pBuffer = xsapi_memory::mem_alloc(dwSize); + } + + ~xsapi_memory_buffer() + { + xsapi_memory::mem_free(m_pBuffer); + m_pBuffer = nullptr; + } + + void* get() + { + return m_pBuffer; + } + +private: + void* m_pBuffer; +}; + +}}} + +template +class xsapi_stl_allocator +{ +public: + xsapi_stl_allocator() { } + + template xsapi_stl_allocator(const xsapi_stl_allocator &) { } + + template + struct rebind + { + typedef xsapi_stl_allocator other; + }; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + pointer allocate(size_type n, const void * = 0) + { + pointer p = reinterpret_cast(xbox::services::system::xsapi_memory::mem_alloc(n * sizeof(T))); + if (p == NULL) + { + throw std::bad_alloc(); + } + return p; + } + + void deallocate(_In_opt_ void* p, size_type) + { + xbox::services::system::xsapi_memory::mem_free(p); + } + + char* _Charalloc(size_type n) + { + char* p = reinterpret_cast(xbox::services::system::xsapi_memory::mem_alloc(n)); + if (p == NULL) + { + throw std::bad_alloc(); + } + return p; + } + + void construct(_In_ pointer p, const_reference t) + { + new ((void*)p) T(t); + } + + void destroy(_In_ pointer p) + { +#if _WIN32 + std::_Destroy(p); +#else + p->~T(); +#endif + } + + size_t max_size() const + { + size_t n = (size_t)(-1) / sizeof(T); + return (0 < n ? n : 1); + } +}; + +template +inline bool operator==(const xsapi_stl_allocator&, const xsapi_stl_allocator&) +{ + return true; +} + +template +bool operator!=(const xsapi_stl_allocator&, const xsapi_stl_allocator&) +{ + return false; +} + +#define xsapi_internal_vector(T) std::vector > + +#define xsapi_internal_unordered_map(Key, T) std::unordered_map, std::equal_to, xsapi_stl_allocator< std::pair< const Key, T > > > + +#define xsapi_internal_string std::basic_string, xsapi_stl_allocator > + +#define xsapi_internal_dequeue(T) std::deque > \ No newline at end of file diff --git a/Include/xsapi/multiplayer.h b/Include/xsapi/multiplayer.h new file mode 100644 index 00000000..3594435c --- /dev/null +++ b/Include/xsapi/multiplayer.h @@ -0,0 +1,4243 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#include +#include "xsapi/real_time_activity.h" +#include "xsapi/game_server_platform.h" + +namespace xbox { namespace services { + class xbox_live_context_impl; + + namespace tournaments { + +/// +/// Defines values used to indicate the state of a tournament game. +/// +enum class tournament_game_result_state +{ + /// + /// No game + /// + no_contest, + + /// + /// Win + /// + win, + + /// + /// loss + /// + loss, + + /// + /// Draw + /// + draw, + + /// + /// Rank + /// + rank, + + /// + /// Didn't show up + /// + no_show, +}; + +/// +/// Defines values used to indicate the arbitration state of a tournament game. +/// +enum class tournament_arbitration_state +{ + /// + /// Results were fully uploaded and complete + /// + completed, + + /// + /// The match was canceled, for example in the case of forfeiting + /// + canceled, + + /// + /// The match begun, but no players or servers reported results in time before the arbitration deadline + /// + no_results, + + /// + /// Some results were received, and results were compiled based on this incomplete data + /// + partial_results +}; + +/// +/// Defines values used to indicate the source for a tournament game state. +/// +enum class tournament_game_result_source +{ + /// + /// No game result source . + /// + none, + + /// + /// Game result source is from client arbitration submit. + /// + arbitration, + + /// + /// Game result is determined by game servers. + /// + server, + + /// + /// Game result is adjusted by tournament administrator. + /// + adjusted, +}; + +/// +/// Defines values used to indicate the status of a tournament game result. +/// +enum class tournament_arbitration_status +{ + /// + /// Occurs before arbitrationStartTime. + /// + waiting, + + /// + /// Occurs after arbitrationStartTime and at least one user has gone active. + /// + in_progress, + + /// + /// The user has reported results and his role in the arbitration process is now done. + /// Occurs either after (arbitrationForfeitTime and no players have joined), (arbitration succeeded), or (arbitrationFinishTime). + /// + complete, + + /// + /// The user has gone active at least once and is now participating in the match. + /// + playing, + + /// + /// The user was not able to upload results before the arbitrationTimeout deadline. + /// + incomplete, +}; + + +/// +/// Defines values used to indicate the team session registration state for a tournament. +/// +enum class tournament_registration_state +{ + /// + /// The team registration state is unknown. + /// + unknown, + + /// + /// Registration was successfully received by the Tournament service and will be eventually processed. + /// + pending, + + /// + /// Registration for the team was withdrawn. + /// + withdrawn, + + /// + /// Registration could not be performed for the team. + /// + rejected, + + /// + /// Registration has been confirmed by the Tournament service. + /// + registered, + + /// + /// The team has completed its participation in the Tournament. + /// + completed +}; + +/// +/// Defines values used to indicate the reason why the team in under selected tournament registration state. +/// +enum class tournament_registration_reason +{ + /// + /// The team registration reason is unknown. + /// + unknown, + + /// + /// The registration for this tournament has been closed. + /// + registration_closed, + + /// + /// One of the team members have already been registered for this tournament. + /// + member_already_registered, + + /// + /// The tournament has reached its max team registration limit and is now full. + /// + tournament_full, + + /// + /// The team has been eliminated from the tournament. + /// + team_eliminated, + + /// + /// The tournament has been completed. + /// + tournament_completed +}; + + +/// +/// Represents a reference to a tournament reference. +/// +class tournament_reference +{ +public: + /// + /// Internal function + /// + tournament_reference(); + + /// + /// Internal function + /// + tournament_reference( + _In_ string_t definitionName, + _In_ string_t tournamentId, + _In_ string_t organizer, + _In_ string_t serviceConfigurationId + ); + + /// + /// The definition name of the tournament. + /// + _XSAPIIMP const string_t& definition_name() const; + + /// + /// The tournament ID specific to the tournament. + /// + _XSAPIIMP const string_t& tournament_id() const; + + /// + /// The organizer name of the tournament. + /// + _XSAPIIMP const string_t& organizer() const; + + /// + /// The service configuration ID specific to the tournament. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// Whether this object has been properly constructed + /// + _XSAPIIMP bool is_null() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_definitionName; + string_t m_tournamentId; + string_t m_organizer; + string_t m_serviceConfigurationId; +}; + +class tournament_team_result +{ +public: + tournament_team_result(); + + tournament_team_result( + _In_ tournament_game_result_state state, + _In_ uint64_t ranking = 0 + ); + + /// + /// The state of the result for the team + /// + _XSAPIIMP tournament_game_result_state state() const; + + /// + /// The ranking of the result + /// + _XSAPIIMP uint64_t ranking() const; + + /// + /// set the state of the result for the team + /// + _XSAPIIMP void set_state(_In_ tournament_game_result_state state); + + /// + /// set the ranking of the result + /// + _XSAPIIMP void set_ranking(_In_ uint64_t ranking); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + tournament_game_result_state m_state; + uint64_t m_ranking; +}; + +}}} +namespace xbox { namespace services { + class xbox_live_context_impl; + namespace multiplayer { + namespace manager { + class multiplayer_client_manager; + }} + + /// + /// Contains classes and enumerations for managing a multiplayer session. + /// + namespace multiplayer { + +class multiplayer_session_request; +class multiplayer_session_member_request; +class multiplayer_service_impl; + +/// +/// Defines values used to indicate status for visibility or accessibility of a session. +/// +enum class multiplayer_session_visibility +{ + /// Unknown + unknown, + + /// Ignore the SessionVisibility filter. + any, + + /// + /// The session is private and it's not visible to other users who + /// aren't in the session. Joining a visible or private session is a HTTP_E_STATUS_FORBIDDEN. + /// + private_session, + + /// + /// The session is visible to other users who aren't in the session, but the session is read-only to them and they can't join. + /// Joining an visible causes the service to return HTTP_E_STATUS_BAD_REQUEST (403). + /// + visible, + + /// + /// The session is full and cannot be joined by anyone. + /// Joining an open but full session causes the service to return HTTP_E_STATUS_BAD_REQUEST (400). + /// + full, + + /// The session is open and can be joined by anyone. + open +}; + +/// +/// Defines values used to indicate status for the initialization stage of a session during managed initialization. +/// +enum class multiplayer_initialization_stage +{ + /// Unknown + unknown, + + /// Initialization stage not set. + none, + + /// + /// Joining initialization stage. + /// Typically matchmaking creates session and puts users into it. + /// SPC has up to the joining timeout to join the session during this phase. + /// + joining, + + /// + /// Measuring initialization stage. Stage where QoS measurement happens. + /// If the title is manually managing QoS, then title will do this stage. + /// Otherwise the Party system will do this when calling RegisterGameSession or RegisterMatchSession. + /// + measuring, + + /// + /// Evaluating initialization stage. + /// If auto evaluate is true, then this stage is skipped. + /// Otherwise the title will do its own evaluation. + /// This stage is applied even with the SPC is managing QoS. + /// + evaluating, + + /// + /// Failed initialization stage. + /// If episode 1 didn't succeed, then goes into failed permanently. + /// + failed +}; + +/// +/// Defines values used to indicate the type of metric used to measure matchmaking QoS for a session. +/// +enum class multiplay_metrics +{ + /// Unknown metric + unknown, + + /// Bandwidth host selection metric + bandwidth_up, + + /// Bandwidth down host selection metric + bandwidth_down, + + /// Bandwidth host selection metric + bandwidth, + + /// Latency host selection metric + latency +}; + +/// +/// Defines values used to indicate the current network address translation (NAT) settings for a console connecting to Xbox Live. +/// +enum class network_address_translation_setting +{ + /// The server returned an unrecognized response. + unknown, + + /// Can connect with any other consoles regardless of their NAT setting. + open, + + /// Consoles using Moderate NAT settings can only connect with other consoles using Moderate or Open settings. + moderate, + + /// Consoles using Strict NAT settings can only connect with other consoles using Open NAT settings. + strict +}; + +/// +/// Defines values used to indicate types measurement failures for a session member on the network. +/// +enum class multiplayer_measurement_failure +{ + /// Unknown measurement failure + unknown, + + /// This player has no measurement failure. + none, + + /// This player failed because timeout measurement test failed. + timeout, + + /// This player failed because latency measurement test failed. + latency, + + /// This player failed because bandwidth up measurement test failed. + bandwidth_up, + + /// This player failed because bandwidth down measurement test failed. + bandwidth_down, + + /// This player failed cause someone failed in their group failed. + group, + + /// This player failed due to a network error such as the user was unreachable. + network, + + /// This player failed because your episode failed. This likely happened because there wasn't enough users in the session. + episode +}; + +/// +/// Defines values used to indicate current status values for a session. +/// +enum class multiplayer_session_status +{ + /// + /// The server returned an unrecognized response. + /// + unknown, + + /// + /// The session is active and there is at least one user. + /// + active, + + /// + /// The session is inactive. This means no users in the session are + /// active or all users left the session. + /// + inactive, + + /// + /// The session is reserved. This means one for more users have not + /// accepted the session invite. + /// + reserved +}; + +/// +/// Defines values used to indicate restrictions on the users who can join a session. +/// +enum class multiplayer_session_restriction +{ + /// The unrecognized restriction type. + unknown, + + /// Default value, no restriction + none, + + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + local, + + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can join without a reservation. + followed +}; + +/// +/// Defines values used to indicate status for a matchmaking request for a session. +/// +enum class matchmaking_status +{ + /// The server returned an unrecognized response. + unknown, + + /// Indicates the matchmaking search is not specified. This status is optional and requires the clientMatchmaking capability. + none, + + /// Indicates the matchmaking search is still searching. + searching, + + /// Indicates the matchmaking search has expired. + expired, + + /// Indicates the matchmaking search has found a session. + found, + + /// Indicates the matchmaking search has been canceled. + canceled +}; + +/// +/// Defines values used to indicate status for member of a session. +/// +enum class multiplayer_session_member_status +{ + /// + /// Member is reserved for a specific Xbox User ID. + /// This specific member must join the session to fill the reservation. + /// If a reserved member doesn't join before the JoinTimeout they will be removed. + /// + reserved, + + /// + /// The member is inactive in the current title. + /// The member may be active in another title as specified by ActiveTitleId. + /// If a inactive member doesn't mark themselves as Active within the MemberInactiveTimeout they will be removed from the session. + /// + inactive, + + /// + /// When the shell launches the title to start a multiplayer game, the member is marked as ready. + /// If a ready member doesn't mark themselves as Active within the MemberReadyTimeout they will be marked as inactive. + /// + ready, + + /// The member is active in the current title. + active +}; + +/// +/// Defines values used to indicate the mode used when creating or writing to a new Multiplayer service session. +/// +enum class multiplayer_session_write_mode +{ + /// + /// Create a new multiplayer session. Fails if the session already exists. + /// + create_new, + + /// + /// Either update or create a new session. Doesn't care whether the session exists. + /// + update_or_create_new, + + /// + /// Updates an existing multiplayer session; fails if the session doesn't exist. + /// + update_existing, + + /// + /// Updates an existing multiplayer session. Fails with HTTP_E_STATUS_PRECOND_FAILED (HTTP status 412) if eTag on local session doesn't match eTag on server. + /// Fails if the session does not exist. + /// + synchronized_update, +}; + +enum class write_session_status +{ + /// + /// Unknown write result + /// + unknown, + + /// + /// HTTP Result 403- User does not have proper permission to write a session + /// + access_denied, + + /// + /// HTTP Result 201- Write created session successfully + /// + created, + + /// + /// HTTP Result 409- Conflict occurred during write about session document + /// + conflict, + + /// + /// HTTP Result 404- Session not found + /// + handle_not_found, + + /// + /// HTTP Result 412- Session docuemnt is not the most recent + /// + out_of_sync, + + /// + /// HTTP Result 204- Session deleted successfully + /// + session_deleted, + + /// + /// HTTP Result 200- Session updated successfully + /// + updated +}; + +/// +/// Defines values used to indicate change types for a multiplayer session. +/// +enum multiplayer_session_change_types +{ + /// + /// None + /// + none = 0x0000, + + /// + /// Changes to anything in the session. + /// + everything = 0x0001, + + /// + /// Changes to the host device token. + /// + host_device_token_change = 0x0002, + + /// + /// Changes to the stage of initialization has changed. + /// + initialization_state_change = 0x0004, + + /// + /// Changes to the matchmaking status (e.g. match found or expired) + /// + matchmaking_status_change = 0x0008, + + /// + /// A member joined the session + /// + member_list_change = 0x0010, + + /// + /// A member left the session + /// + member_status_change = 0x0020, + + /// + /// Changes to the joinability of the session. + /// + session_joinability_change = 0x0040, + + /// + /// Changes within properties/custom + /// + custom_property_change = 0x0080, + + /// + /// Changes within member/properties/custom, for any of the members. + /// + member_custom_property_change = 0x0100, + + /// + /// Changes within tournament server properties. Such as next game, last game, or registration. + /// + tournament_property_change = 0x0200, + + /// + /// Changes within arbitration server properties. Such as game results. + /// + arbitration_property_change = 0x0400 +}; + +/// +/// Defines values used to indicate mutable_role_setting types for a multiplayer role. +/// Note: Only the session owner can modify role settings and only those that are set as multiplayer_role_type::mutable_role_settings(). +/// The mutable_role_settings can be set in the session template. +/// +enum class mutable_role_setting +{ + /// + /// Allows you to set a max count for the multiplayer role + /// + max, + + /// + /// Allows you to set a target count for the multiplayer role + /// + target +}; + +/// +/// Represents requirements that apply to each connection between a host candidate and session members. +/// +class multiplayer_peer_to_host_requirements +{ +public: + /// + /// Internal function + /// + multiplayer_peer_to_host_requirements(); + + /// + /// Internal function + /// + multiplayer_peer_to_host_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32_t bandwidthUpMinimumInKilobitsPerSecond, + _In_ multiplay_metrics hostSelectionMetric + ); + + /// + /// The maximum latency for the peer to host connection. + /// + _XSAPIIMP const std::chrono::milliseconds& latency_maximum() const; + + /// + /// The minimum bandwidth down in kilobits per second for the peer to host connection. + /// + _XSAPIIMP uint64_t bandwidth_down_minimum_in_kilobits_per_second() const; + + /// + /// The minimum bandwidth up in kilobits per second for the peer to host connection. + /// + _XSAPIIMP uint64_t bandwidth_up_minimum_in_kilobits_per_second() const; + + /// + /// Indicates which metric was used to select the host. + /// + _XSAPIIMP multiplay_metrics host_selection_metric() const; + + /// + /// Internal function + /// + web::json::value _Serialize(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::chrono::milliseconds m_latencyMaximum; + uint64_t m_bandwidthDownMinimumInKilobitsPerSecond; + uint64_t m_bandwidthUpMinimumInKilobitsPerSecond; + multiplay_metrics m_hostSelectionMetric; +}; + +/// +/// Represents requirements for a connection between session members. +/// +class multiplayer_peer_to_peer_requirements +{ +public: + /// + /// Internal function + /// + multiplayer_peer_to_peer_requirements(); + + /// + /// Internal function + /// + multiplayer_peer_to_peer_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthMinimumInKilobitsPerSecond + ); + + /// + /// The maximum latency for the peer to peer connection. + /// + _XSAPIIMP uint64_t bandwidth_minimum_in_kilobits_per_second() const; + + /// + /// The minimum bandwidth in kilobits per second for the peer to peer connection. + /// + _XSAPIIMP const std::chrono::milliseconds& latency_maximum() const; + + /// + /// Internal function + /// + web::json::value _Serialize(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + uint64_t m_bandwidthMinimumInKilobitsPerSecond; + std::chrono::milliseconds m_latencyMaximum; +}; + +/// +/// DEPRECATED. Instead use multiplayer_member_initialization class +/// Used to configure requirements and initialize a new Multiplayer session. +/// +class multiplayer_managed_initialization +{ +public: + /// + /// Internal function + /// + multiplayer_managed_initialization(); + + /// + /// Internal function + /// + multiplayer_managed_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measureTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool autoEvaluate, + _In_ uint32_t membersNeededToStart + ); + + /// + /// Indicates if the ManagedInitializion object is set. + /// + _XSAPIIMP bool managed_initialization_set() const; + + /// + /// Returns the timeout for the first stage of the QoS process which is the joining stage. + /// + _XSAPIIMP const std::chrono::milliseconds& join_timeout() const; + + /// + /// Returns the timeout for the measurement stage of the QoS process. + /// + _XSAPIIMP const std::chrono::milliseconds& measurement_timeout() const; + + /// + /// Returns the timeout for the evaluation stage of the QoS process. + /// + _XSAPIIMP const std::chrono::milliseconds& evaluation_timeout() const; + + /// + /// This is an optional evaluate stage for title. The title can do evaluation when set to false. + /// + _XSAPIIMP bool auto_evaluate() const; + + /// + /// Defaults to 2. Must be between 1 and maxMemberCount. Only applies to initialization episode zero. + /// + _XSAPIIMP uint32_t members_need_to_start() const; + + /// + /// Internal function + /// + web::json::value _Serialize(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::chrono::milliseconds m_joinTimeout; + std::chrono::milliseconds m_measurementTimeout; + std::chrono::milliseconds m_evaluationTimeout; + bool m_managedInitializationSet; + bool m_autoEvaluate; + bool m_writeManagedInitialization; + uint32_t m_membersNeededToStart; +}; + +/// +/// Used to configure requirements and initialize a new Multiplayer session. +/// +class multiplayer_member_initialization +{ +public: + /// + /// Internal function + /// + multiplayer_member_initialization(); + + /// + /// Internal function + /// + multiplayer_member_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measureTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool externalEvaluation, + _In_ uint32_t membersNeededToStart + ); + + /// + /// Indicates if the ManagedInitializion object is set. + /// + _XSAPIIMP bool member_initialization_set() const; + + /// + /// Returns the timeout for the first stage of the QoS process which is the joining stage. + /// + _XSAPIIMP const std::chrono::milliseconds& join_timeout() const; + + /// + /// Returns the timeout for the measurement stage of the QoS process. + /// + _XSAPIIMP const std::chrono::milliseconds& measurement_timeout() const; + + /// + /// Returns the timeout for the evaluation stage of the QoS process. + /// + _XSAPIIMP const std::chrono::milliseconds& evaluation_timeout() const; + + /// + /// This is an optional evaluate stage for title. The title can do evaluation when set to true. + /// + _XSAPIIMP bool external_evaluation() const; + + /// + /// Defaults to 2. Must be between 1 and maxMemberCount. Only applies to initialization episode zero. + /// + _XSAPIIMP uint32_t members_need_to_start() const; + + /// + /// Internal function + /// + web::json::value _Serialize(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::chrono::milliseconds m_joinTimeout; + std::chrono::milliseconds m_measurementTimeout; + std::chrono::milliseconds m_evaluationTimeout; + bool m_managedInitializationSet; + bool m_externalEvaluation; + bool m_writeManagedInitialization; + uint32_t m_membersNeededToStart; +}; + +/// +/// Represents the capabilities of a multiplayer session. +/// +/// +/// Session capabilities are boolean values that are optionally set in the session template. If no capabilities are needed, an empty SessionCapabilities object should be in the template to prevent capabilities from being specified on session creation, unless the title requires dynamic session capabilities. +/// +class multiplayer_session_capabilities +{ +public: + /// + /// Constructor + /// + _XSAPIIMP multiplayer_session_capabilities(); + + /// + /// If false, the session can't enable any metrics and the session members can not set their SecureDeviceAddress. + /// + _XSAPIIMP bool connectivity() const; + + /// + /// If false, the session can't enable any metrics and the session members can not set their SecureDeviceAddress. + /// + _XSAPIIMP void set_connectivity(_In_ bool connectivity); + + /// + /// True if team capability is set on the session for a tournament. + /// + _XSAPIIMP bool team() const; + + /// + /// Session supports team capability for a tournament + /// + _XSAPIIMP void set_team(_In_ bool crossplay); + + /// + /// True if arbitration capability is set on the session for a tournament. + /// + _XSAPIIMP bool arbitration() const; + + /// + /// Session supports arbitration capability for a tournament + /// + _XSAPIIMP void set_arbitration(_In_ bool crossplay); + + /// + /// By default (if false), active users are required to remain online playing the title, otherwise they get demoted to + /// inactive status. Setting this flag to true disables this check so that members stay active indefinitely. + /// + _XSAPIIMP bool suppress_presence_activity_check() const; + + /// + /// By default (if false), active users are required to remain online playing the title, otherwise they get demoted to + /// inactive status. Setting this flag to true disables this check so that members stay active indefinitely. + /// + _XSAPIIMP void set_suppress_presence_activity_check(_In_ bool suppressPresenceActivityCheck); + + /// + /// Indicates whether the session represents actual gameplay, as opposed to setup/menu time like a lobby or matchmaking. + /// If true, then the session is in gameplay mode. + /// + _XSAPIIMP bool gameplay() const; + + /// + /// Indicates whether the session represents actual gameplay, as opposed to setup/menu time like a lobby or matchmaking. + /// If true, then the session is in gameplay mode. + /// + _XSAPIIMP void set_gameplay(_In_ bool gameplay); + + /// + /// If true, this session can host a large number of users, which has impact on other session properties (see documentation) + /// + _XSAPIIMP bool large() const; + + /// + /// If true, this session can host a large number of users, which has impact on other session properties (see documentation) + /// + _XSAPIIMP void set_large(_In_ bool large); + + /// + /// If true, this connection is required to have a member be active (see documentation) + /// + _XSAPIIMP bool connection_required_for_active_members() const; + + /// + /// If true, this connection is required to have a member be active (see documentation) + /// + _XSAPIIMP void set_connection_required_for_active_members(_In_ bool connectionRequired); + + /// + /// Session supports calls from platforms without strong title identity. This capability can't be set on large sessions. + /// + _XSAPIIMP bool user_authorization_style() const; + + /// + /// Session supports calls from platforms without strong title identity. This capability can't be set on large sessions. + /// + _XSAPIIMP void set_user_authorization_style(_In_ bool userAuthorizationStyle); + + /// + /// Session supports cross play between PC and Xbox + /// + _XSAPIIMP bool crossplay() const; + + /// + /// Session supports cross play between PC and Xbox + /// + _XSAPIIMP void set_crossplay(_In_ bool crossplay); + + /// + /// True, if the session can be linked to a search handle for searching. + /// + _XSAPIIMP bool searchable() const; + + /// + /// Allows the session to be linked to a search handle for searching. + /// + _XSAPIIMP void set_searchable(_In_ bool searchable); + + /// + /// True, if the session has owners. If you have user_authorization_style set, then in order to be searchable, you must have owners set. + /// + _XSAPIIMP bool has_owners() const; + + /// + /// If you have user_authorization_style set, then in order to be searchable, you must have owners set. + /// + _XSAPIIMP void set_has_owners(_In_ bool hasOwners); + +private: + bool m_connectivity; + bool m_suppressPresenceActivityCheck; + bool m_gameplay; + bool m_large; + bool m_connectionRequiredForActiveMembers; + bool m_userAuthorizationStyle; + bool m_crossplay; + bool m_team; + bool m_arbitration; + bool m_searchable; + bool m_hasOwners; + + friend class multiplayer_session_constants; +}; + +/// +/// Represents matchmaking quality of service (QoS) measurements for the network used by a session member. +/// +class multiplayer_quality_of_service_measurements +{ +public: + multiplayer_quality_of_service_measurements(); + + /// + /// Creates a new MultiplayerQualityOfServiceMeasurements object. + /// + /// The device token of the member that this measurement is for. + /// The time of the latency measurement. + /// The bandwidth down in kilobits per second. + /// The bandwidth up in kilobits per second. + /// JSON string that specify the custom properties. + _XSAPIIMP multiplayer_quality_of_service_measurements( + _In_ string_t memberDeviceToken, + _In_ std::chrono::milliseconds latency, + _In_ uint64_t bandwidthDownInKilobitsPerSecond, + _In_ uint64_t bandwidthUpInKilobitsPerSecond, + _In_ string_t customJson + ); + + /// + /// The device token of the member that this measurement is for. + /// + _XSAPIIMP const string_t& member_device_token() const; + + /// + /// The time of the latency measurement. + /// + _XSAPIIMP const std::chrono::milliseconds& latency() const; + + /// + /// The bandwidth down in kilobits per second. + /// + _XSAPIIMP uint64_t bandwidth_down_in_kilobits_per_second() const; + + /// + /// The bandwidth up in kilobits per second. + /// + _XSAPIIMP uint64_t bandwidth_up_in_kilobits_per_second() const; + + /// + /// JSON string that specify the custom properties. + /// + _XSAPIIMP const web::json::value& custom_json() const; + + /// + /// Internal function + /// + void _Set_member_device_token(_In_ const string_t& memberDeviceToken); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_memberDeviceToken; + std::chrono::milliseconds m_latency; + uint64_t m_bandwidthDownInKilobitsPerSecond; + uint64_t m_bandwidthUpInKilobitsPerSecond; + web::json::value m_customJson; +}; + +/// +/// Represents constant values for a multiplayer session. +/// +class multiplayer_session_constants +{ +public: + /// + /// Internal function + /// + multiplayer_session_constants(); + + /// + /// Internal function + /// + multiplayer_session_constants( + _In_ uint32_t maxMembersInSession, + _In_ multiplayer_session_visibility visibility, + _In_ std::vector initiatorXboxIds, + _In_ web::json::value sessionCustomConstants + ); + + /// + /// Internal function + /// + multiplayer_session_constants( + _In_ std::vector initiatorXboxIds + ); + + /// + /// The maximum number of members in this session. + /// + _XSAPIIMP uint32_t max_members_in_session() const; + + /// + /// The maximum number of members in this session. + /// + _XSAPIIMP void set_max_members_in_session(_In_ uint32_t maxMembersInSession); + + /// + /// The visibility of this session. + /// + _XSAPIIMP multiplayer_session_visibility visibility() const; + + /// + /// The visibility of this session. + /// + _XSAPIIMP void set_visibility(_In_ multiplayer_session_visibility visibility); + + /// + /// A collection of Xbox User IDs indicating who initiated the session. (Optional) + /// + _XSAPIIMP const std::vector& initiator_xbox_user_ids() const; + + /// + /// JSON string that specify the custom constants for the session. These can not be changed after the session is created. (Optional) + /// + _XSAPIIMP const web::json::value& session_custom_constants_json() const; + + /// + /// If a member reservation does not join within this timeout, then reservation is removed. + /// + _XSAPIIMP const std::chrono::milliseconds& member_reserved_time_out() const; + + /// + /// If a inactive member reservation does not become active within this timeout, then inactive member is removed from the session. + /// + _XSAPIIMP const std::chrono::milliseconds& member_inactive_timeout() const; + + /// + /// If a member who is marked as ready doesn't mark themselves as active within this timeout, then member becomes inactive. + /// When the shell launches the title to start a multiplayer game, the member is marked as ready. + /// + _XSAPIIMP const std::chrono::milliseconds& member_ready_timeout() const; + + /// + /// If the session is empty for this timeout, then the session is deleted. + /// + _XSAPIIMP const std::chrono::milliseconds& session_empty_timeout() const; + + /// + /// Delta from start time representing the point at which results are finalized. If no one has reported (client or server) at this point, we declare the match results incomplete. + /// + _XSAPIIMP const std::chrono::milliseconds& arbitration_timeout() const; + + /// + /// Delta from start time representing the point at which, if the session has no active users, the match is canceled. + /// + _XSAPIIMP const std::chrono::milliseconds& forfeit_timeout() const; + + /// + /// Indicates if the title wants latency measured for determining connectivity + /// Requires CapabilitiesConnectivity capability. + /// + _XSAPIIMP bool enable_metrics_latency() const; + + /// + /// Indicates if the title wants bandwidth down measured for determining connectivity + /// Requires CapabilitiesConnectivity capability. + /// + _XSAPIIMP bool enable_metrics_bandwidth_down() const; + + /// + /// Indicates if the title wants bandwidth up measured for determining connectivity + /// Requires CapabilitiesConnectivity capability. + /// + _XSAPIIMP bool enable_metrics_bandwidth_up() const; + + /// + /// Indicates if the title wants a custom measurement measured for determining connectivity + /// Requires CapabilitiesConnectivity capability. + /// + _XSAPIIMP bool enable_metrics_custom() const; + + /// + /// DEPRECATED. Instead call member_initialization() + /// If a ManagedInitialization object is set, the session expects the client system or title to perform + /// initialization following session creation. The timeouts and initialization stages are automatically tracked by + /// the session, including initial QoS if any metrics are set. + /// + _XSAPIIMP_DEPRECATED const multiplayer_managed_initialization& managed_initialization() const; + + /// + /// If a MemberInitialization object is set, the session expects the client system or title to perform + /// initialization following session creation. The timeouts and initialization stages are automatically tracked by + /// the session, including initial QoS if any metrics are set. + /// + _XSAPIIMP const multiplayer_member_initialization& member_initialization() const; + + /// + /// Peer to peer QoS requirements + /// + _XSAPIIMP const multiplayer_peer_to_peer_requirements& peer_to_peer_requirements() const; + + /// + /// Peer to host QoS requirements + /// + _XSAPIIMP const multiplayer_peer_to_host_requirements& peer_to_host_requirements() const; + + /// + /// The set of potential server connection strings that should be evaluated. + /// + _XSAPIIMP const web::json::value& measurement_server_addresses_json() const; + + /// + /// Indicates whether the matchmaking status fields can be written to. + /// + _XSAPIIMP bool client_matchmaking_capable() const; + + /// + /// If false, the session can't enable any metrics and the session members can not set their SecureDeviceAddress. + /// + _XSAPIIMP bool capabilities_connectivity() const; + + /// + /// By default (if false), active users are required to remain online playing the title, otherwise they get demoted to + /// inactive status. Setting this flag to true disables this check so that members stay active indefinitely. + /// + _XSAPIIMP bool capabilities_suppress_presence_activity_check() const; + + /// + /// Indicates whether the session represents actual gameplay, as opposed to setup/menu time like a lobby or matchmaking. + /// If true, then the session is in gameplay mode. + /// + _XSAPIIMP bool capabilities_gameplay() const; + + /// + /// If true, this session can host a large number of users, which has impact on other session properties. + /// + _XSAPIIMP bool capabilities_large() const; + + /// + /// If true, this connection is required to have a member be active (see documentation) + /// + _XSAPIIMP bool capabilities_connection_required_for_active_member() const; + + /// + /// Session supports cross play between PC and Xbox + /// + _XSAPIIMP bool capabilities_crossplay() const; + + /// + /// Session supports calls from platforms without strong title identity. This capability can't be set on large sessions. + /// Using this capability will cause both readRestriction and joinRestriction to default to local. + /// + _XSAPIIMP bool capabilities_user_authorization_style() const; + + /// + /// True if team capability is set on the session for a tournament. + /// + _XSAPIIMP bool capabilities_team() const; + + /// + /// True, if the session can be linked to a search handle for searching. + /// + _XSAPIIMP bool capabilities_searchable() const; + + /// + /// True if arbitration capability is set on the session for a tournament. + /// + _XSAPIIMP bool capabilities_arbitration() const; + + /// + /// Internal function + /// + void _Set_timeouts( + _In_ std::chrono::milliseconds memberReservedTimeout, + _In_ std::chrono::milliseconds memberInactiveTimeout, + _In_ std::chrono::milliseconds memberReadyTimeout, + _In_ std::chrono::milliseconds sessionEmptyTimeout + ); + + /// + /// Internal function + /// + void _Set_arbitration_timeouts( + _In_ std::chrono::milliseconds arbitrationTimeout, + _In_ std::chrono::milliseconds forfeitTimeout + ); + + /// + /// Internal function + /// + void _Set_quality_of_service_connectivity_metrics( + _In_ bool enableLatencyMetric, + _In_ bool enableBandwidthDownMetric, + _In_ bool enableBandwidthUpMetric, + _In_ bool enableCustomMetric + ); + + /// + /// Internal function + /// + void _Set_managed_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32_t membersNeededToStart + ); + + /// + /// Internal function + /// + void _Set_member_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool externalEvaluation, + _In_ uint32_t membersNeededToStart + ); + + /// + /// Internal function + /// + void _Set_peer_to_peer_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthMinimumInKilobitsPerSecond + ); + + /// + /// Internal function + /// + void _Set_peer_to_host_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32_t bandwidthUpMinimumInKilobitsPerSecond, + _In_ multiplay_metrics hostSelectionMetric + ); + + /// + /// Internal function + /// + void _Set_measurement_server_addresses( + _In_ const std::vector& serverAddresses + ); + + /// + /// Internal function + /// + void _Set_session_capabilities( + _In_ const multiplayer_session_capabilities& capabilities + ); + + /// + /// Internal function + /// + bool _Should_serialize() const; + + /// + /// Internal function + /// + web::json::value _Serialize(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + uint32_t m_maxMembersInSession; + multiplayer_session_visibility m_visibility; + std::vector m_initiatorXboxUserIds; + web::json::value m_sessionCustomConstants; + multiplayer_session_capabilities m_sessionCapabilities; + + // Arbitration timeouts + bool m_writeArbitrationTimeouts; + std::chrono::milliseconds m_arbitrationTimeout; + std::chrono::milliseconds m_forfeitTimeout; + + // Timeouts + bool m_writeTimeouts; + std::chrono::milliseconds m_memberReservedTimeout; + std::chrono::milliseconds m_memberInactiveTimeout; + std::chrono::milliseconds m_memberReadyTimeout; + std::chrono::milliseconds m_sessionEmptyTimeout; + + // QualityOfServiceConnectivityMetrics + bool m_writeQualityOfServiceConnectivityMetrics; + bool m_enableMetricsLatency; + bool m_enableMetricsBandwidthDown; + bool m_enableMetricsBandwidthUp; + bool m_enableMetricsCustom; + bool m_shouldSerialize; + + // ManagedInitialization + bool m_writeMemberInitialization; + multiplayer_managed_initialization m_managedInitialization; + multiplayer_member_initialization m_memberInitialization; + + // PeerToPeerRequirements + bool m_writePeerToPeerRequirements; + multiplayer_peer_to_peer_requirements m_peerToPeerRequirements; + + // PeerToHostRequirements + bool m_writePeerToHostRequirements; + multiplayer_peer_to_host_requirements m_peerToHostRequirements; + + // MeasurementServerAddresses + bool m_writeMeasurementServerAddresses; + web::json::value m_measurementServerAddressesJson; + + static std::mutex m_lock; +}; + +/// +/// Represents a reference to a multiplayer session. +/// +class multiplayer_session_reference +{ +public: + /// + /// Constructs a null MultiplayerSession object. + /// + _XSAPIIMP multiplayer_session_reference(); + +#ifndef DEFAULT_MOVE_ENABLED + _XSAPIIMP multiplayer_session_reference(multiplayer_session_reference&& other); + + _XSAPIIMP multiplayer_session_reference& operator=(multiplayer_session_reference&& other); +#endif + + /// + /// Constructs the MultiplayerSession object with data about the session. + /// + /// A service configuration ID appropriate for the title. + /// The name of the template for the session to be based on. + /// A unique name for the session. + _XSAPIIMP multiplayer_session_reference( + _In_ string_t serviceConfigurationId, + _In_ string_t sessionTemplateName, + _In_ string_t sessionName + ); + + /// + /// The service configuration ID specific to the title. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The name of the template for the session. + /// + _XSAPIIMP const string_t& session_template_name() const; + + /// + /// The name of the session. + /// + _XSAPIIMP const string_t& session_name() const; + + /// + /// Whether this object has been properly constructed + /// + _XSAPIIMP bool is_null() const; + + /// + /// Returns a URI path representation of the session reference. + /// + _XSAPIIMP string_t to_uri_path() const; + + /// + /// Internal function + /// + web::json::value _Serialize() const; + + /// + /// Returns the session reference parsed from URI. + /// + static multiplayer_session_reference parse_from_uri_path(_In_ const string_t& path); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_serviceConfigurationId; + string_t m_sessionTemplateName; + string_t m_sessionName; +}; + +/// +/// Represents the matchmaking server supporting the multiplayer session. +/// +class multiplayer_session_matchmaking_server +{ +public: + /// + /// Internal function + /// + multiplayer_session_matchmaking_server(); + + /// + /// The Matchmaking Status of the Multiplayer Session Server. + /// + _XSAPIIMP matchmaking_status status() const; + + /// + /// The Matchmaking Status Details of the Multiplayer Session Server. + /// + _XSAPIIMP const string_t& status_details() const; + + /// + /// The Typical Wait of the Multiplayer Session Server. + /// + _XSAPIIMP const std::chrono::seconds& typical_wait() const; + + /// + /// The Target Session Reference of the Multiplayer Session Server. + /// + _XSAPIIMP const multiplayer_session_reference& target_session_ref() const; + + /// + /// Returns true if this object is blank + /// + _XSAPIIMP bool is_null() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + matchmaking_status m_status; + string_t m_statusDetails; + std::chrono::seconds m_typicalWait; + multiplayer_session_reference m_targetSessionRef; + bool m_isNull; +}; + +/// +/// Represents the arbitration server supporting the multiplayer session. +/// +class multiplayer_session_arbitration_server +{ +public: + multiplayer_session_arbitration_server(); + + /// + /// The state of the result + /// + _XSAPIIMP xbox::services::tournaments::tournament_arbitration_state result_state() const; + + /// + /// The source of the result + /// + _XSAPIIMP xbox::services::tournaments::tournament_game_result_source result_source() const; + + /// + /// A value from 0-100 that indicates the confidence level of this result + /// + _XSAPIIMP uint32_t result_confidence_level() const; + + /// + /// The results of the game + /// + _XSAPIIMP const std::unordered_map& results() const; + + /// + /// Internal Function + /// + bool _Is_null() const; + + /// + /// Internal Function + /// + bool _Is_same(const multiplayer_session_arbitration_server& other) const; + + /// + /// Internal function + /// + static xbox::services::tournaments::tournament_arbitration_state _Convert_string_to_arbitration_state(_In_ const string_t& value); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + xbox::services::tournaments::tournament_arbitration_state m_resultState; + uint32_t m_resultConfidenceLevel; + xbox::services::tournaments::tournament_game_result_source m_resultSource; + std::unordered_map m_results; + bool m_isNull; +}; + +/// +/// Represents the tournament server supporting the multiplayer session. +/// +class multiplayer_session_tournaments_server +{ +public: + multiplayer_session_tournaments_server(); + + /// + /// The tournament reference. + /// + _XSAPIIMP const xbox::services::tournaments::tournament_reference& tournament_reference() const; + + /// + /// The teams in the tournament + /// + _XSAPIIMP const std::unordered_map& teams() const; + + /// + /// The tournament registration state of the team. + /// + _XSAPIIMP xbox::services::tournaments::tournament_registration_state registration_state() const; + + /// + /// The tournament registration reaon for the certain state. + /// + _XSAPIIMP xbox::services::tournaments::tournament_registration_reason registration_reason() const; + + /// + /// Next game's start time for the tournament. + /// + _XSAPIIMP const utility::datetime& next_game_start_time() const; + + /// + /// Next game session reference for the tournament. + /// + _XSAPIIMP const multiplayer_session_reference& next_game_session_reference() const; + + /// + /// The last game's end time for the tournament. + /// + _XSAPIIMP const utility::datetime& last_game_end_time() const; + + /// + /// The last game's state for the tournament. + /// + _XSAPIIMP xbox::services::tournaments::tournament_team_result last_team_result() const; + + /// + /// The source for the last game's state of the tournament. + /// + _XSAPIIMP xbox::services::tournaments::tournament_game_result_source last_game_result_source() const; + + /// + /// Internal Function + /// + bool _Is_null() const; + + /// + /// Internal Function + /// + bool _Is_same(const multiplayer_session_tournaments_server& other) const; + + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + static xbox::services::tournaments::tournament_registration_state _Convert_string_to_registration_result(_In_ const string_t& value); + static xbox::services::tournaments::tournament_registration_reason _Convert_string_to_registration_reason(_In_ const string_t& value); + +private: + xbox::services::tournaments::tournament_registration_state m_registrationState; + xbox::services::tournaments::tournament_registration_reason m_registrationReason; + xbox::services::tournaments::tournament_team_result m_lastTeamResult; + xbox::services::tournaments::tournament_game_result_source m_lastGameResultSource; + xbox::services::tournaments::tournament_reference m_tournamentRef; + utility::datetime m_nextGameStartTime; + multiplayer_session_reference m_nextGameSessionReference; + utility::datetime m_lastGameEndTime; + bool m_isNull; + std::unordered_map m_teams; +}; + +/// +/// Represents role info for a multiplayer role. +/// +class multiplayer_role_info +{ +public: + /// + /// Member xbox_user_ids currently assigned for this role. + /// + _XSAPIIMP const std::vector& member_xbox_user_ids() const; + + /// + /// Number of slots occupied for this role. + /// + _XSAPIIMP uint32_t members_count() const; + + /// + /// Number of target slots assigned for this role. + /// + _XSAPIIMP uint32_t target_count() const; + + /// + /// Maximum number of slots available for this role. + /// + _XSAPIIMP uint32_t max_members_count() const; + + /// + /// Set the max member count for this role. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + /// The max member count for this role. + _XSAPIIMP void set_max_members_count(_In_ uint32_t maxCount); + + /// + /// Set the target member count for this role. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + /// The max member count for this role. + _XSAPIIMP void set_target_count(_In_ uint32_t targetCount); + + /// + /// Internal function + /// + _XSAPIIMP multiplayer_role_info(); + + /// + /// Internal function + /// + static xbox::services::xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::vector m_memberXuids; + uint32_t m_maxMembersCount; + uint32_t m_membersCount; + uint32_t m_targetCount; +}; + +/// +/// Represents a collection of roles for this role type. +/// +class multiplayer_role_type +{ +public: + /// + /// True if ownerManaged is set on the roleType. + /// + _XSAPIIMP bool owner_managed() const; + + /// + /// Mutable role settings for this role. + /// + _XSAPIIMP const std::vector& mutable_role_settings() const; + + /// + /// A collection of roles for this role type. + /// + _XSAPIIMP const std::unordered_map& roles() const; + + /// + /// Set a collection of roles for this role type. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + _XSAPIIMP void set_roles(_In_ const std::unordered_map& roles); + + /// + /// Internal function + /// + _XSAPIIMP multiplayer_role_type(); + + /// + /// Internal function + /// + static xbox::services::xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + static std::vector _Convert_string_vector_to_mutable_role_settings(std::vector roleSettings); + + bool m_ownerManaged; + std::vector m_mutableRoleSettings; + std::unordered_map m_roles; +}; + +/// +/// Represents session role type values for a multiplayer session. +/// +class multiplayer_session_role_types +{ +public: + /// + /// A collection of role types. + /// + _XSAPIIMP const std::unordered_map& role_types() const; + + /// + /// Internal function + /// + multiplayer_session_role_types(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::unordered_map m_roleTypes; +}; + +/// +/// Represents a users current multiplayer activity, along with some details about the corresponding session. +/// +class multiplayer_activity_details +{ +public: + _XSAPIIMP multiplayer_activity_details(); + + /// + /// Object containing identifying information for the session. + /// + _XSAPIIMP const multiplayer_session_reference& session_reference() const; + + /// + /// HandleId corresponding to this activity. + /// + _XSAPIIMP const string_t& handle_id() const; + + /// + /// TitleId that should be launched in order to join this activity. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The visibility state of the session. Whether other users can see, or join, etc. + /// + _XSAPIIMP multiplayer_session_visibility visibility() const; + + /// + /// The join restriction of the session, which applies if visiblity is "open". + /// + _XSAPIIMP multiplayer_session_restriction join_restriction() const; + + /// + /// Indicates whether the session is temporarily closed for joining. + /// + _XSAPIIMP bool closed() const; + + /// + /// Xbox User ID of the member whose activity this is. + /// + _XSAPIIMP const string_t& owner_xbox_user_id() const; + + /// + /// Number of total slots. + /// + _XSAPIIMP uint32_t max_members_count() const; + + /// + /// Number of slots occupied. + /// + _XSAPIIMP uint32_t members_count() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + multiplayer_session_reference m_sessionReference; + string_t m_handleId; + uint32_t m_titleId; + multiplayer_session_visibility m_visibility; + multiplayer_session_restriction m_joinRestriction; + bool m_closed; + string_t m_ownerXboxUserId; + + uint32_t m_maxMembersCount; + uint32_t m_membersCount; +}; + +/// +/// Represents a users current search handle, along with some details about the corresponding session. +/// +class multiplayer_search_handle_details +{ +public: + /// + /// Internal function + /// + _XSAPIIMP multiplayer_search_handle_details(); + + /// + /// Object containing identifying information for the session. + /// + _XSAPIIMP const multiplayer_session_reference& session_reference() const; + + /// + /// HandleId corresponding to this activity. + /// + _XSAPIIMP const string_t& handle_id() const; + + /// + /// Owners of the session. + /// + _XSAPIIMP const std::vector& session_owner_xbox_user_ids() const; + + /// + /// The tags that are currently set on the session. + /// + _XSAPIIMP const std::vector& tags() const; + + /// + /// The numbers metadata that is currently set on the session. + /// + _XSAPIIMP const std::unordered_map& numbers_metadata() const; + + /// + /// The strings metadata that is currently set on the session. + /// + _XSAPIIMP const std::unordered_map& strings_metadata() const; + + /// + /// A collection of role types. + /// + _XSAPIIMP const std::unordered_map& role_types() const; + + /// + /// The visibility state of the session. Whether other users can see, or join, etc. + /// + _XSAPIIMP multiplayer_session_visibility visibility() const; + + /// + /// The join restriction of the session, which applies if visibility is "open". + /// + _XSAPIIMP multiplayer_session_restriction join_restriction() const; + + /// + /// Indicates whether the session is temporarily closed for joining. + /// + _XSAPIIMP bool closed() const; + + /// + /// Number of total slots. + /// + _XSAPIIMP uint32_t max_members_count() const; + + /// + /// Number of slots occupied. + /// + _XSAPIIMP uint32_t members_count() const; + + /// + /// The time when the search handle was created. + /// + _XSAPIIMP utility::datetime handle_creation_time() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + multiplayer_session_reference m_sessionReference; + string_t m_handleId; + std::vector m_tags; + std::vector m_sessionOwners; + bool m_closed; + std::unordered_map m_stringsMetadata; + std::unordered_map m_numbersMetadata; + std::unordered_map m_roleTypes; + multiplayer_session_visibility m_visibility; + multiplayer_session_restriction m_joinRestriction; + uint32_t m_maxMembersCount; + uint32_t m_membersCount; + utility::datetime m_handleCreationTime; +}; + +/// +/// Represents a reference to a multiplayer session. It +/// contains mostly just ids. +/// +class multiplayer_session_states +{ +public: + /// + /// Internal function + /// + _XSAPIIMP multiplayer_session_states(); + + /// + /// The time that the session began. + /// + _XSAPIIMP const utility::datetime& start_time() const; + + /// + /// Object containing identifying information for the session. + /// + _XSAPIIMP const multiplayer_session_reference& session_reference() const; + + /// + /// The current status of the session. + /// + _XSAPIIMP multiplayer_session_status status() const; + + /// + /// The visibility state of the session. Whether other users can see, or join, etc. + /// + _XSAPIIMP multiplayer_session_visibility visibility() const; + + /// + /// Indicates if it is my turn. + /// + _XSAPIIMP bool is_my_turn() const; + + /// + /// Xbox User ID of the member. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Approximate number of non-reserved members. + /// + _XSAPIIMP uint32_t accepted_member_count() const; + + /// + /// Approximate number of non-reserved members. + /// + _XSAPIIMP multiplayer_session_restriction join_restriction() const; + + /// + /// A collection of keywords associated with the session. (Optional, might be empty) + /// + _XSAPIIMP const std::vector& keywords() const; + + /// + /// Internal function + /// + static multiplayer_session_restriction _Convert_string_to_multiplayer_session_restriction(_In_ const string_t& value); + + /// + /// Internal function + /// + static const xbox_live_result _Convert_multiplayer_session_restriction_to_string(_In_ multiplayer_session_restriction joinRestriction); + + /// + /// Internal function + /// + static multiplayer_session_status _Convert_string_to_session_status(_In_ const string_t& value); + + /// + /// Internal function + /// + static multiplayer_session_visibility _Convert_string_to_session_visibility(_In_ const string_t& value); + + /// + /// Internal function + /// + static const xbox_live_result _Convert_multiplayer_session_visibility_to_string(_In_ multiplayer_session_visibility sessionVisibility); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_xboxUserId; + uint32_t m_accepted; + multiplayer_session_restriction m_joinRestriction; + std::vector m_keywords; + multiplayer_session_reference m_multiplayerSessionReference; + multiplayer_session_status m_status; + multiplayer_session_visibility m_visibility; + bool m_myTurn; + utility::datetime m_startTime; +}; + +/// +/// Represents a reference to member in a multiplayer session. +/// +class multiplayer_session_member +{ +public: + multiplayer_session_member(); + multiplayer_session_member( + _In_ bool isCurrentUser, + _In_ uint32_t memberId, + _In_ string_t xboxUserId, + _In_ web::json::value customConstants + ); + + std::shared_ptr _Create_deep_copy(); + + /// + /// Id for this member. + /// + _XSAPIIMP uint32_t member_id() const; + + /// + /// Id of this members' team in a tournament. + /// + _XSAPIIMP const string_t& team_id() const; + + /// + /// Arbitration Status of a member in a tournament + /// + _XSAPIIMP xbox::services::tournaments::tournament_arbitration_status arbitration_status() const; + + void _Set_member_id(_In_ uint32_t memberId); + + /// + /// Xbox User ID of the member. Only known if the member has accepted. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// JSON string that specify the custom constants for the member. + /// + _XSAPIIMP const web::json::value& member_custom_constants_json() const; + + /// + /// The base64 encoded secure device address of the member. (Optional) + /// + _XSAPIIMP const string_t& secure_device_base_address64() const; + + /// + /// A collection of role types to role names for this member. (Optional) + /// + _XSAPIIMP const std::unordered_map& roles() const; + + /// + /// Internal function + /// + void _Set_secure_device_base_address64(_In_ const string_t& deviceBaseAddress); + + /// + /// Internal function + /// + void _Set_role_info(_In_ const std::unordered_map& roleInfo); + + /// + /// JSON string that specify the custom properties for the member. + /// + _XSAPIIMP const web::json::value& member_custom_properties_json() const; + + /// + /// The Gamertag of the member. Only known if the member has accepted. (Optional) + /// + _XSAPIIMP const string_t& gamertag() const; + + /// + /// The status of this member. + /// + _XSAPIIMP multiplayer_session_member_status status() const; + + /// + /// The arbitration results submitted by the member + /// + _XSAPIIMP const std::unordered_map& results() const; + + /// + /// Only true if this member is ready for turn. + /// + _XSAPIIMP bool is_turn_available() const; + + /// + /// Indicates if this MultiplayerSessionMember is for the current user. + /// + _XSAPIIMP bool is_current_user() const; + + /// + /// Indiates to run QoS initialization for this user. Defaults to false. + /// Ignored if there is not a "memberInitialization" section for the session. + /// + _XSAPIIMP bool initialize_requested() const; + + /// + /// When match adds a user to a session, it can provide some context around how and why they were matched into the session. + /// This is a copy of the user's serverMeasurements from the matchmaking session. + /// + _XSAPIIMP const web::json::value& matchmaking_result_server_measurements_json() const; + + /// + /// QoS measurements by game-server connection string. + /// Like all fields, "serverMeasurements" must be updated as a whole, so it should be set once when measurement is complete. + /// If empty, it means that none of the measurements completed within the "serverMeasurementTimeout". + /// + _XSAPIIMP const web::json::value& member_server_measurements_json() const; + + /// + /// A collection of members in my group + /// If a "initializationGroup" list is set, the member's own index will always be added if it isn't already present. + /// During managed initialization, if any members in the list fail, this member will also fail. + /// + _XSAPIIMP const std::vector>& members_in_group() const; + + /// + /// A collection of members in my group + /// If a "initializationGroup" list is set, the member's own index will always be added if it isn't already present. + /// During managed initialization, if any members in the list fail, this member will also fail. + /// + _XSAPIIMP std::error_code set_members_list(_In_ std::vector> members); + + /// + /// QoS measurements by secure device address. Like all fields, "measurements" must be updated as a whole. It should be set once when measurement is complete, not incrementally. + /// If a "measurements" object is set, it can't contain an entry for the member's own address. + /// + _XSAPIIMP std::shared_ptr> member_measurements() const; + + /// + /// This is set when the member uploads a secure device address. It's a case-insensitive string that can be used for equality comparisons. + /// + _XSAPIIMP const string_t& device_token() const; + + /// + /// This is the device's NAT setting when the member uploads a secure device address. + /// + _XSAPIIMP network_address_translation_setting nat() const; + + /// + /// If the member is active, this is the title ID in which they are active. + /// + _XSAPIIMP uint32_t active_title_id() const; + + /// + /// This value is only useful to read when the title is manually managing their own QoS. + /// If the "memberInitialization" section is set and the member was added with "initialize":true, + /// this is set to the initialization episode that the member will participate in otherwise it is 0. + /// Users join sessions in batches. + /// The initialization episode number indicates a set of users that QoS needs to be performed against. + /// Initialization episode 1 is a special value used for the members added to a new session at create time. + /// + _XSAPIIMP uint32_t initialization_episode() const; + + /// + /// The time the user joined the session. If "reserved" is true, this is the time the reservation was made. + /// + _XSAPIIMP const utility::datetime& join_time() const; + + /// + /// The cause of why the initialization failed, or MultiplayerMeasurementFailure::None if there was no failure. + /// Set when transitioning out of the "joining" or "measuring" stage if this member doesn't pass. + /// + _XSAPIIMP multiplayer_measurement_failure initialization_failure_cause() const; + + /// + /// Gets or sets a string vector of group names for the current user indicating which groups that user was part of during a multiplayer session. + /// + _XSAPIIMP const std::vector& groups() const; + + /// + /// Gets or sets a string vector of group names for the current user indicating which groups that user was part of during a multiplayer session. + /// + _XSAPIIMP void set_groups(_In_ std::vector groups); + + /// + /// Gets a list of group names for the current user indicating which groups that user encountered during a multiplayer session. + /// + _XSAPIIMP const std::vector& encounters() const; + + /// + /// Gets a list of group names for the current user indicating which groups that user encountered during a multiplayer session. + /// + _XSAPIIMP void set_encounters(_In_ std::vector encounters); + + /// + /// The tournament team session reference. + /// + _XSAPIIMP const multiplayer_session_reference& tournament_team_session_reference() const; + + /// + /// Internal function + /// + std::shared_ptr _Session_request() const; + + /// + /// Internal function + /// + void _Set_session_request(_In_ std::shared_ptr sessionRequest); + + /// + /// Internal function + /// + std::shared_ptr _Member_request() const; + + /// + /// Internal function + /// + void _Set_member_request(_In_ std::shared_ptr multiplayerSessionMemberRequest); + + /// + /// Internal function + /// + void _Set_is_current_user(_In_ bool isCurrentUser); + + /// + /// Internal function + /// + std::error_code _Set_current_user_status(_In_ multiplayer_session_member_status status); + + /// + /// Internal function + /// + void _Set_current_user_members_in_group(_In_ std::vector> membersInGroup); + + /// + /// Internal function + /// + std::error_code _Set_member_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson + ); + + /// + /// Internal function + /// + void _Delete_custom_property_json(_In_ const string_t& name); + + /// + /// Internal function + /// + void _Set_current_user_quality_of_service_measurements( + _In_ std::shared_ptr> qualityOfServiceMeasurements + ); + + /// + /// Internal function + /// + void _Set_current_user_quality_of_service_server_measurements_json( + _In_ web::json::value serverMeasurementsJson + ); + + /// + /// Internal function + /// + void _Set_rta_connection_id( + _In_ const string_t& rtaConnectionId + ); + + /// + /// Internal function + /// + multiplayer_session_change_types _Subscribed_change_types() const; + + /// + /// Internal function + /// + void _Set_session_change_subscription( + _In_ multiplayer_session_change_types changeTypes, + _In_ const string_t& subscriptionId); + + /// + /// Internal function + /// + void _Set_arbitration_results(_In_ const std::unordered_map& results); + + /// + /// Internal function + /// + static network_address_translation_setting _Convert_string_to_multiplayer_nat_setting(_In_ const string_t& value); + + /// + /// Internal function + /// + static multiplayer_measurement_failure _Convert_string_to_multiplayer_metric_stage(_In_ const string_t& value); + + /// + /// Internal function + /// + static multiplayer_session_change_types _Convert_string_vector_to_change_types(std::vector changeTypeList); + + /// + /// Internal function + /// + static xbox::services::tournaments::tournament_arbitration_status _Convert_string_to_arbitration_status(_In_ const string_t& value); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::error_code convert_measure_json_to_vector(); + + void deep_copy_from( + _In_ const multiplayer_session_member& other + ); + + uint32_t m_memberId; + web::json::value m_customConstantsJson; + web::json::value m_customPropertiesJson; + string_t m_gamertag; + string_t m_xboxUserId; + bool m_isCurrentUser; + bool m_isTurnAvailable; + bool m_isReserved; + bool m_isActive; + bool m_isReady; + string_t m_secureDeviceAddressBase64; + std::unordered_map m_roles; + xbox::services::tournaments::tournament_registration_state m_registrationState; + xbox::services::tournaments::tournament_registration_reason m_registrationReason; + std::unordered_map m_results; + multiplayer_session_reference m_tournamentTeamSessionRef; + string_t m_teamId; + xbox::services::tournaments::tournament_arbitration_status m_arbitrationStatus; + + + std::vector m_groups; + std::vector m_encounters; + + std::shared_ptr m_sessionRequest; + std::shared_ptr m_memberRequest; + + multiplayer_session_change_types m_subscribedChangeTypes; + + // QoS + string_t m_deviceToken; + network_address_translation_setting m_nat; + uint32_t m_activeTitleId; + uint32_t m_initializationEpisode; + utility::datetime m_joinTime; + multiplayer_measurement_failure m_initializationFailure; + bool m_initialize; + web::json::value m_matchmakingResultServerMeasurementsJson; + web::json::value m_memberServerMeasurementsJson; + std::vector m_membersInGroupIndices; + std::vector> m_membersInGroup; + web::json::value m_memberMeasurementsJson; + std::shared_ptr> m_memberMeasurements; + + static std::mutex m_lock; + + friend class multiplayer_session; +}; + +/// +/// Represents multiplayer session properties. +/// +class multiplayer_session_properties +{ +public: + /// + /// Internal function + /// + multiplayer_session_properties(); + + /// + /// Internal function + /// + multiplayer_session_properties& _Deep_copy( + _In_ const multiplayer_session_properties& other + ); + + /// + /// A collection of keywords associated with the session. (Optional, might be empty) + /// When changing, call multiplayer_service::write_session to write the changes to the service. + /// + _XSAPIIMP const std::vector& keywords() const; + + /// + /// A collection of keywords associated with the session. (Optional, might be empty) + /// When changing, call multiplayer_service::write_session to write the changes to the service. + /// + _XSAPIIMP void set_keywords(_In_ std::vector keywords); + + /// + /// Restricts who can join "open" sessions. (Has no effect on reservations, which means it has no impact on "private" and "visible" sessions.) + /// Defaults to "none". + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can join without a reservation. + /// + _XSAPIIMP multiplayer_session_restriction join_restriction() const; + + /// + /// Restricts who can join "open" sessions. (Has no effect on reservations, which means it has no impact on "private" and "visible" sessions.) + /// Defaults to "none". + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can join without a reservation. + /// + _XSAPIIMP std::error_code set_join_restriction(_In_ multiplayer_session_restriction joinRestriction); + + /// + /// Restricts who can read "open" sessions. (Has no effect on reservations, which means it has no impact on "private" and "visible" sessions.) + /// Defaults to "none". + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can read without a reservation. + /// "The read restriction applies to sessions with open or visible visibility and determines who can read the session without an invite. + /// The read restriction must be at least as accessible as the join restriction, i.e. joinRestriction cant be set to followed without also setting readRestriction." + /// + _XSAPIIMP multiplayer_session_restriction read_restriction() const; + + /// + /// Restricts who can read "open" sessions. (Has no effect on reservations, which means it has no impact on "private" and "visible" sessions.) + /// Defaults to "none". + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can read without a reservation. + /// + _XSAPIIMP std::error_code set_read_restriction(_In_ multiplayer_session_restriction readRestriction); + + /// + /// A collection of MultiplayerSessionMember objects indicating whose turn it is. + /// When changing, call multiplayer_service::write_session to write the changes to the service. + /// + _XSAPIIMP const std::vector>& turn_collection() const; + + /// + /// A collection of MultiplayerSessionMember objects indicating whose turn it is. + /// When changing, call multiplayer_service::write_session to write the changes to the service. + /// + _XSAPIIMP std::error_code set_turn_collection(_In_ std::vector> turnCollection); + + /// + /// A JSON string representing the target session constants. + /// + _XSAPIIMP const web::json::value& matchmaking_target_session_constants_json() const; + + /// + /// JSON string that specify the custom properties for the session. These can be changed anytime. + /// When changing, call multiplayer_service::write_session to write the changes to the service. + /// + _XSAPIIMP const web::json::value& session_custom_properties_json() const; + + /// + /// Force a specific connection string to be used. This is useful for session in progress join scenarios. + /// + _XSAPIIMP const string_t& matchmaking_server_connection_string() const; + + /// + /// The ordered list of connection strings that the session could use to connect to a game server. Generally titles should use the first on + /// the list, but sophisticated titles could use a custom mechanism for choosing one of the others (e.g. based on load). + /// + _XSAPIIMP const std::vector& server_connection_string_candidates() const; + + /// + /// Member index of owners of the session. + /// + _XSAPIIMP const std::vector& session_owner_indices() const; + + /// + /// Device token of the host. + /// Must match the "deviceToken" of at least one member, otherwise this field is deleted. + /// If "peerToHostRequirements" is set and "host" is set, the measurement stage assumes the given host is the correct host and only measures metrics to that host. + /// + _XSAPIIMP const string_t& host_device_token() const; + + /// + /// Controls whether a session is joinable, independent of visibility, joinrestriction, and available space in the session. + /// Does not affect reservations. Defaults to false. + /// + _XSAPIIMP bool closed() const; + + /// + /// Internal function + /// + void _Initialize( + _In_ std::shared_ptr request, + _In_ std::vector> members + ); + + /// + /// Internal function + /// + std::error_code _Set_session_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson + ); + + /// + /// Internal function + /// + std::error_code _Delete_session_custom_property_json( + _In_ const string_t& name + ); + + /// + /// Internal function + /// + std::error_code _Set_matchmaking_target_session_constants_json( + _In_ const web::json::value& matchmakingTargetSessionConstantsJson + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + + web::json::value m_customPropertiesJson; + std::vector m_keywords; + std::vector m_sessionOwnerIndices; + std::vector> m_turnCollection; + multiplayer_session_restriction m_joinRestriction; + multiplayer_session_restriction m_readRestriction; + + web::json::value m_matchmakingTargetSessionConstants; + std::vector m_turnIndexList; + + string_t m_servers; + string_t m_membersInfo; + string_t m_correlationId; + string_t m_eTag; + + std::shared_ptr m_sessionRequest; + + // QoS + string_t m_host; + string_t m_serverConnectionString; + std::vector m_serverConnectionStringCandidates; + + bool m_closed; + + static std::mutex m_lock; +}; + +/// +/// Represents a multiplayer session. +/// +class multiplayer_session +{ +public: + /// + /// Internal function + /// + _XSAPIIMP multiplayer_session(); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only create a local session + /// object but does not commit it to the service. + /// Creates a new MultiplayerSession without any constants or session reference. This override is intended + /// to be used when the session (serviceconfigid/template/name) are not known. A MultiplayerSession created + /// using this constructor must we retrieved/written using the "ByHandle" overrides. + /// (e.g. WriteSessionByHandleAsync and GetCurrentSessionByHandleAsync) + /// + /// The Xbox User ID of the user who is creating this session + /// A reference that uniquely identifies the session. + _XSAPIIMP multiplayer_session( + _In_ string_t xboxUserId + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only create a local session object but does not commit it to the service. + /// Creates a new MultiplayerSession without any constants, which allows the request to simply use whatever constants are already specified in the session + /// template on the service. Those constants are returned in the response session data. + /// + /// The Xbox User ID of the user who is creating this session + /// A reference that uniquely identifies the session. + _XSAPIIMP multiplayer_session( + _In_ string_t xboxUserId, + _In_ multiplayer_session_reference sessionReference + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only create a local session object but does not commit it to the service. + /// Creates a new MultiplayerSession using the specified session constants. + /// + /// The Xbox User ID of the user who is creating this session + /// A reference that uniquely identifies the session. + /// The maximum number of members in this session. This value can only be set if the maximum is not specified in the title's multiplayer session template. + /// If the maximum is specified in the title's multiplayer session template, then set to 0 to ignore this parameter + /// The visibility of this session + /// A collection of Xbox User IDs indicating who initiated the session (Optional) + /// JSON that specify the custom constants for the session. These can not be changed after the session is created. (Optional) + _XSAPIIMP multiplayer_session( + _In_ string_t xboxUserId, + _In_ multiplayer_session_reference multiplayerSessionReference, + _In_ uint32_t maxMembersInSession, + _In_ multiplayer_session_visibility multiplayerSessionVisibility, + _In_ std::vector initiatorXboxUserIds = std::vector(), + _In_ web::json::value sessionCustomConstantsJson = web::json::value() + ); + + /// + /// A unique ID to the session used to query trace logs for entries that relate to the session. + /// + _XSAPIIMP const string_t& multiplayer_correlation_id() const; + + /// + /// A unique search handle ID to the session. + /// + _XSAPIIMP const string_t& search_handle_id() const; + + /// + /// The time that the session began. + /// + _XSAPIIMP utility::datetime start_time() const; + + /// + /// If any timeouts are in progress, this is the date when the the next timer will fire. + /// + _XSAPIIMP utility::datetime date_of_next_timer() const; + + /// + /// The date when the server returned the session. + /// + _XSAPIIMP utility::datetime date_of_session() const; + + /// + /// Present during managed initialization. + /// The "stage" goes from "joining" to "measuring" to "evaluating". + /// If episode 1 fails, then "stage" is set to "failed" and the session cannot be initialized. + /// Otherwise, when an initialization episode completes, the "initialization" object is removed. + /// If "externalEvaluation" is not set, "evaluating" is skipped. If "metrics" isn't set, "measuring" is skipped. + /// + _XSAPIIMP multiplayer_initialization_stage initialization_stage() const; + + /// + /// The time with the initialization stage started. + /// + _XSAPIIMP utility::datetime initializing_stage_start_time() const; + + /// + /// If MemberInitialization set and Initialize is true on the member, then the member gets assigned to an InitializingEpisode. + /// An episode is a set of users that need to have QoS metrics applied to them. + /// Will be 0 when the InitializingEpisode is not set. + /// This value is only useful when manually managing QoS. + /// + _XSAPIIMP uint32_t intializing_episode() const; + + /// + /// Returns an OR'd set of MultiplayerSessionChangeTypes values representing the aspects of + /// the session that the current xboxlivecontext is subscribed to, of None if there is none. + /// + _XSAPIIMP multiplayer_session_change_types subscribed_change_types() const; + + /// + /// Host candidates are a ordered list of device tokens, ordered by preference as specified by MultiplayerSessionConstants::PeerToHostRequirements::HostSelectionMetric. + /// + _XSAPIIMP std::vector host_candidates() const; + + /// + /// The uniquely identifying information for the session. + /// + _XSAPIIMP const multiplayer_session_reference& session_reference() const; + + /// + /// A set of constants associated with this session. These can only be set when creating the session. + /// + _XSAPIIMP std::shared_ptr session_constants() const; + + /// + /// A set of properties associated with this session. Any player can modify these properties. + /// + _XSAPIIMP std::shared_ptr session_properties() const; + + /// + /// A set of role types associated with this session. + /// + _XSAPIIMP std::shared_ptr session_role_types() const; + + /// + /// A collection of members that are in the session or entering the session together. + /// Call MultiplayerSession::Join or MultiplayerSession::Leave to add or remove youself from this list. + /// Call MultiplayerSession::AddMemberReservation to add a reservation for another user on this list. + /// Call multiplayer_service::write_session to write these changes to the service. + /// + _XSAPIIMP const std::vector>& members() const; + + /// + /// A multiplayer session servers that contains properties associated with a target session reference. + /// + _XSAPIIMP const multiplayer_session_matchmaking_server& matchmaking_server() const; + + /// + /// A tournament session servers that contains properties associated with a tournament reference. + /// + _XSAPIIMP const multiplayer_session_tournaments_server& tournaments_server() const; + + /// + /// An arbitration server that contains properties associated with a tournament games results. + /// + _XSAPIIMP const multiplayer_session_arbitration_server& arbitration_server() const; + + /// + /// The number of members that have accepted and are added to the session and are no longer pending. + /// + _XSAPIIMP uint32_t members_accepted() const; + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// A JSON string containing a collection of servers for this multiplayer session. + /// + _XSAPIIMP const web::json::value& servers_json() const; + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// A JSON string containing a collection of servers for this multiplayer session. + /// + _XSAPIIMP void set_servers_json(_In_ const web::json::value& serversJson); + + /// + /// The ETag returned with this session. + /// + _XSAPIIMP const string_t& e_tag() const; + + /// + /// Returns the current User in the session. A nullptr will be returned if there is no current user in the session. + /// + _XSAPIIMP std::shared_ptr current_user() const; + + /// + /// The branch of the session used to scope change numbers. + /// + _XSAPIIMP const string_t& branch() const; + + /// + /// The change number of the session. + /// + _XSAPIIMP uint64_t change_number() const; + + /// + /// On writing a session, the status of the write + /// + _XSAPIIMP write_session_status write_status() const; + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Add a new member reservation on the session for the specified xboxUserId and member constants. + /// + /// The Xbox User ID to add a reservation for. + /// The custom constants to set for this member. This is the only time the member's constants can be set. (Optional) + _XSAPIIMP std::error_code add_member_reservation( + _In_ const string_t& xboxUserId, + _In_ const web::json::value& memberCustomConstantsJson = web::json::value() + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Add a new member reservation on the session for the specified xboxUserId and member constants. + /// + /// The Xbox User ID to add a reservation for. + /// The custom constants to set for this member. This is the only time the member's constants can be set. (Optional) + /// True if the system should perform managed initialization, and false otherwise. + _XSAPIIMP std::error_code add_member_reservation( + _In_ const string_t& xboxUserId, + _In_ const web::json::value& memberCustomConstantsJson, + _In_ bool initializeRequested + ); + + /// + /// Joins this user to the session, sets the user to active. + /// + /// The custom constants to set for this member. + /// This is the only time the member's constants can be set. + /// True if the system should perform managed + /// initialization, and false otherwise. + /// True if player should join with active status. + /// True to write the 'initialize' property to the request. False otherwise and that means initializeRequested will be ignored. + _XSAPIIMP xbox_live_result> join( + _In_ const web::json::value& memberCustomConstantsJson = web::json::value::null(), + _In_ bool initializeRequested = true, + _In_ bool joinWithActiveStatus = true, + _In_ bool addInitializePropertyToRequest = true + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// Sets the visibility of the session. + /// + /// Set the visibility setting of the session. + _XSAPIIMP void set_visibility(_In_ multiplayer_session_visibility visibility); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// Sets the max member count of the session. + /// + /// Set the max member count of the session. + _XSAPIIMP void set_max_members_in_session(_In_ uint32_t maxMembersInSession); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Sets the max member count per role. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + /// A map of role type names to multiplayer role type + _XSAPIIMP std::error_code set_mutable_role_settings( + _In_ const std::unordered_map& roleTypes + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// Sets the timeouts for the session. + /// + /// The timeout for a member reservation, in milliseconds. A value of 0 is allowed and indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// The timeout for a member to be considered inactive, in milliseconds. A value of 0 is allowed and indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// The timeout for a member to be considered ready, in milliseconds. A value of 0 is allowed and indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// The timeout for an empty session, in milliseconds. A value of 0 is allowed and indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + _XSAPIIMP std::error_code set_timeouts( + _In_ std::chrono::milliseconds memberReservedTimeout, + _In_ std::chrono::milliseconds memberInactiveTimeout, + _In_ std::chrono::milliseconds memberReadyTimeout, + _In_ std::chrono::milliseconds sessionEmptyTimeout + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// Sets the arbitration timeouts for the session. + /// + /// The timeout for arbitration, in milliseconds representing the point at which results are finalized. + /// The timeout for forfeit, in milliseconds representing the point at which, if the session has no active users, the match is canceled. + _XSAPIIMP std::error_code set_arbitration_timeouts( + _In_ std::chrono::milliseconds arbitrationTimeout, + _In_ std::chrono::milliseconds forfeitTimeout + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// Enables or disables connectivity metrics for the session. + /// For ones that are enabled, they must be sufficient to satisfy the QoS requirements. + /// + /// True to enable the measuring of latency, and false to disable latency measurement. + /// True to enable the measuring of bandwidth down, and false to disable bandwidth down measurement. + /// True to enable the measuring of bandwidth up, and false to disable bandwidth up measurement. + /// True to enable custom metrics, and false to disable them. + _XSAPIIMP std::error_code set_quality_of_service_connectivity_metrics( + _In_ bool enableLatencyMetric, + _In_ bool enableBandwidthDownMetric, + _In_ bool enableBandwidthUpMetric, + _In_ bool enableCustomMetric + ); + + /// + /// DEPRECATED. Instead call set_member_initialization() + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// If a 'managedInitialization' object is set, the session expects the client system or title to perform + /// initialization following session creation and/or as new members join the session. + /// The timeouts and initialization stages are automatically tracked by the session, including QoS + /// measurements if any metrics are set. These timeouts override the session's reservation and ready + /// timeouts for members that have 'initializationEpisode' set. + /// + /// The period of time, in milliseconds, that the Xbox system waits for a member to join the session. + /// The period of time, in milliseconds, that the Xbox system waits for a measuring operation during managed initialization. + /// The period of time, in milliseconds, that the Xbox system waits for an evaluation. + /// True if the Xbox system should auto-evaluate the session service, and false if the title performs the evaluation. + /// The number of members needed to start the session, for initialization episode zero only. + _XSAPIIMP_DEPRECATED std::error_code set_managed_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32_t membersNeededToStart + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// If a 'memberInitialization' object is set, the session expects the client system or title to perform + /// initialization following session creation and/or as new members join the session. + /// The timeouts and initialization stages are automatically tracked by the session, including QoS + /// measurements if any metrics are set. These timeouts override the session's reservation and ready + /// timeouts for members that have 'initializationEpisode' set. + /// + /// The period of time, in milliseconds, that the Xbox system waits for a member to join the session. + /// The period of time, in milliseconds, that the Xbox system waits for a measuring operation during managed initialization. + /// The period of time, in milliseconds, that the Xbox system waits for an evaluation. + /// False if the Xbox system should auto-evaluate the session service, and true if the title performs the evaluation. + /// The number of members needed to start the session, for initialization episode zero only. + _XSAPIIMP std::error_code set_member_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool externalEvaluation, + _In_ uint32_t membersNeededToStart + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// These thresholds apply to each pairwise connection for all members in a session. + /// + /// The maximum latency, in milliseconds, between session members. + /// The minimum bandwidth, in kilobits per second, between members. + _XSAPIIMP std::error_code set_peer_to_peer_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthMinimumInKilobitsPerSecond + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// These thresholds apply to each connection from a host candidate. + /// + /// The maximum latency time, in milliseconds. + /// The minimum bandwidth, in kilobits per second, for information sent from the host to the session member. + /// The minimum bandwidth, in kilobits per second, for information sent from the session member to the host. + /// An enumeration value indicating the metric for the Xbox system to use in selecting a host. + _XSAPIIMP std::error_code set_peer_to_host_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32_t bandwidthUpMinimumInKilobitsPerSecond, + _In_ multiplay_metrics hostSelectionMetric + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// The set of potential server connection strings that should be evaluated. + /// + /// A collection of QualityOfServiceServer objects returned from GameServerPlatformService::GetQualityOfServiceServersAsync() + _XSAPIIMP std::error_code set_measurement_server_addresses( + _In_ const std::vector& measurementServerAddresses + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// + /// A collection of MultiplayerSessionCapabilities flags that apply to the MultiplayerSessionConstant's capabilities JSON object + _XSAPIIMP std::error_code set_session_capabilities( + _In_ const multiplayer_session_capabilities& capabilities + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// This can only be set when creating a new session. + /// The set of potential server connection strings that should be evaluated. + /// + /// True if initialization succeeded, and false otherwise. + _XSAPIIMP void set_initialization_status( + _In_ bool initializationSucceeded + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Sets the device token of the host. + /// If "peerToHostRequirements" is set and this is set, the measurement stage assumes the given host is the correct host and only measures metrics to that host. + /// + /// The host device token. + _XSAPIIMP void set_host_device_token( + _In_ const string_t& hostDeviceToken + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Forces a specific server connection string to be used, useful in preserveSession=always cases. + /// + /// The server connection path. Setting this path can be useful when the session is preserved. + _XSAPIIMP void set_matchmaking_server_connection_path( + _In_ const string_t& serverConnectionPath + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// If set to true, makes the session "closed", meaning that new users will not be able to join unless they already have a reservation. + /// + _XSAPIIMP void set_closed( + _In_ bool closed + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set matchResubmit to true if the match that was found didn't work out and needs to be resubmitted. + /// Set matchResubmit to false to signal that the match did work, and the matchmaking service can release the session. + /// + /// True if the match that was found was not successful and needs to be resubmitted. + _XSAPIIMP void set_matchmaking_resubmit( + _In_ bool matchResubmit + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// The ordered list of case-insensitive connection strings that the session could use to connect to + /// a game server. Generally titles should use the first on the list, but sophisticated titles could use + /// a custom mechanism for choosing one of the others (e.g. based on load). + /// + /// The collection of connection paths. + _XSAPIIMP void set_server_connection_string_candidates( + _In_ const std::vector& serverConnectionStringCandidates + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local + /// session object but does not commit it to the service. Configures the set of session changes that + /// this client will be subscribed to. Set to "MultiplayerSessionChangeTypes::None" to clear the subscription. + /// + /// Or'd set of MultiplayerSessionChangeType enum values representing the change types to subscribe to. + _XSAPIIMP std::error_code set_session_change_subscription( + _In_ multiplayer_session_change_types changeTypes + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// With the user who either created or got the session, leave the session. If the session is deleted as a result of this action, a 204 response with a nullptr for the MultiplayerSession object will be returned. + /// + _XSAPIIMP std::error_code leave(); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set the current user to active or inactive. + /// You cannot set the the user to reserved or ready in this manner. + /// Use AddMemberReservation() to add a member reservation. + /// The member must first be joined to the session. + /// + /// Indicates the current user status. + _XSAPIIMP std::error_code set_current_user_status( + _In_ multiplayer_session_member_status status + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set the base64 encoded secure device address of the member + /// The member must first be joined to the session. + /// + /// Indicates the value of the current user's secure device address encoded in base64. + _XSAPIIMP std::error_code set_current_user_secure_device_address_base64( + _In_ const string_t& value + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set the role info of the member. + /// The member must first be joined to the session. + /// + /// Indicates a collection of role types to role names for the current user. + _XSAPIIMP std::error_code set_current_user_role_info( + _In_ const std::unordered_map& roles + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set a collection of members in the group + /// The member must first be joined to the session. + /// + /// Indicates the value of the current user's secure device address encoded in base64. + _XSAPIIMP std::error_code set_current_user_members_in_group( + _In_ const std::vector>& membersInGroup + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Sets a collection of MultiplayerQualityOfServiceMeasurements for the members. + /// This is only useful when the title is manually managing QoS. + /// If the platform is automatically performing QoS, this does not need to be called. + /// + /// A collection of objects representing the QoS measurements. + _XSAPIIMP std::error_code set_current_user_quality_of_service_measurements( + _In_ std::shared_ptr> measurements + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Sets measurements JSON for the servers. + /// This is only useful when the title is manually managing QoS. + /// If the platform is automatically performing QoS, this does not need to be called. + /// + /// The JSON that represents the server measurements. + _XSAPIIMP std::error_code set_current_user_quality_of_service_measurements_json( + _In_ const web::json::value& serverMeasurementsJson + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set a custom property on the current user to the specified JSON string + /// The member must first be joined to the session. + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + _XSAPIIMP std::error_code set_current_user_member_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson = web::json::value() + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set the arbitration result for all teams in a tournament game session. + /// + /// The results of the tournament game session. A map of team names to tournament results + _XSAPIIMP std::error_code set_current_user_member_arbitration_results( + _In_ const std::unordered_map& results + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Delete a custom property on the current user + /// + /// The name of the property to set + _XSAPIIMP std::error_code delete_current_user_member_custom_property_json( + _In_ const string_t& name + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Sets the properties of the matchmaking. This should only be set by a client acting as a matchmaking service. + /// + /// A JSON string representing the target session constants. + _XSAPIIMP std::error_code set_matchmaking_target_session_constants_json( + _In_ web::json::value matchmakingTargetSessionConstantsJson + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set a session custom property to the specified JSON string. + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + _XSAPIIMP std::error_code set_session_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson = web::json::value() + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Deletes a session custom property. + /// + /// The name of the property to set. + _XSAPIIMP std::error_code delete_session_custom_property_json( + _In_ const string_t& name + ); + + /// + /// Static compare method that allows comparison between 2 sessions and returns a Or'ed MultiplayerSessionChangeType. + /// + /// A session to compare to the other. + /// A session to compare to the other. + /// An OR'ed MultiplayerSessionChangeType that contains all of the differences. + _XSAPIIMP static xbox_live_result compare_multiplayer_sessions( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession + ); + + /// + /// Static method that converts an HTTP Status code to a write_session_status + /// + /// Status code of a http result + /// A write_session_status which gives more specific information about the status code in regards to the Write Session Call + _XSAPIIMP static write_session_status convert_http_status_to_write_session_status( + _In_ int32_t httpStatusCode + ); + + /// + /// Internal function + /// + void _Initialize( + _In_ string_t xboxUserId + ); + + /// + /// Internal function + /// + void _Initialize_after_deserialize( + _In_ string_t eTag, + _In_ string_t responseDate, + _In_ multiplayer_session_reference sessionReference, + _In_ string_t xboxUserId + ); + + /// + /// Internal function + /// + std::shared_ptr _Create_deep_copy(); + + /// + /// Internal function + /// + void _Set_write_session_status( + int32_t httpStatusCode + ); + + /// + /// Internal function + /// + std::shared_ptr _Session_request() const; + + /// + /// Internal function + /// + static const xbox_live_result _Convert_multiplayer_host_selection_metric_to_string(_In_ multiplay_metrics multiplayMetric); + + /// + /// Internal function + /// + static multiplay_metrics _Convert_string_to_multiplayer_host_selection_metric(_In_ const string_t& value); + + /// + /// Internal function + /// + static multiplayer_initialization_stage _Convert_string_to_multiplayer_initialization_stage(_In_ const string_t& value); + + /// + /// Internal function + /// + static xbox_live_result _Convert_string_to_matchmaking_status(_In_ const string_t& value); + + /// + /// Internal function + /// + static const xbox_live_result _Convert_matchmaking_status_to_string(_In_ matchmaking_status matchmakingStatus); + + /// + /// Internal function + /// + static std::vector> _Deserialize_me_member(_In_ const web::json::value& json, _In_ std::error_code& errc); + + /// + /// Internal function + /// + static std::vector> _Deserialize_members_list(_In_ const web::json::value& json, _In_ std::error_code& errc); + + /// + /// Internal function + /// + static std::error_code _Populate_members_with_members_list(_In_ std::vector> members); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + /// + /// Internal function + /// + multiplayer_session( + _In_ string_t xboxUserId, + _In_ multiplayer_session_reference multiplayerSessionReference, + _In_ std::vector initiatorXboxUserIds + ); + +private: + + void deep_copy_from( + _In_ const multiplayer_session& other + ); + + xbox_live_result> join_helper( + _In_ web::json::value memberCustomConstantsJson, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus + ); + + std::error_code add_member_reservation_helper( + _In_ const string_t& xboxUserId, + _In_ const web::json::value& memberCustomConstantsJson, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializeRequested + ); + + void ensure_session_subscription_id_initialized(); + + string_t m_xboxUserId; + multiplayer_session_reference m_sessionReference; + std::shared_ptr m_sessionConstants; + std::shared_ptr m_multiplayerSessionProperties; + std::shared_ptr m_sessionRoleTypes; + std::vector> m_members; + web::json::value m_servers; + uint32_t m_membersAccepted; + string_t m_correlationId; + string_t m_searchHandleId; + string_t m_eTag; + std::shared_ptr m_sessionRequest; + std::shared_ptr m_memberCurrentUser; + bool m_joiningSession; + bool m_newSession; + utility::datetime m_startTime; + utility::datetime m_dateOfSession; + multiplayer_session_matchmaking_server m_matchmakingServer; + multiplayer_session_tournaments_server m_tournamentsServer; + multiplayer_session_arbitration_server m_arbitrationServer; + bool m_hasMatchmakingServer; + string_t m_sessionSubscriptionGuid; + string_t m_branch; + uint64_t m_changeNumber; + write_session_status m_writeSessionStatus; + + // QoS + utility::datetime m_nextTimer; + multiplayer_initialization_stage m_initializationStage; + utility::datetime m_initializationStageStartTime; + uint32_t m_initializationEpisode; + std::vector m_hostCandidate; +}; + +/// +/// Arguments passed to the event handler when a session change occurs. +/// +class multiplayer_session_change_event_args +{ +public: + /// + /// Internal function + /// + multiplayer_session_change_event_args() {}; + + /// + /// Internal function + /// + multiplayer_session_change_event_args( + _In_ multiplayer_session_reference sessionRef, + _In_ string_t branch, + _In_ uint64_t changeNumber + ); + + /// + /// The session that triggered this event. + /// + _XSAPIIMP const multiplayer_session_reference& session_reference() const; + + /// + /// The branch of the session used to scope change numbers. + /// + _XSAPIIMP const string_t& branch() const; + + /// + /// The change number of the session. + /// + _XSAPIIMP uint64_t change_number() const; + +private: + multiplayer_session_reference m_sessionReference; + string_t m_branch; + uint64_t m_changeNumber; +}; + +/// +/// Gets the visible multiplayer sessions based on the configuration of this request. +/// +class multiplayer_get_sessions_request +{ +public: + + /// Creates a GetSessionsRequest object. + /// The service configuration id that the sessions part of. + /// The maximum number of items to return. + _XSAPIIMP multiplayer_get_sessions_request( + _In_ string_t serviceConfigurationId, + _In_ uint32_t maxItems = 0 + ); + + /// + /// The service configuration id that the sessions part of. + /// + _XSAPIIMP const string_t& service_configuration_id(); + + /// + /// The maximum number of items to return. + /// + _XSAPIIMP uint32_t max_items(); + + /// + /// Include private sessions to the result. + /// + _XSAPIIMP bool include_private_sessions(); + + /// + /// Sets the query to include private sessions in the result. + /// + /// Whether to include private sessions. + _XSAPIIMP void set_include_private_sessions(_In_ bool includePrivateSessions); + + /// + /// Include sessions that the user hasn't accepted. Must specify xboxUserIdFilter to use. + /// + _XSAPIIMP bool include_reservations(); + + /// + /// Sets the query to include session reservations for members in the result. + /// + /// Whether to include reservations. + _XSAPIIMP void set_include_reservations(_In_ bool includeResevations); + + /// + /// Include inactive sessions to the result. Must specify xboxUserIdFilter to use. + /// + _XSAPIIMP bool include_inactive_sessions(); + + /// + /// Sets the query to include inactive sessions in the result. + /// + /// Whether to include inactive sessions. + _XSAPIIMP void set_include_inactive_sessions(_In_ bool includeInactiveSessions); + + /// + /// Filter result to just sessions this Xbox User ID in it. + /// + _XSAPIIMP const string_t& xbox_user_id_filter(); + + /// + /// Sets the xbox user id filter. (The xboxUserIdFilter, xboxUserIdsFilter, or keywordFilter must be specified) + /// + /// The xbox user id to filter by. + _XSAPIIMP void set_xbox_user_id_filter(_In_ const string_t& filter); + + /// + /// Filter result to just sessions these Xbox User IDs in it. + /// + _XSAPIIMP const std::vector& xbox_user_ids_filter(); + + /// + /// Sets the xbox user ids filter. (The xboxUserIdFilter, xboxUserIdsFilter, or keywordFilter must be specified) + /// + /// The xbox user ids to filter by. + _XSAPIIMP void set_xbox_user_ids_filter(_In_ std::vector filter); + + /// + /// Filter result to just sessions with this keyword. + /// + _XSAPIIMP const string_t& keyword_filter(); + + /// + /// Sets the xbox user ids filter. (The xboxUserIdFilter, xboxUserIdsFilter, or keywordFilter must be specified) + /// + /// The keyword to filter by. + _XSAPIIMP void set_keyword_filter(_In_ const string_t& filter); + + /// + /// The name of the template for the multiplayer session to filter on. + /// + _XSAPIIMP const string_t& session_template_name_filter(); + + /// + /// Sets the session template to filter by. + /// + /// The session template name to filter by. + _XSAPIIMP void set_session_template_name_filter(_In_ const string_t& filter); + + /// + /// Filter result to just sessions with the specified visibility. + /// + _XSAPIIMP multiplayer_session_visibility visibility_filter(); + + /// + /// Sets the session template to filter by. + /// + /// The session template name to filter by. + _XSAPIIMP void set_visibility_filter(_In_ multiplayer_session_visibility filter); + + /// + /// Filter result to just sessions with this major version or less of the contract. (use 0 to ignore) + /// + _XSAPIIMP uint32_t contract_version_filter(); + + /// + /// Sets the contract version to filter by. + /// + /// The contract version to filter by. + _XSAPIIMP void set_contract_version_filter(_In_ uint32_t filter); + +private: + string_t m_serviceConfigurationId; + bool m_includePrivateSessions; + uint32_t m_maxItems; + bool m_includeReservations; + bool m_includeInactiveSessions; + string_t m_xboxUserIdFilter; + std::vector m_xboxUserIdsFilter; + string_t m_keywordFilter; + string_t m_sessionTemplateNameFilter; + multiplayer_session_visibility m_visibilityFilter; + uint32_t m_contractVersionFilter; +}; + +/// +/// Queries for the all search handles that references the searchable sessions given the specific query. +/// There is no paging or continuation, and the multiplayer service will limit the number of items returned to 100. +/// +class multiplayer_query_search_handle_request +{ +public: + /// Creates a multiplayer_query_search_handle_request object. + /// The scid within which to query for search handles. + /// The name of the template to query for search handles. + /// + _XSAPIIMP multiplayer_query_search_handle_request( + _In_ string_t serviceConfigurationId, + _In_ string_t sessionTemplateName + ); + + /// + /// The service configuration id that the sessions part of. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The name of the template that the sessions part of. + /// + _XSAPIIMP const string_t& session_template_name() const; + + /// + /// The attribute to sort the search handles by. + /// + _XSAPIIMP const string_t& order_by() const; + + /// + /// Specify the attribute to sort the search handles by. + /// Valid values are "Timestamp desc", "Timestamp asc" or any Numbers search attribute followed by 'asc or 'desc' (ex: 'Numbers/gamerank asc') + /// + /// Pass empty string to default to ordering by 'Timestamp asc'. + _XSAPIIMP void set_order_by(_In_ const string_t& orderBy); + + /// + /// The order to sort the search handles by. + /// + _XSAPIIMP bool order_ascending(); + + /// + /// Specify the order to sort the search handles by. + /// + /// Pass true to order ascending, false to order descending + _XSAPIIMP void set_order_ascending(_In_ bool orderAscending); + + /// + /// The filter to search for. + /// + _XSAPIIMP const string_t& search_filter() const; + + /// + /// Specify the filter to search for. + /// The filter syntax is an OData like syntax with only the following operators supported EQ, NE, GE, GT, LE and LT along with the logical operators of AND and OR. + /// + /// Example 1: + /// To search for search handles for a specific XboxUserId use + /// "MemberXuids/any(d:d eq 12345678)" or "OwnerXuids/any(d:d eq 12345678)" + /// + /// Example 2: + /// To search for search handles for a title defined string metadata use + /// "Strings/stringMetadataType eq value" + /// + /// Example 3: + /// To search for search handles for a title defined numbers metadata AND a tag type value use + /// Numbers/numberMetadataType eq 53 AND Tags/tagType eq value + /// + /// The filter string to search for. + _XSAPIIMP void set_search_filter(_In_ const string_t& searchFilter); + + /// + /// The social group to get the search handles for. + /// + _XSAPIIMP const string_t& social_group() const; + + /// + /// Specify the social group to get the search handles for. + /// + /// The social group to use in order to get the list of users. (e.g. "people" or "favorites") + _XSAPIIMP void set_social_group(_In_ const string_t& socialGroup); + + /// + /// Internal function + /// + multiplayer_query_search_handle_request( + _In_ string_t serviceConfigurationId, + _In_ string_t sessionTemplateName, + _In_ string_t orderBy, + _In_ bool orderAscending, + _In_ string_t searchFilter + ); + + /// + /// Internal function + /// + web::json::value _Serialize(_In_ const string_t& socialGroupXuid) const; + +private: + string_t m_serviceConfigurationId; + string_t m_sessionTemplateName; + string_t m_orderBy; + bool m_orderAscending; + string_t m_searchFilter; + string_t m_socialGroup; +}; + +/// +/// Sets the search handle based on the configuration of this request. +/// +class multiplayer_search_handle_request +{ +public: + /// Creates a multiplayer_search_handle_request object. + /// The session referenceid that the sessions part of. + _XSAPIIMP multiplayer_search_handle_request( + _In_ multiplayer_session_reference sessionRef + ); + + /// + /// The session reference that the sessions part of. + /// + _XSAPIIMP const multiplayer_session_reference& session_reference() const; + + /// + /// Filter result to just sessions with the tags set. + /// + _XSAPIIMP const std::vector& tags() const; + + /// + /// Sets the tags to filter by. + /// + /// The tags to filter by. + _XSAPIIMP void set_tags(_In_ const std::vector& value); + + /// + /// Filter result to just sessions with the numbers metadata. + /// + _XSAPIIMP const std::unordered_map& numbers_metadata() const; + + /// + /// Sets the numbers metadata to filter by. + /// + /// The tags to filter by. + _XSAPIIMP void set_numbers_metadata(_In_ const std::unordered_map& metadata); + + /// + /// Filter result to just sessions with the strings metadata. + /// + _XSAPIIMP const std::unordered_map& strings_metadata() const; + + /// + /// Sets the strings metadata to filter by. + /// + /// The tags to filter by. + _XSAPIIMP void set_strings_metadata(_In_ const std::unordered_map& metadata); + + /// + /// Internal function + /// + void _Set_version(_In_ uint32_t version); + + /// + /// Internal function + /// + web::json::value _Serialize() const; + +private: + uint32_t m_version; + multiplayer_session_reference m_sessionReference; + std::vector m_tags; + std::unordered_map m_stringsMetadata; + std::unordered_map m_numbersMetadata; +}; + +/// +/// Used to handle interactions with an Xbox Live service endpoint on a server. +/// +class multiplayer_service +{ +public: + /// + /// Writes a new or updated multiplayer session to the service. + /// The passed multiplayerSession must have a valid multiplayer_session_reference set on it. + /// + /// A MultiplayerSession object that has been modified with the changes to write. + /// The type of write operation + /// The async object for notifying when the operation is completed. With the handler, a MultiplayerSession + /// object is returned that contains the response returned from the server. Note that if you leave a session that you are the + /// the last member of and the sessionEmptyTimeout is equal to 0, then the session will be deleted immediately and a nullptr will be returned. + /// Calls V105 PUT /serviceconfigs/{serviceConfigurationId}/sessionTemplates/{sessiontemplateName}/sessions/{sessionName} + _XSAPIIMP pplx::task>> write_session( + _In_ std::shared_ptr multiplayerSession, + _In_ multiplayer_session_write_mode writeMode + ); + + /// + /// Writes a new or updated multiplayer session to the service, using the specified handle to the session. + /// A handle is a service-side pointer to a session. The handleid is a GUID identifier of the handle. Callers will + /// usually get the handleid either from another player's MultiplayerActivityDetails, or from a protocol + /// activation after a user has accepted an invite. + /// + /// Use this method only if your MultiplayerSession object doesn't have a multiplayer_session_reference, as + /// a handle's lifetime may be shorter than that of the session it points to. + /// + /// + /// A MultiplayerSession object that has been modified with the changes to write + /// The type of write operation + /// The ID of the handle that should be used when writing the session. + /// The async object for notifying when the operation is completed. With the handler, a MultiplayerSession + /// object is returned that contains the response returned from the server. The returned MultiplayerSession will + /// contain a multiplayer_session_reference, so may be used when calling write_session. Note that if you leave a session that you are the + /// the last member of and the sessionEmptyTimeout is equal to 0, then the session will be deleted immediately and a nullptr will be returned. + /// Calls V105 PUT /handles/{handleid}/session + _XSAPIIMP pplx::task>> write_session_by_handle( + _In_ std::shared_ptr multiplayerSession, + _In_ multiplayer_session_write_mode multiplayerSessionWriteMode, + _In_ const string_t& handleId + ); + + /// + /// Gets a session object with all its attributes from the server. + /// + /// A multiplayer_session_reference object containing identifying information for the session. + /// The async object for notifying when the operation is completed. With the handler, a MultiplayerSession + /// object is returned that contains the response returned from the server. + /// Calls V102 GET /serviceconfigs/{serviceConfigurationId}/sessionTemplates/{sessiontemplateName}/sessions/{sessionName} + _XSAPIIMP pplx::task>> get_current_session( + _In_ multiplayer_session_reference sessionReference + ); + + /// + /// Gets a session object with all its attributes from the server, given a session handle id. + /// A handle is a service-side pointer to a session. The handleid is a GUID identifier of the handle. Callers will + /// usually get the handleid either from another player's MultiplayerActivityDetails, or from a protocol + /// activation after a user has accepted an invite. + /// + /// A multiplayer handle id, which uniquely identifies the session. + /// The async object for notifying when the operation is completed. With the handler, a MultiplayerSession + /// object is returned that contains the response returned from the server. + /// Calls GET /handles/{handleId}/session + _XSAPIIMP pplx::task>> get_current_session_by_handle( + _In_ const string_t& handleId + ); + + /// + /// Retrieve a list of sessions with various filters + /// + /// A session request object that sends a query for the session + /// The async object for notifying when the operation is completed. With the handler, a collection of + /// SessionStates objects are returned where each contains metadata about one session. + /// Calls V102 GET /serviceconfigs/{scid}/sessions or /serviceconfigs/{scid}/sessiontemplates/{session-template-name}/sessions + _XSAPIIMP pplx::task>> get_sessions( + _In_ multiplayer_get_sessions_request getSessionsRequest + ); + + /// + /// Sets the passed session as the user's current activity, which will be displayed in Xbox + /// dashboard user experiences (e.g. friends and gamercard) as associated with the currently + /// running title. If the session is joinable, it may also be displayed as such in those + /// user experiences. + /// + /// A multiplayer_session_reference for the session of the activity + /// The async object for notifying when the operation is completed. + _XSAPIIMP pplx::task> set_activity(_In_ multiplayer_session_reference sessionReference); + + /// + /// The access rights the caller has to the origin session are extended to the target session. + /// For example, in a title with a lobby session and a game session, the title could put a transfer handle + /// linking the lobby to the game inside the lobby session. Users invited to the lobby can use the handle to join the game session as well. + /// The transfer handle is deleted once the target session is deleted. + /// + /// Target multiplayer_session_reference for the session you want to extend the access rights for + /// Origin multiplayer_session_reference for the session that grants access to the target session + /// The async object for notifying when the operation is completed. This contains the transfer handle ID string. + _XSAPIIMP pplx::task> set_transfer_handle( + _In_ multiplayer_session_reference targetSessionReference, + _In_ multiplayer_session_reference originSessionReference + ); + + /// + /// Creates a search handle associated with the session. The visibility of the session is dependent on its search handle. + /// While you can create an searchable session, it is not queryable and visible to others unless you have the associated search handle committed as well. + /// + /// A search handle request object for the associated session + /// The async object for notifying when the operation is completed. + _XSAPIIMP pplx::task> set_search_handle( + _In_ multiplayer_search_handle_request searchHandleRequest + ); + + /// + /// Clears the user's current activity session for the specified serviceConfigurationId + /// + /// A string containing the serviceConfigurationId in which to clear activity. + /// The async object for notifying when the operation is completed. + _XSAPIIMP pplx::task> clear_activity(_In_ const string_t& serviceConfigurationId); + + /// + /// Clears the search handle that is associated with the session. + /// + /// The handleId associated with the session to clear. + /// The async object for notifying when the operation is completed. + _XSAPIIMP pplx::task> clear_search_handle(_In_ const string_t& handleId); + + /// + /// Invites the specified users to a session. This will result in a notification being shown to + /// each invited user using standard invite text. If a user accepts that notification the title will be activated. + /// + /// A multiplayer_session_reference object representing the session the target users will be invited to. + /// The list of xbox user IDs who will be invited. + /// The ID of the title that the invited user will activate in order to join the session. + /// The async object for notifying when the operation is completed. This contains a vectorview of handle ID strings corresponding to the invites that have been sent. + _XSAPIIMP pplx::task>> send_invites( + _In_ multiplayer_session_reference sessionReference, + _In_ const std::vector& xboxUserIds, + _In_ uint32_t titleId + ); + + /// + /// Invites the specified users to a session. This will result in a notification being shown to + /// each invited user. If a user accepts that notification the title will be activated. + /// + /// A multiplayer_session_reference object representing the session the target users will be invited to. + /// The list of xbox user IDs who will be invited. + /// The ID of the title that the invited user will activate in order to join the session. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with ///. Pass an empty string if + /// you dont want a custom string added to the invite. + /// The activation context string. + /// The async object for notifying when the operation is completed. This contains a vectorview of handle ID strings corresponding to the invites that have been sent. + _XSAPIIMP pplx::task>> send_invites( + _In_ multiplayer_session_reference sessionReference, + _In_ const std::vector& xboxUserIds, + _In_ uint32_t titleId, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ); + + /// + /// Queries for the current activity for a socialgroup of users associated with a particular + /// "owner" user. There is no paging or continuation, and the multiplayer service will + /// limit the number of items returned to 100. + /// + /// The scid within which to query for activities. + /// The person whose social group will be used for the query. + /// The social group to use in order to get the list of users. (e.g. "friends" or "favorites") + /// The async object for notifying when the operation is completed. This contains a vectorview of MultiplayerActivityDetails objects, containing the details of the activities of the targeted users. + _XSAPIIMP pplx::task>> get_activities_for_social_group( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& socialGroupOwnerXboxUserId, + _In_ const string_t& socialGroup + ); + + /// + /// Queries for the current activity for a set of users specified by xuid. + /// There is no paging or continuation, and the multiplayer service will limit the + /// number of items returned to 100. + /// + /// The scid within which to query for activities. + /// The list of user ids to find activities for. + /// The async object for notifying when the operation is completed. This contains a vectorview of MultiplayerActivityDetails objects, containing the details of the activities of the targeted users. + _XSAPIIMP pplx::task>> get_activities_for_users( + _In_ const string_t& serviceConfigurationId, + _In_ const std::vector& xboxUserIds + ); + + /// + /// Queries for the all search handles that references the searchable sessions given the specific query. + /// There is no paging or continuation, and the multiplayer service will limit the number of items returned to 100. + /// Call get_search_handles(multiplayer_query_search_handle_request) instead. + /// + /// The scid within which to query for search handles. + /// The name of the template to query for search handles. + /// This specifies the attribute to sort the search handles by. Pass empty string to default to ordering by 'Timestamp asc'. (Optional) + /// Pass true to order ascending, false to order descending + /// The query string to get the search handles for. (Optional) + /// The search query. + /// The query syntax is an OData like syntax with only the following operators supported EQ, NE, GE, GT, LE and LT along with the logical operators of AND and OR. + /// + /// Example 1: + /// To search for search handles for a specific XboxUserId use + /// "MemberXuids/any(d:d eq 12345678)" or "OwnerXuids/any(d:d eq 12345678)" + /// + /// Example 2: + /// To search for search handles for a title defined string metadata use + /// "Strings/stringMetadataType eq value" + /// + /// Example 3: + /// To search for search handles for a title defined numbers metadata AND a tag type value use + /// Numbers/numberMetadataType eq 53 AND Tags/tagType eq value + /// + /// The async object for notifying when the operation is completed. This contains a vectorview of multiplayer_search_handle_details objects, containing the details of the search handles. + _XSAPIIMP pplx::task>> get_search_handles( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& orderBy, + _In_ bool orderAscending, + _In_ const string_t& searchFilter + ); + + /// + /// Queries for the all search handles that references the searchable sessions given the specific query. + /// There is no paging or continuation, and the multiplayer service will limit the number of items returned to 100. + /// + /// + /// The async object for notifying when the operation is completed. This contains a vectorview of multiplayer_search_handle_details objects, containing the details of the search handles. + _XSAPIIMP pplx::task>> get_search_handles( + _In_ const multiplayer_query_search_handle_request& searchHandleRequest + ); + + /// + /// Starts multiplayerservice connectivity via RTA, for two purposes: + /// 1. subscriptions to changes on specific sessions, using the MultiplayerSession object. + /// 2. automatic removal of members from sessions when the collection underlying this multiplayer subscription is broken. + /// This method does not actually make the connection, but enables the connection, and helps track its lifetime. + /// This method will fail if called twice, unless the multiplayerconnection has been lost or stopped in the interim. + /// This can be detected by listening for the MultiplayerSubscriptionsLost event. + /// + _XSAPIIMP std::error_code enable_multiplayer_subscriptions(); + + /// + /// Stops multiplayerservice connectivity via RTA. + /// When stopping multiplayer is complete, a MultiplayerSubscriptionsLost event will fire. + /// It is not necessary to wait for this event to fire, unless you intend to call EnableMultiplayerSubscriptions() to re-start it, + /// in which case you must wait for the stop to complete. + /// + _XSAPIIMP void disable_multiplayer_subscriptions(); + + /// + /// Indicates whether multiplayer subscriptions are currently enabled. + /// + _XSAPIIMP bool subscriptions_enabled(); + + /// + /// Registers an event handler for notifications when a multiplayer session changes. + /// Event handlers receive a multiplayer_session_change_event_args& object. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + /// + /// Session subscriptions are created using the multiplayer_session object within the multiplayer namespace. + /// + _XSAPIIMP function_context add_multiplayer_session_changed_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for multiplayer session change notifications. + /// + /// The function_context object that was returned when the event handler was registered. + /// The callback function that recieves notifications. + _XSAPIIMP void remove_multiplayer_session_changed_handler(_In_ function_context context); + + /// + /// Registers an event handler for notifications when a multiplayer subscription is lost. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + /// + /// Session subscriptions are created using the multiplayer_session object within the multiplayer namespace. + /// + _XSAPIIMP function_context add_multiplayer_subscription_lost_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for multiplayer subscription lost notifications. + /// + /// The function_context object that was returned when the event handler was registered. + /// The callback function that recieves notifications. + _XSAPIIMP void remove_multiplayer_subscription_lost_handler(_In_ function_context context); + + std::shared_ptr _Xbox_live_context_settings() { return m_xboxLiveContextSettings; } + + /// + /// Internal function + /// + static tournaments::tournament_game_result_state _Convert_string_to_game_result_state(_In_ const string_t& value); + + /// + /// Internal function + /// + static tournaments::tournament_game_result_source _Convert_string_to_game_result_source(_In_ const string_t& value); + + /// + /// Internal function + /// + static string_t _Convert_game_result_state_to_string(_In_ tournaments::tournament_game_result_state value); + +private: + multiplayer_service(); + + multiplayer_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivity + ); + + pplx::task>> write_session_using_subpath( + _In_ std::shared_ptr session, + _In_ multiplayer_session_write_mode mode, + _In_ const string_t& subpathAndQuery + ); + + static string_t multiplayer_session_directory_create_or_update_subpath( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& sessionName + ); + + static string_t multiplayer_session_directory_create_or_update_by_handle_subpath( + _In_ const string_t& handleId + ); + + static string_t multiplayer_session_directory_get_sessions_sub_path( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateNameFilter, + _In_ const string_t& xboxUserIdFilter, + _In_ const string_t& keywordFilter, + _In_ const string_t& visibilityFilter, + _In_ uint32_t contextVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ bool isBatch, + _In_ uint32_t maxItems + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::shared_ptr m_multiplayerServiceImpl; + + friend xbox_live_context_impl; + friend xbox::services::multiplayer::manager::multiplayer_client_manager; +}; +}}} \ No newline at end of file diff --git a/Include/xsapi/multiplayer_manager.h b/Include/xsapi/multiplayer_manager.h new file mode 100644 index 00000000..f082ca89 --- /dev/null +++ b/Include/xsapi/multiplayer_manager.h @@ -0,0 +1,1638 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#include "pplx/pplxtasks.h" +#include "xsapi/services.h" + +namespace xbox { namespace services { + + namespace system { + class xbox_live_user; + } +}} + +#if TV_API | XBOX_UWP +typedef Windows::Xbox::System::User^ xbox_live_user_t; +#else +typedef std::shared_ptr xbox_live_user_t; +#endif + +#if XSAPI_CPP +typedef const void* context_t; +#else +typedef Platform::Object^ context_t; +#endif + +namespace xbox { namespace services { + /// + /// Contains classes related to multiplayer. + /// + namespace multiplayer { + /// + /// Contains classes and enumerations for more easily managing multiplayer + /// scenarios. + /// + namespace manager { + +class multiplayer_client_manager; +class multiplayer_lobby_client; +class multiplayer_game_client; + +/// +/// Defines values used to indicate who can join your lobby. +/// +enum class joinability +{ + /// + /// Joinability not set or no lobby exists yet. + /// + none, + + /// + /// Default value. The lobby is joinable by users who are followed by an existing member of the session. + /// + joinable_by_friends, + + /// + /// The lobby is joinable only via an invite. + /// + invite_only, + + /// + /// This option will close the lobby only when a game is in progress. All other times, + /// it will keep the lobby open for invite_only so invitees can join when no game is in progress. + /// + disable_while_game_in_progress, + + /// + /// This option will close the lobby immediately. + /// + closed +}; + +/// +/// Defines values used to indicate status for the matchmaking stages. +/// +enum match_status +{ + /// + /// Indicates no matchmaking search has been started. + /// + none, + + /// + /// Indicates that a match ticket was submitted for matchmaking. + /// + submitting_match_ticket, + + /// + /// Indicates that matchmaking is still searching. + /// + searching, + + /// + /// Indicates that matchmaking search has found a match. + /// + found, + + /// + /// Joining initialization stage. + /// Matchmaking creates the game session and adds users to it. + /// The client has up to the joining timeout to join the session during this phase. + /// + joining, + + /// + /// Waiting for remote clients to join the game session. + /// The client has up to the joining timeout to join the session during this phase. + /// + waiting_for_remote_clients_to_join, + + /// + /// Measuring initialization stage. + /// Stage where QoS measurement happens. + /// The client has up to the measurement timeout to upload qos measurements to the service during this phase. + /// + measuring, + + /// + /// Uploading QoS measurement results to the service. + /// The client has up to the measurement timeout to upload qos measurements to the service during this phase. + /// + uploading_qos_measurements, + + /// + /// Waiting for remote clients to upload QoS measurement results to the service. + /// The client has up to the measurement timeout to upload qos measurements to the service during this phase. + /// + waiting_for_remote_clients_to_upload_qos, + + /// + /// Evaluating initialization stage. + /// If auto evaluate is true, then this stage is skipped. + /// Otherwise the title will do its own evaluation. + /// + evaluating, + + /// + /// Match was found and QoS measurement was successful. + /// + completed, + + /// + /// If the match that was found was not successful and is resubmitting. + /// + resubmitting, + + /// + /// Indicates that matchmaking search has expired. + /// + expired, + + /// + /// Indicates that matchmaking is in the process of canceling the search. + /// + canceling, + + /// + /// Indicates that matchmaking search has been canceled. + /// + canceled, + + /// + /// Failed initialization stage. + /// The initialization failed. + /// + failed, +}; + +/// +/// Defines values used to indicate event types for a multiplayer lobby or game. +/// +enum class multiplayer_event_type +{ + /// + /// Indicates the user was added. + /// + user_added, + + /// + /// Indicates the user was removed. + /// + user_removed, + + /// + /// Indicates a new member has joined the session. + /// The event_args object should be cast to a + /// member_joined_event_args object for more information. + /// + member_joined, + + /// + /// Indicates a member has left the session. + /// The event_args object should be cast to a + /// member_left_event_args object for more information. + /// + member_left, + + /// + /// Indicates a member property has changed. + /// The event_args object should be cast to a + /// member_property_changed_event_args object for more information. + /// + member_property_changed, + + /// + /// Indicates that the set_local_member_properties() or delete_local_member_properties() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write local member properties by calling the set_local_member_properties() operation. + /// + local_member_property_write_completed, + + /// + /// Indicates that the set_local_member_connection_address() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write local member properties by calling the set_local_member_connection_address() operation. + /// + local_member_connection_address_write_completed, + + /// + /// Indicates a session (lobby or game) property has changed. + /// The event_args object should be cast to a + /// session_property_changed_event_args object for more information. + /// + session_property_changed, + + /// + /// Indicates that the set_synchronized_properties() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write synchronized properties by calling the set_properties() operation. + /// + session_property_write_completed, + + /// + /// Indicates that the set_synchronized_properties() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write synchronized properties by calling the set_synchronized_properties() operation. + /// + session_synchronized_property_write_completed, + + /// + /// Indicates host has changed. + /// The event_args object should be cast to a + /// host_changed_event_args object for more information. + /// + host_changed, + + /// + /// Indicates that the set_synchronized_host() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write synchronized host by calling the set_synchronized_host() operation. + /// + synchronized_host_write_completed, + + /// + /// Indicates that the joinability value has changed. + /// A game can be change the state by calling the set_joinability() operation. + /// + joinability_state_changed, + + /// + /// Fired when a match has been found, and the client has joined the target game session. + /// When this event occurs, title should provide qos measurement results (via set_quality_of_service_measurements) between itself and a list of remote clients. + /// Note: If your title does not require QoS (based on the session template), this event will not be triggered. + /// + perform_qos_measurements, + + /// + /// Indicates that the find_match() operation has completed. + /// The event_args object should be cast to a + /// find_match_completed_event_args object for more information. + /// + find_match_completed, + + /// + /// Indicates that the join_game() operation has completed. Once the join succeeds, + /// the member is now part of the game session, and can use data in the session + /// to connect to other game members. + /// + join_game_completed, + + /// + /// Indicates that the leave_game() operation has completed. After recieving this event, + /// the game session object will be set to null. You can join another game by calling + /// join_game() or join_game_from_lobby(). + /// + leave_game_completed, + + /// + /// Indicates that the join_lobby() operation has completed. Once the join succeeds, + /// the member is now part of the lobby session, and can use data in the session + /// to connect to other lobby members. The event_args object should be cast to a + /// join_lobby_completed_event_args object for more information. + /// + join_lobby_completed, + + /// + /// Fired when the title's connection to MPSD using the real-time activity service is lost. + /// When this event occurs, the title should shut down the multiplayer. + /// + client_disconnected_from_multiplayer_service, + + /// + /// Indicates that the invite API operation has been completed. + /// + invite_sent, + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Triggered when the tournament's team registration state changes. The event_args object + /// should be cast to a tournament_registration_state_changed_event_args object for more information. + /// + tournament_registration_state_changed, + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Triggered when a new game has been scheduled. The event_args object + /// should be cast to a tournament_game_session_ready_event_args object for more information. + /// + tournament_game_session_ready, + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Triggered when arbitration is complete and game results have been written to the game session. + /// + arbitration_complete +}; + +/// +/// Defines values used to indicate types for multiplayer sessions. +/// +enum class multiplayer_session_type +{ + /// + /// The session type is unknown. + /// + unknown, + + /// + /// Indicates multiplayer lobby session. + /// + lobby_session, + + /// + /// Indicates multiplayer game session. + /// + game_session, + + /// + /// Indicates multiplayer match session. + /// + match_session +}; + +/// +/// Represents a reference to a member in a multiplayer game. +/// +class multiplayer_member +{ +public: + /// + /// Internal function + /// + multiplayer_member(); + + /// + /// Internal function + /// + multiplayer_member( + _In_ std::shared_ptr member, + _In_ bool isLocal, + _In_ bool isGameHost, + _In_ bool isLobbyHost, + _In_ bool isInLobby, + _In_ bool isInGame + ); + + /// + /// Id for the member. + /// + _XSAPIIMP uint32_t member_id() const; + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Id of this members' team in a tournament. + /// + _XSAPIIMP const string_t& team_id() const; + + /// + /// Xbox User ID of the member. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The Gamertag of the member. This is only to be used for debugging purposes as this gamertag may be out of date. + /// It is recommended you use social manager or the profile service to get this information. + /// + _XSAPIIMP const string_t& debug_gamertag() const; + + /// + /// Indicates if this member is playing on the local device. + /// + _XSAPIIMP bool is_local() const; + + /// + /// Indicates if this member is part of the lobby. + /// + _XSAPIIMP bool is_in_lobby() const; + + /// + /// Indicates if this member is part of the game. + /// + _XSAPIIMP bool is_in_game() const; + + /// + /// The status of this member. + /// + _XSAPIIMP xbox::services::multiplayer::multiplayer_session_member_status status() const; + + /// + /// The address used for network connection. + /// This can be used for secure socket connection. + /// + _XSAPIIMP const string_t& connection_address() const; + + /// + /// JSON value that specify the custom properties of the member. + /// + _XSAPIIMP const web::json::value& properties() const; + + /// + /// Determines whether the member is on the same device. + /// + _XSAPIIMP bool is_member_on_same_device( + _In_ std::shared_ptr member + ) const; + + /// + /// Internal function. + /// + const string_t& _Device_token() const; +private: + + string_t m_teamId; + uint32_t m_memberId; + string_t m_xboxUserid; + string_t m_gamertag; + string_t m_deviceToken; + bool m_isLocal; + bool m_isGameHost; + bool m_isLobbyHost; + bool m_isInLobby; + bool m_isInGame; + xbox::services::multiplayer::multiplayer_session_member_status m_status; + string_t m_connectionAddress; + web::json::value m_jsonProperties; +}; + +/// +/// Represents a multiplayer lobby. This is also where you would manage members that are local to this device. +/// There are 2 game objects when using a mulitplayer manager. One repesents the lobby_session() which is where friends you invite will join. +/// Another is the game_session() which contains people that your lobby has been matched with. +/// +class multiplayer_lobby_session +{ +public: + /// + /// Internal function + /// + multiplayer_lobby_session(); + + /// + /// A unique ID to the session used to query trace logs for entries that relate to the session. + /// + _XSAPIIMP const string_t& correlation_id() const; + + /// + /// Object containing identifying information for the session. + /// + _XSAPIIMP const xbox::services::multiplayer::multiplayer_session_reference& session_reference() const; + + /// + /// A collection of members that are local to this device. + /// + _XSAPIIMP const std::vector>& local_members() const; + + /// + /// A collection of members that are in the lobby. When a friend accepts a game invite, + /// members will be added to the lobby. + /// + _XSAPIIMP const std::vector>& members() const; + + /// + /// Returns the host member for the lobby. + /// The host is defined as the user with the lowest index on the host device. + /// + _XSAPIIMP std::shared_ptr host() const; + + /// + /// JSON string that specify the custom properties for the game. These can be changed anytime. + /// + _XSAPIIMP const web::json::value& properties() const; + + /// + /// A set of constants associated with this session. These can only be set through the session template. + /// + _XSAPIIMP std::shared_ptr session_constants() const; + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// The known last team result of the tournament. + /// + _XSAPIIMP const xbox::services::tournaments::tournament_team_result& last_tournament_team_result() const; + + /// + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// Hosts a new lobby when the first user is added. For all other users, they will be added to the existing lobby + /// as secondary users. This API will also advertise the lobby for friends to join. + /// You can send invites, set lobby properties, access lobby memebers via lobby() only once you've added the local user. + /// While joining a lobby via an invite, or a handleId, you can skip adding the local user to avoid creating a lobby and + /// instead pass in the list of users in the join_lobby() API. + /// + /// The associated system User. + _XSAPIIMP xbox_live_result add_local_user( + _In_ xbox_live_user_t user + ); + + /// + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// Removes the local user from the lobby and game session. + /// After this method is called, if no local users are active, title will not be able to perform any further multiplayer operations. + /// You can join another game or re-add the local user. + /// + /// The associated system User. + _XSAPIIMP xbox_live_result remove_local_user( + _In_ xbox_live_user_t user + ); + + /// + /// Set a custom property on the local member to the specified JSON string + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// The result is delivered via multiplayer_event callback of type local_member_property_write_completed through do_work(). + /// + /// The associated system User you want to set the property for. + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_local_member_properties( + _In_ xbox_live_user_t user, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context = nullptr + ); + + /// + /// Delete a custom property on the local member + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// The result is delivered via multiplayer_event callback of type local_member_property_write_completed through do_work(). + /// + /// The associated system User you want to delete the property for. + /// The name of the property to delete + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result delete_local_member_properties( + _In_ xbox_live_user_t user, + _In_ const string_t& name, + _In_opt_ context_t context = nullptr + ); + + /// + /// Set connection address for the local member. The address can be used for network and secure socket connection. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// The result is delivered via multiplayer_event callback of type local_member_connection_address_write_completed through do_work(). + /// + /// The associated system User you want to set the property for. + /// The network connection address to set. + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_local_member_connection_address( + _In_ xbox_live_user_t user, + _In_ const string_t& connectionAddress, + _In_opt_ context_t context = nullptr + ); + + /// + /// Whether or not the Xbox User ID is the host. + /// + /// The Xbox User ID of the user + _XSAPIIMP bool is_host( + _In_ const string_t& xboxUserId + ); + + /// + /// Set a custom game property to the specified JSON string. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// The result is delivered via multiplayer_event callback of type session_property_write_completed through do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context = nullptr + ); + + /// + /// Sets a custom property to the specified JSON string using multiplayer_session_write_mode::synchronized_update. + /// Use this method to resolve any conflicts between devices while trying to set properties to a shared portion that other + /// devices can also modify. It ensures that updates to the session are atomic. If writing to non-sharable properties, use set_properties() instead. + /// The service may reject your request if a race condition occurred (due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type session_synchronized_property_write_completed through do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_synchronized_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context = nullptr + ); + + /// + /// Sets the host for the game using multiplayer_session_write_mode::synchronized_update. Use this method to resolve + /// any conflicts between devices trying to set the host at the same time. It ensures that updates to the session are atomic. + /// The service may reject your request if a race condition occurred(due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type synchronized_host_write_completed through do_work(). + /// + /// The host member. + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_synchronized_host( + _In_ std::shared_ptr gameHost, + _In_opt_ context_t context = nullptr + ); + +#if !XSAPI_U + /// + /// Displays the invite UI and allows the user to select people from the user's people list and invite them to join the user's party + /// If a user accepts that notification the title will be activated. + /// + /// The associated system User. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with ///. (Optional) + /// The activation context string. (Optional) + _XSAPIIMP xbox_live_result invite_friends( + _In_ xbox_live_user_t user, + _In_ const string_t& contextStringId = string_t(), + _In_ const string_t& customActivationContext = string_t() + ); +#endif + + /// + /// Invites the specified users to a game. This will result in a notification being shown to + /// each invited user using standard invite text. If a user accepts that notification the title will be activated. + /// + /// The associated system User. + /// The list of xbox user IDs who will be invited. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with ///. (Optional) + /// The activation context string. (Optional) + /// The async object for notifying when the operation is completed. + _XSAPIIMP xbox_live_result invite_users( + _In_ xbox_live_user_t user, + _In_ const std::vector& xboxUserIds, + _In_ const string_t& contextStringId = string_t(), + _In_ const string_t& customActivationContext = string_t() + ); + + /// + /// Internal function + /// + multiplayer_lobby_session( + _In_ std::shared_ptr multiplayerClientManagerInstance + ); + + /// + /// Internal function + /// + multiplayer_lobby_session( + _In_ std::shared_ptr session, + _In_ std::shared_ptr host, + _In_ std::vector> members, + _In_ std::vector> localMmembers + ); + + /// + /// Internal function. + /// + uint64_t _Change_number() const; + + /// + /// Internal function + /// + void _Set_multiplayer_client_manager( + _In_ std::shared_ptr clientManager + ); + + /// + /// Internal function + /// + std::shared_ptr _Create_deep_copy(); + + /// + /// Internal function + /// + void _Set_host(_In_ std::shared_ptr hostMember); + +#if defined(XSAPI_CPPWINRT) + + _XSAPIIMP xbox_live_result add_local_user( + _In_ winrt::Windows::Xbox::System::User user + ) + { + return add_local_user(convert_user_to_cppcx(user)); + } + + _XSAPIIMP xbox_live_result remove_local_user( + _In_ winrt::Windows::Xbox::System::User user + ) + { + return remove_local_user(convert_user_to_cppcx(user)); + } + + _XSAPIIMP xbox_live_result set_local_member_properties( + _In_ winrt::Windows::Xbox::System::User user, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context = nullptr + ) + { + return set_local_member_properties( + convert_user_to_cppcx(user), + name, + valueJson, + context + ); + } + + _XSAPIIMP xbox_live_result delete_local_member_properties( + _In_ winrt::Windows::Xbox::System::User user, + _In_ const string_t& name, + _In_opt_ context_t context = nullptr + ) + { + return delete_local_member_properties( + convert_user_to_cppcx(user), + name, + context + ); + } + + _XSAPIIMP xbox_live_result set_local_member_connection_address( + _In_ winrt::Windows::Xbox::System::User user, + _In_ const string_t& connectionAddress, + _In_opt_ context_t context = nullptr + ) + { + return set_local_member_connection_address( + convert_user_to_cppcx(user), + connectionAddress, + context + ); + } + +#if !XSAPI_U + _XSAPIIMP xbox_live_result invite_friends( + _In_ winrt::Windows::Xbox::System::User user, + _In_ const string_t& contextStringId = string_t(), + _In_ const string_t& customActivationContext = string_t() + ) + { + return invite_friends( + convert_user_to_cppcx(user), + contextStringId, + customActivationContext + ); + } +#endif + + _XSAPIIMP xbox_live_result invite_users( + _In_ winrt::Windows::Xbox::System::User user, + _In_ const std::vector& xboxUserIds, + _In_ const string_t& contextStringId = string_t(), + _In_ const string_t& customActivationContext = string_t() + ) + { + return invite_users( + convert_user_to_cppcx(user), + xboxUserIds, + contextStringId, + customActivationContext + ); + } +#endif + +private: + + void deep_copy_from(_In_ const multiplayer_lobby_session& other); + + std::shared_ptr m_multiplayerClientManager; + + string_t m_correlationId; + uint64_t m_changeNumber; + xbox::services::tournaments::tournament_team_result m_lastTournamentTeamResult; + xbox::services::multiplayer::multiplayer_session_reference m_sessionReference; + std::shared_ptr m_host; + std::vector> m_members; + std::vector> m_localMembers; + web::json::value m_properties; + std::shared_ptr m_sessionConstants; +}; + +/// +/// Represents a multiplayer game. +/// There are 2 game objects when using a mulitplayer manager. One repesents the lobby_session() which is where friends you invite will join. +/// Another is the game_session() which contains people that your lobby has been matched with. +/// +class multiplayer_game_session +{ +public: + /// + /// Internal function + /// + multiplayer_game_session(); + + /// + /// Internal function + /// + multiplayer_game_session( + _In_ std::shared_ptr session, + _In_ std::shared_ptr host, + _In_ std::vector> members + ); + + /// + /// A unique ID to the session used to query trace logs for entries that relate to the session. + /// + _XSAPIIMP const string_t& correlation_id() const; + + /// + /// Object containing identifying information for the session. + /// + _XSAPIIMP const xbox::services::multiplayer::multiplayer_session_reference& session_reference() const; + + /// + /// A collection of members that are in the game. When a friend accepts a game invite, + /// members will be added to the lobby and the game session members list. + /// + _XSAPIIMP const std::vector>& members() const; + + /// + /// Returns the host member for the game. + /// The host is defined as the user with the lowest index on the host device. + /// + _XSAPIIMP std::shared_ptr host() const; + + /// + /// JSON string that specify the custom properties for the game. These can be changed anytime. + /// + _XSAPIIMP const web::json::value& properties() const; + + /// + /// A set of constants associated with this session. These can only be set through the session template. + /// + _XSAPIIMP std::shared_ptr session_constants() const; + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Teams currently participating in this tournament game. + /// + _XSAPIIMP const std::unordered_map& tournament_teams() const; + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Tournament team results for the game. + /// + _XSAPIIMP const std::unordered_map& tournament_team_results() const; + + /// + /// Whether or not the Xbox User ID is the host. + /// + /// The Xbox User ID of the user + _XSAPIIMP bool is_host( + _In_ const string_t& xboxUserId + ); + + /// + /// Set a custom game property to the specified JSON string. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context = nullptr + ); + + /// + /// Sets a custom property to the specified JSON string using multiplayer_session_write_mode::synchronized_update. + /// Use this method to resolve any conflicts between devices while trying to set properties to a shared portion that other + /// devices can also modify. It ensures that updates to the session are atomic. If writing to non-sharable properties, use set_properties() instead. + /// The service may reject your request if a race condition occurred (due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type synchronized_property_write_completed through do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_synchronized_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context = nullptr + ); + + /// + /// Sets the host for the game using multiplayer_session_write_mode::synchronized_update. Use this method to resolve + /// any conflicts between devices trying to set the host at the same time. It ensures that updates to the session are atomic. + /// The service may reject your request if a race condition occurred(due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type synchronized_host_write_completed through do_work(). + /// + /// The host member. + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_synchronized_host( + _In_ std::shared_ptr gameHost, + _In_opt_ context_t context = nullptr + ); + + /// + /// Internal function. + /// + uint64_t _Change_number() const; + + /// + /// Internal function + /// + std::shared_ptr _Create_deep_copy(); + + /// + /// Internal function + /// + void _Set_multiplayer_client_manager( + _In_ std::shared_ptr clientManager + ); + + /// + /// Internal function + /// + void _Set_host(_In_ std::shared_ptr hostMember); + +private: + + void deep_copy_from(_In_ const multiplayer_game_session& other); + + string_t m_correlationId; + uint64_t m_changeNumber; + std::unordered_map m_teams; + std::unordered_map m_tournamentTeamResults; + xbox::services::multiplayer::multiplayer_session_reference m_sessionReference; + std::shared_ptr m_host; + std::vector> m_members; + web::json::value m_properties; + std::shared_ptr m_sessionConstants; + std::shared_ptr m_multiplayerClientManager; +}; + +class multiplayer_event_args +{ +public: + multiplayer_event_args(){} + + virtual ~multiplayer_event_args(){} +}; + +/// +/// Notifies the title when a new user was added. +/// +class user_added_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + user_added_event_args( + _In_ string_t xboxUserId + ); + + /// + /// Xbox User ID of the member that that was added. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + +private: + string_t m_xboxUserid; +}; + +/// +/// Notifies the title when a user was removed. +/// +class user_removed_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + user_removed_event_args( + _In_ string_t xboxUserId + ); + + /// + /// Xbox User ID of the member that that was removed. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + +private: + string_t m_xboxUserid; +}; + +/// +/// Notifies the title when a new game member joins the game. +/// +class member_joined_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + member_joined_event_args( + _In_ std::vector> members + ); + + /// + /// A list of members that joined the game. + /// + _XSAPIIMP std::vector> members(); + +private: + std::vector> m_members; +}; + +/// +/// Notifies the title when an existing game member leaves the game. +/// +class member_left_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + member_left_event_args( + _In_ std::vector> members + ); + + /// + /// A list of members that left the game. + /// + _XSAPIIMP std::vector> members(); + +private: + std::vector> m_members; +}; + +/// +/// Notifies the title when a new host member has been set. +/// +class host_changed_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + host_changed_event_args( + _In_ std::shared_ptr hostMember + ); + + /// + /// The new host member. If an existing host leaves, the host_member() will be nullptr. + /// + _XSAPIIMP std::shared_ptr host_member(); + +private: + std::shared_ptr m_hostMember; +}; + +/// +/// Notifies the title when a game member property has been added or modified. +/// +class member_property_changed_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + member_property_changed_event_args( + _In_ std::shared_ptr member, + _In_ web::json::value jsonProperties + ); + + /// + /// The member whose property changed. + /// + _XSAPIIMP std::shared_ptr member(); + + /// + /// The JSON of the property that changed. + /// + _XSAPIIMP web::json::value properties(); + +private: + std::shared_ptr m_member; + web::json::value m_properties; +}; + +/// +/// Notifies the title when a session property has been added or modified. +/// +class session_property_changed_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + session_property_changed_event_args( + _In_ web::json::value jsonProperties + ); + + /// + /// The JSON of the property that changed. + /// + _XSAPIIMP const web::json::value& properties(); + +private: + web::json::value m_properties; +}; + +/// +/// Notifies the title when the client joins a lobby. Once join succeeds, the member is now +/// part of the lobby session, and can use data in the session to connect to other lobby members. +/// To join a friend's lobby, call join_lobby(handleId) operation using the handleId you back get from +/// multiplayer_service::get_activities_for_social_group. If the user accepts an invite or joined a friends' game via the shell, +/// the title will get protocol activated, in which case you should call join_lobby(IProtocolActivatedEventArgs^). +/// +/// For scenarios where the local user has not been added, you can pass the local user object part of the join_lobby API. +/// If the invited user is not added via add_local_user() or through join_lobby, then join_lobby() will fail and +/// provide the invited_xbox_user_id() that the invite was sent for as part of the join_lobby_completed_event_args(). +/// +class join_lobby_completed_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + join_lobby_completed_event_args( + _In_ string_t xboxUserId + ); + + /// + /// Invited Xbox User ID of the member that the invite was sent for. + /// + _XSAPIIMP const string_t& invited_xbox_user_id() const; + +private: + string_t m_invitedXboxUserid; +}; + +/// +/// Contains information for an event that indicates when a multiplayer match is found. +/// +class find_match_completed_event_args : public multiplayer_event_args +{ +public: + find_match_completed_event_args( + _In_ xbox::services::multiplayer::manager::match_status status, + _In_ xbox::services::multiplayer::multiplayer_measurement_failure failure + ); + + /// + /// Provides the current matchmaking status. + /// + _XSAPIIMP xbox::services::multiplayer::manager::match_status match_status() const; + + /// + /// The cause of why the initialization failed, or multiplayer_measurement_failure::None if there was no failure. + /// Set when transitioning out of the "joining" or "measuring" stage if this member doesn't pass. + /// + _XSAPIIMP xbox::services::multiplayer::multiplayer_measurement_failure initialization_failure_cause() const; + +private: + xbox::services::multiplayer::manager::match_status m_matchStatus; + xbox::services::multiplayer::multiplayer_measurement_failure m_initializationFailure; +}; + +/// +/// Notifies the title when it should provide qos measurement results between itself and a list of remote clients. +/// +class perform_qos_measurements_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + perform_qos_measurements_event_args( + _In_ std::map addressDeviceTokenMap + ); + + /// + /// A map of connection addresses and device tokens to run qos on. + /// + _XSAPIIMP const std::map& connection_address_to_device_tokens() const; + +private: + std::map m_addressToDeviceTokenMap; +}; + +/// +/// Contains information for an event that indicates when the tournament registration state changes. +/// +class tournament_registration_state_changed_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + tournament_registration_state_changed_event_args( + _In_ xbox::services::tournaments::tournament_registration_state state, + _In_ xbox::services::tournaments::tournament_registration_reason reason + ); + + /// + /// The tournament team registration state. + /// + _XSAPIIMP xbox::services::tournaments::tournament_registration_state registration_state() const; + + /// + /// The tournament team registration reason for the certain registration states. + /// + _XSAPIIMP xbox::services::tournaments::tournament_registration_reason registration_reason() const; + +private: + xbox::services::tournaments::tournament_registration_state m_registrationState; + xbox::services::tournaments::tournament_registration_reason m_registrationReason; +}; + +/// +/// Triggered when a new game has been scheduled. Game session is where the match will actually be played. +/// +class tournament_game_session_ready_event_args : public multiplayer_event_args +{ +public: + /// + /// Internal function + /// + tournament_game_session_ready_event_args( + _In_ utility::datetime startTime + ); + + /// + /// Game's start time for the tournament. + /// + _XSAPIIMP const utility::datetime& start_time() const; + +private: + utility::datetime m_startTime; +}; + +/// +/// Base class for all event arg classes. Based on the multiplayer_event_type, you would need to cast the args +/// to the appropriate class. +/// +class multiplayer_event +{ +public: + /// + /// Internal function + /// + multiplayer_event( + _In_ std::error_code errorCode, + _In_ std::string errorMessage, + _In_ multiplayer_event_type eventType, + _In_ std::shared_ptr eventArgs, + _In_ multiplayer_session_type sessionType, + _In_opt_ context_t context = nullptr + ); + + /// + /// The error code indicating the result of the operation. + /// + _XSAPIIMP const std::error_code& err() const; + + /// + /// Returns call specific debug information if join fails + /// It is not localized, so only use for debugging purposes. + /// + _XSAPIIMP const std::string& err_message() const; + + /// + /// A pointer to the application-defined data passed into the initiating method. + /// + context_t context(); + + /// + /// Type of the event triggered. + /// + _XSAPIIMP multiplayer_event_type event_type() const; + + /// + /// You need to cast this to one of the event arg classes to retrieve the data for that particular event. + /// + _XSAPIIMP std::shared_ptr event_args(); + + /// + /// The multiplayer session type this event was triggered for. Depending upon the session type, + /// you can then retrieve the latest lobby or game session from the multiplayer_manager class. + /// + _XSAPIIMP multiplayer_session_type session_type() const; + +private: + context_t m_pContext; + std::error_code m_errorCode; + std::string m_errorMessage; + multiplayer_event_type m_eventType; + multiplayer_session_type m_sessionType; + std::shared_ptr m_eventArgs; +}; + +/// +/// APIs for matchmaking, player roster and multiplayer session management. +/// +class multiplayer_manager +{ +public: + + /// + /// Gets the multiplayer_manager singleton instance + /// + _XSAPIIMP static std::shared_ptr get_singleton_instance(); + + /// + /// Initializes the object. + /// + /// The name of the template for the lobby session to be based on. + _XSAPIIMP void initialize( + _In_ string_t lobbySessionTemplateName + ); + + /// + /// Ensures proper game state updates are maintained between the title and the Xbox Live Multiplayer Service. + /// To ensure best performance, do_work() must be called frequently, such as once per frame. + /// Title needs to be thread safe when calling do_work() since this is when the state will change. + /// For example, if you looping through the list of members() on a different thread than your calling do_work() on, + /// it may change when do_work() is called. + /// + /// A list of all callback events for the game to handle. Empty if no events are triggered during this update. + _XSAPIIMP std::vector do_work(); + + /// + /// Represents a lobby session used for managing members that are local to this device and your invited friends. + /// When a member accepts a game invite, they will be added to the lobby and the game session (if it exists). + /// Users found via matchmaking will not be added in the lobby. + /// + _XSAPIIMP std::shared_ptr lobby_session() const; + + /// + /// Represents a game session used for your active gameplay. When a member accepts an invite, + /// they will be added to the lobby and the game session (if there is room). + /// You can call leave_game() to leave the game session. + /// + _XSAPIIMP std::shared_ptr game_session() const; + + /// + /// Joins a game given a session handle id. A handle is a service-side pointer to a session. + /// The handleId is a GUID identifier of the handle. Callers will usually get the handleId from + /// another member's multiplayer_activity_details. Optionally, if you haven't added the local users through + /// lobby_session()::add_local_user(), you can pass in the list of users via the join_lobby() API. + /// The result is delivered via multiplayer_event callback of type join_lobby_completed through do_work(). + /// After joining, you can set the host via set_synchronized_host if one doesn't exist. + /// + /// A multiplayer handle id, which uniquely identifies the game session you want to join. + /// The system User joining the lobby. + _XSAPIIMP xbox_live_result join_lobby( + _In_ const string_t& handleId, + _In_ xbox_live_user_t user + ); + +#if (TV_API || UWP_API || UNIT_TEST_SERVICES) + /// + /// Joins a game via the specified IProtocolActivatedEventArgs. + /// The IProtocolActivatedEventArgs provides arguments for protocol activation. If the user accepts an invite or + /// joined a friends game via a shell UI, the title will get a protocol activation. The result is delivered via + /// join_lobby_completed_event_args() callback through do_work(). + /// Optionally, if you haven't added the local users through lobby_session()::add_local_user(), you can pass in + /// the list of users via the join_lobby() API. If the invited user is not added either via + /// lobby_session()::add_local_user() or through join_lobby(), then join_lobby() will fail and provide the + /// invited_xbox_user_id() that the invite was sent for as part of the join_lobby_completed_event_args() + /// After joining, you can set the host via set_synchronized_host if one doesn't exist. + /// + /// The IProtocolActivatedEventArgs when the title is protocol activated. + /// The system User joining the lobby. + _XSAPIIMP xbox_live_result join_lobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ xbox_live_user_t user + ); +#endif + +#if TV_API | XBOX_UWP + /// + /// Joins a game given a session handle id. A handle is a service-side pointer to a game session. + /// The handleId is a GUID identifier of the handle. Callers will usually get the handleId from + /// another member's multiplayer_activity_details. Optionally, if you haven't added the local users through + /// lobby_session()::add_local_user(), you can pass in the list of users via the join_lobby() API. + /// The result is delivered via multiplayer_event callback of type join_lobby_completed through do_work(). + /// After joining, you can set the host via set_synchronized_host if one doesn't exist. + /// + /// A multiplayer handle id, which uniquely identifies the game session you want to join. + /// List of system Users joining the lobby. + _XSAPIIMP xbox_live_result join_lobby( + _In_ const string_t& handleId, + _In_ std::vector users + ); + + /// + /// Joins a game via the specified IProtocolActivatedEventArgs. + /// The IProtocolActivatedEventArgs provides arguments for protocol activation. If the user accepts an invite or + /// joined a friends game via a shell UI, the title will get a protocol activation. The result is delivered via + /// join_lobby_completed_event_args() callback through do_work(). + /// Optionally, if you haven't added the local users through lobby_session()::add_local_user(), you can pass in + /// the list of users via the join_lobby() API. If the invited user is not added either via + /// lobby_session()::add_local_user() or through join_lobby(), then join_lobby() will fail and provide the + /// invited_xbox_user_id() that the invite was sent for as part of the join_lobby_completed_event_args() + /// After joining, you can set the host via set_synchronized_host if one doesn't exist. + /// + /// The IProtocolActivatedEventArgs when the title is protocol activated. + /// List of system Users joining the lobby. + _XSAPIIMP xbox_live_result join_lobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ std::vector users + ); + + /// + /// Send invites to your party to join your game. + /// + _XSAPIIMP void invite_party_to_game(); + +#endif + + /// + /// Join the lobby's game session if one exists and if there is room. If the session doesn't exist, it creates a new game session + /// with the existing lobby members. The result is delivered via multiplayer_event callback of + /// type join_game_completed through do_work(). This does not migrate existing lobby session properties over to the game session. + /// After joining, you can set the properties or the host via game_session()::set_synchronized APIs. + /// + /// The name of the template for the game session to be based on. + _XSAPIIMP xbox_live_result join_game_from_lobby( + _In_ const string_t& sessionTemplateName + ); + + /// + /// Joins a game given a globally unique session name. Callers can get the unique session name + /// as a result of the title's third party matchmaking. Call this on all clients that needs to join this game. + /// The result is delivered via multiplayer_event callback of type join_game_completed through do_work(). + /// After joining, you can set the properties or the host via game_session()::set_synchronized APIs. + /// + /// A unique name for the session. + /// The name of the template for the game session to be based on. + /// The list of xbox user IDs you want to be part of the game. + _XSAPIIMP xbox_live_result join_game( + _In_ const string_t& sessionName, + _In_ const string_t& sessionTemplateName, + _In_ const std::vector& xboxUserIds = std::vector() + ); + + /// + /// Leaving the game will put you back into the lobby. This will remove all local users from the game. + /// The result is delivered via multiplayer_event callback of type leave_game_completed through do_work(). + /// + _XSAPIIMP xbox_live_result leave_game(); + + /// + /// Sends a matchmaking request to the server. When a match is found, the manager will join + /// the game and notify the title via find_match_completed_event(). + /// + /// The name of the hopper. + /// The ticket attributes for the match. (Optional) + /// The maximum time to wait for members to join the match. (Optional) + _XSAPIIMP xbox_live_result find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes = web::json::value(), + _In_ const std::chrono::seconds& timeout = std::chrono::seconds(60) + ); + + /// + /// Cancels the match request on the server, if one exists. + /// + _XSAPIIMP void cancel_match(); + + /// + /// Provides the current status of matchmaking. 'None' if no matchmaking is in progress. + /// + _XSAPIIMP xbox::services::multiplayer::manager::match_status match_status() const; + + /// + /// Estimated wait time for a match request to be matched with other members. + /// Only applies after find_match() has been called. + /// + std::chrono::seconds estimated_match_wait_time() const; + + /// + /// Indicates whether the game should auto fill open slots during gameplay. + /// + bool auto_fill_members_during_matchmaking() const; + + /// + /// If set to true, it finds members via matchmaking to fill open slots during gameplay. + /// This can be changed anytime. + /// + /// True to search for members during matchmaking if the game has open slots. + void set_auto_fill_members_during_matchmaking( + _In_ bool autoFillMembers + ); + + /// + /// Sets a collection of multiplayer_quality_of_service_measurements between itself and a list of remote clients. + /// This is only used when the title is manually managing QoS. + /// + _XSAPIIMP void set_quality_of_service_measurements( + _In_ std::shared_ptr> measurements + ); + + /// + /// Indicates who can join your game via the lobby. + /// + _XSAPIIMP joinability joinability() const; + + /// + /// Restricts who can join the game. Defaults to "joinable_by_friends", meaning only local users and users who are followed + /// by an existing member of the lobby can join without an invite. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// The result is delivered via multiplayer_event callback of type joinability_state_changed through do_work(). + /// + /// The joinability value you want to set. + /// The application-defined data to correlate the multiplayer_event to the initiating call. (Optional) + _XSAPIIMP xbox_live_result set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context = nullptr + ); + + /// + /// Internal function + /// + bool _Is_dirty(); + + /// + /// Internal function + /// + std::shared_ptr _Get_multiplayer_client_manager() { return m_multiplayerClientManager; } + + /// + /// Internal function + /// + std::shared_ptr _Game_client(); + + /// + /// Internal function + /// + std::shared_ptr _Lobby_client(); + +#if UNIT_TEST_SERVICES + // + /// Internal function + /// + void _Shutdown(); +#endif + +#if TV_API | XBOX_UWP +#if defined(XSAPI_CPPWINRT) + _XSAPIIMP xbox_live_result join_lobby( + _In_ const string_t& handleId, + _In_ std::vector users + ) + { + return join_lobby(handleId, convert_user_vector_to_cppcx(users)); + } + + _XSAPIIMP xbox_live_result join_lobby( + _In_ winrt::Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs eventArgs, + _In_ std::vector users + ) + { + return join_lobby(convert_eventargs_to_cppcx(eventArgs), convert_user_vector_to_cppcx(users)); + } + + _XSAPIIMP xbox_live_result join_lobby( + _In_ winrt::Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs eventArgs, + _In_ winrt::Windows::Xbox::System::User user + ) + { + return join_lobby(convert_eventargs_to_cppcx(eventArgs), convert_user_to_cppcx(user)); + } +#endif +#endif + +private: + + multiplayer_manager(); + multiplayer_manager(multiplayer_manager const&); + void operator=(multiplayer_manager const&); + + bool m_isDirty; + void set_multiplayer_game_session(_In_ std::shared_ptr gameSession); + void set_multiplayer_lobby_session(_In_ std::shared_ptr multiplayerLobby); + + mutable std::mutex m_lock; + xbox::services::multiplayer::manager::joinability m_joinability; + std::shared_ptr m_multiplayerLobbySession; + std::shared_ptr m_multiplayerGameSession; + std::shared_ptr m_multiplayerClientManager; +}; + +}}}} diff --git a/Include/xsapi/notification_helper.h b/Include/xsapi/notification_helper.h new file mode 100644 index 00000000..84ed55d5 --- /dev/null +++ b/Include/xsapi/notification_helper.h @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#if XSAPI_I +#include "errors.h" + +namespace xbox { namespace services { + + enum class xbox_live_notification_type + { + unknown = 2, + game_invite = 1, + achievement_unlocked = 0 + }; + + struct xbox_live_notification + { + xbox_live_notification_type type; + string_t title; + string_t body; + string_t data; + }; + + + xbox_live_result parse_notification(NSDictionary* notificationInfo); + +}} +#endif diff --git a/Include/xsapi/presence.h b/Include/xsapi/presence.h new file mode 100644 index 00000000..38827a70 --- /dev/null +++ b/Include/xsapi/presence.h @@ -0,0 +1,876 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/real_time_activity.h" + +#if !XSAPI_U +namespace xbox { namespace services { namespace experimental { namespace social { namespace manager { + enum class change_list_enum; +} } } } } +#endif + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that let you retrieve + /// information about player's online presence on Xbox Live. + /// + namespace presence { + +class presence_service_impl; + +/// Defines values used to indicate the device type associate with a PresenceTitleRecord. +enum class presence_device_type +{ + /// Unknown device + unknown, + + /// Windows Phone device + windows_phone, + + /// Windows Phone 7 device + windows_phone_7, + + /// Web device, like Xbox.com + web, + + /// Xbox360 device + xbox_360, + + /// Games for Windows LIVE device + pc, + + /// Xbox LIVE for Windows device + windows_8, + + /// Xbox One device + xbox_one, + + /// Windows One Core devices + windows_one_core, + + /// Windows One Core Mobile devices + windows_one_core_mobile +}; + +/// +/// Defines values used to indicate the state of the user with regard to the presence service. +/// +enum class user_presence_state +{ + /// The state is unknown. + unknown, + + /// User is signed in to Xbox LIVE and active in a title. + online, + + /// User is signed-in to Xbox LIVE, but inactive in all titles. + away, + + /// User is not signed in to Xbox LIVE. + offline +}; + +/// +/// Defines values used to indicate the states of the screen view of presence information. +/// +enum class presence_title_view_state +{ + /// Unknown view state. + unknown, + + /// The title's view is using the full screen. + full_screen, + + /// The title's view is using part of the screen with another application snapped. + filled, + + /// The title's view is snapped with another application using a part of the screen. + snapped, + + /// The title's running in the background and is not visible. + background +}; + +/// Defines values used to set the level of presence detail return from the service. Choosing proper detail level could help the performance of the API. +enum class presence_detail_level +{ + /// Default detail level. + default_level, + + /// User detail level. User presence info only, no device, title or rich presence info. + user, + + /// Device detail level. User and device presence info only, no title or rich presence info. + device, + + /// Title detail level. User, device and title presence info only, no rich presence info. + title, + + /// All detail possible. User, device, title and rich presence info will be provided. + all +}; + +/// Defines values used to indicate the media id types for media presence data. +enum class presence_media_id_type +{ + /// Unknown media Id. + unknown, + + /// Bing media Id. + bing, + + /// MediaProvider media Id. + media_provider +}; + +/// Defines values used to indicate the title presence state for a user. +enum class title_presence_state +{ + /// + /// Indicates this is a Unknown state. + /// + unknown, + + /// + /// Indicates the user started playing the title. + /// + started, + + /// + /// Indicates the user ended playing the title. + /// + ended +}; + +/// +/// Represents data supporting Rich Presence features. +/// +class presence_data +{ +public: + /// + /// Initializes a new instance of the PresenceData class, which identifies where the presence strings are defined and which of the defined strings is used. + /// + /// The service configuration ID (SCID) that identifies where the presence strings are defined by Id. + /// Id of the presence string that should be used. + _XSAPIIMP presence_data( + _In_ string_t serviceConfigurationId, + _In_ string_t presenceId + ); + + /// + /// Initializes a new instance of the PresenceData class, which identifies where the presence strings are defines, which string is used, and IDs of strings to be used in place of tokens within the presence string. + /// + /// The service configuration ID (SCID) that identifies where the presence strings are defined by Id. + /// Id of the presence string that should be used. + /// Ids of the strings that should be used to replace the tokens in the presence string. + _XSAPIIMP presence_data( + _In_ string_t serviceConfigurationId, + _In_ string_t presenceId, + _In_ std::vector presenceTokenIds + ); + + /// + /// ID of the service configuration containing the presence strings. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The ID of a presence string that is defined in the service configuration. + /// For example, PresenceId = "1" could equal "Playing {0} on {1}" in the service configuration. + /// The service configuration might map token 0 to Maps and token 1 to MapId. + /// + _XSAPIIMP const string_t& presence_id() const; + + /// + /// The IDs of the strings to replace the format string tokens found in the presence string. These strings are also defined in the service configuration. + /// The ID values in the collection map to the strings associated with the token arguments found in the PresenceId. + /// For example let's say this vector view contained the values "4" and "1" and PresenceId = "1" equals "Playing {0} on {1}" in the service configuration. + /// The service configuration might map Token 0 = Maps, where MapId = "4" equals "Hometown". + /// The service configuration might map Token 1 = Difficulty, where DifficultyId = "1" equals "Casual". + /// + _XSAPIIMP const std::vector& presence_token_ids() const; + + /// + /// Internal function + /// + presence_data(); + + /// + /// Internal function + /// + bool _Should_serialize() const; + + /// + /// Internal function + /// + web::json::value _Serialize() const; + +private: + string_t m_serviceConfigurationId; + string_t m_presenceId; + bool m_shouldSerialize; + std::vector m_presenceTokenIds; +}; + +class presence_broadcast_record +{ +public: + /// + /// Id for this broadcast as defined by the broadcasting service. + /// + _XSAPIIMP const string_t& broadcast_id() const; + + /// + /// The GUID uniquely identifying the broadcasting session. + /// + _XSAPIIMP const string_t& session() const; + + /// + /// Name of the streaming provider. + /// + _XSAPIIMP const string_t& provider() const; + + /// + /// Approximate number of current viewers. + /// + _XSAPIIMP uint32_t viewer_count() const; + + /// + /// UTC timestamp when the broadcast was started. + /// + _XSAPIIMP const utility::datetime& start_time() const; + + /// + /// Internal function + /// + presence_broadcast_record(); + + /// + /// Internal function + /// + bool operator!=(_In_ const presence_broadcast_record& rhs) const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + string_t m_broadcastId; + string_t m_session; + string_t m_provider; + uint32_t m_viewerCount; + utility::datetime m_startTime; +}; + +class presence_title_record +{ +public: + + /// + /// The title ID. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The title name. + /// + _XSAPIIMP const string_t& title_name() const; + + /// + /// The UTC timestamp when the record was last updated. + /// + _XSAPIIMP const utility::datetime last_modified_date() const; + + /// + /// The active state for the title. + /// + _XSAPIIMP bool is_title_active() const; + + /// + /// The formatted and localized presence string. + /// + _XSAPIIMP const string_t& presence() const; + + /// + /// The title view state. + /// + _XSAPIIMP presence_title_view_state presence_title_view() const; + + /// + /// The broadcast information of what the user is broadcasting. + /// + _XSAPIIMP const presence_broadcast_record& broadcast_record() const; + + /// + /// Internal function + /// + presence_title_record(); + + /// + /// Internal function + /// + presence_title_record( + _In_ uint32_t titleId, + _In_ title_presence_state titlePresenceState + ); + + /// + /// Internal function + /// + void _Set_title_state( + _In_ title_presence_state state + ); + + bool operator!=(_In_ const presence_title_record& rhs) const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + /// + /// Internal function + /// + static presence_title_view_state _Convert_string_to_presence_title_view_state( + _In_ const string_t& value + ); + +private: + uint32_t m_titleId; + string_t m_titleName; + utility::datetime m_lastModifiedDate; + bool m_isTitleActive; + string_t m_presence; + presence_title_view_state m_titleViewState; + presence_broadcast_record m_broadcastRecord; +}; + +class presence_device_record +{ +public: + /// + /// The device type associated with this record. + /// + _XSAPIIMP presence_device_type device_type() const; + + /// + /// The record containing title presence data. + /// + _XSAPIIMP const std::vector& presence_title_records() const; + + /// + /// Internal function + /// + presence_device_record(); + + /// + /// Internal function + /// + presence_device_record( + _In_ presence_device_type deviceType + ); + + /// + /// Internal function + /// + bool operator!=(_In_ const presence_device_record& rhs); + + /// + /// Internal function + /// + static presence_device_type _Convert_string_to_presence_device_type(_In_ const string_t& value); + + /// + /// Internal function + /// + static string_t _Convert_presence_device_type_to_string(_In_ presence_device_type deviceType); + + /// + /// Internal function + /// + void _Add_title_record( + _In_ uint32_t titleId, + _In_ title_presence_state titlePresenceState + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + std::unordered_map create_map_from_title_records( + _In_ const std::vector& titleRecords + ) const; + + std::vector m_presenceTitleRecords; + presence_device_type m_deviceType; +}; + +class presence_media_record +{ +public: + /// + /// ID of the media used by the Bing catalog or the provider catalog. + /// + _XSAPIIMP const string_t& media_id() const; + + /// + /// The ID type of the media. + /// + _XSAPIIMP presence_media_id_type media_id_type() const; + + /// + /// Localized name of the media content. + /// + _XSAPIIMP const string_t& name() const; + + /// + /// Internal function + /// + presence_media_record(); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + + /// + /// Internal function + /// + static presence_media_id_type _Convert_string_to_media_id_type( + _In_ const string_t& value + ); + +private: + string_t m_mediaId; + presence_media_id_type m_mediaIdType; + string_t m_name; +}; + +class presence_record +{ +public: + /// + /// Initializes a new presence record object. + /// + _XSAPIIMP presence_record(); + + /// + /// The Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The user's presence state. + /// + _XSAPIIMP user_presence_state user_state() const; + + /// + /// Collection of PresenceDeviceRecord objects returned by a request. + /// + _XSAPIIMP const std::vector& presence_device_records() const; + + /// + /// Returns whether the user is playing this title id + /// + _XSAPIIMP bool is_user_playing_title(_In_ uint32_t titleId) const; + + /// + /// Internal function + /// + void _Update_title( + _In_ uint32_t titleId, + _In_ title_presence_state state + ); + + /// + /// Internal function + /// + void _Update_device( + _In_ presence_device_type deviceType, + _In_ bool isUserLoggedIn + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + /// + /// Internal function + /// + static user_presence_state _Convert_string_to_user_presence_state(_In_ const string_t& value); + +private: + static std::unordered_map create_map_from_device_list(_In_ const std::vector& deviceRecords); + + string_t m_xboxUserId; + user_presence_state m_userState; + std::vector m_presenceDeviceRecords; +}; + +/// +/// Used to identify the Xbox user, device, and log-in status presence values. +/// +class device_presence_change_event_args +{ +public: + /// + /// The Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The type of device. + /// + _XSAPIIMP presence_device_type device_type() const; + + /// + /// Value used to indicate if the Xbox user is logged onto the device. + /// + _XSAPIIMP bool is_user_logged_on_device() const; + + /// + /// Internal function + /// + device_presence_change_event_args(); + + /// + /// Internal function + /// + device_presence_change_event_args( + _In_ string_t xboxUserId, + _In_ presence_device_type deviceType, + _In_ bool isUserLoggedOnDevice + ); + +private: + string_t m_xboxUserId; + presence_device_type m_deviceType; + bool m_isUserLoggedOnDevice; +}; + +/// +/// Subscribes to changes to an Xbox user's presence on a device. +/// +class device_presence_change_subscription : public xbox::services::real_time_activity::real_time_activity_subscription +{ +public: + /// + /// Internal function + /// + device_presence_change_subscription(); + + /// + /// Internal function + /// + device_presence_change_subscription( + _In_ string_t xboxUserId, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ); + /// + /// The Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + +protected: + void on_subscription_created(_In_ uint32_t id, _In_ const web::json::value& data) override; + void on_event_received(_In_ const web::json::value& data) override; + +private: + string_t m_xboxUserId; + std::function m_devicePresenceChangeHandler; +}; + +/// +/// Used to identify a Xbox user, title, and presence states that can be subscribed to. +/// +class title_presence_change_event_args +{ +public: + /// + /// The Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The title ID. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// Object that defines possible presence states. + /// + _XSAPIIMP title_presence_state title_state() const; + + /// + /// Internal function + /// + title_presence_change_event_args(); + + /// + /// Internal function + /// + title_presence_change_event_args( + _In_ string_t xboxUserId, + _In_ uint32_t titleId, + _In_ title_presence_state titleState + ); + +private: + string_t m_xboxUserId; + uint32_t m_titleId; + title_presence_state m_titleState; +}; + +/// +/// Subscribes to presence change events for the specified title and user. +/// +class title_presence_change_subscription : public real_time_activity::real_time_activity_subscription +{ +public: + /// + /// The Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The title ID. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// Internal function + /// + title_presence_change_subscription( + _In_ string_t xboxUserId, + _In_ uint32_t titleId, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ); + +protected: + void on_subscription_created(_In_ uint32_t id, _In_ const web::json::value& data) override; + void on_event_received(_In_ const web::json::value& data) override; + +private: + string_t m_xboxUserId; + uint32_t m_titleId; + std::function m_handler; +}; + +class presence_writer; + +class presence_service +{ +public: + /// + /// Sets presence info for the current user context. + /// + /// Indicates if the current user context is currently active or inactive in the title. + /// The application can choose to set this based on an amount of inactivity. + /// Current user's presence data. + /// Calls V1 POST /users/xuid({xuid})/devices/current/titles/current + _XSAPIIMP pplx::task> set_presence( + _In_ bool isUserActiveInTitle + ); + + /// + /// Sets presence info for the current user context. + /// + /// Indicates if the current user context is currently active or inactive in the title. + /// The application can choose to set this based on an amount of inactivity. + /// Current user's presence data. + /// Calls V1 POST /users/xuid({xuid})/devices/current/titles/current + _XSAPIIMP pplx::task> set_presence( + _In_ bool isUserActiveInTitle, + _In_ presence_data presenceData + ); + + /// + /// Gets presence info for a specific Xbox User Id. + /// + /// The Xbox User ID of the user to get presence for + /// Calls V3 GET /users/xuid({xuid}) + _XSAPIIMP pplx::task> get_presence( + _In_ const string_t& xboxUserId + ); + + /// + /// Gets presence info for multiple users. This returns all possible titles on all device, + /// defaults to presence_detail_level::default which is equivalent to + /// presence_detail_level::title (get basic title level information), + /// and does not filter out users who are offline or broadcasting. + /// + /// The name of the users to get presence for. + /// Calls V3 POST /users/batch + _XSAPIIMP pplx::task>> get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds + ); + + /// + /// Gets presence info for multiple users with filters. + /// + /// The name of the users to get presence for. + /// List of device types. If the input is an empty vector, defaults to all possible deviceTypes. + /// List of titleIds for filtering the result. If the input is an empty vector, defaults to all possible titles. + /// Detail level of the result. Defaults to all details + /// If true, API will filter out records for users that are offline + /// If true, API will filter out records for users that are not broadcasting. + /// Calls V3 POST /users/batch + _XSAPIIMP pplx::task>> get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level presenceDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + /// + /// Gets presence info for a specific group of users. + /// + /// The name of the group of users to get presence for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// Calls V3 GET /users/xuid({xuid})/groups/{socialGroup} + _XSAPIIMP pplx::task>> get_presence_for_social_group( + _In_ const string_t& socialGroup + ); + + /// + /// Gets presence info for a specific group of users. + /// + /// The name of the group of users to get presence for. + /// The user whose group should be targeted. If the input is null, current user will be used. + /// List of device types. If the input is null; defaults to all possible deviceTypes. (Optional) + /// List of titleIds for filtering the result. If the input is null, defaults to all possible titles. (Optional) + /// Detail level of the result. Defaults to all details. (Optional) + /// If true, API will filter out records for users that are offline. + /// If true, API will filter out records for users that are not broadcasting. + /// Calls V3 POST /users/batch + _XSAPIIMP pplx::task>> get_presence_for_social_group( + _In_ const string_t& socialGroup, + _In_ const string_t& socialGroupOwnerXboxUserId, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level peoplehubDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + /// + /// Subscribes to device presence change notifications via the DevicePresenceChanged event. + /// + /// The Xbox User ID of the person of the subscription. + /// RealTimeActivityDevicePresenceChangeSubscription containing the initial value of the PresenceDeviceRecord. + /// Register for device presence changes via the DevicePresenceChanged event. + _XSAPIIMP xbox_live_result> subscribe_to_device_presence_change( + _In_ const string_t& xboxUserId + ); + + /// + /// Unsubscribes a previously created device presence change subscription. + /// + /// The subscription object to unsubscribe. + _XSAPIIMP xbox_live_result unsubscribe_from_device_presence_change( + _In_ std::shared_ptr subscription + ); + + /// + /// Subscribes to title presence change notifications via the TitlePresenceChanged event. + /// + /// The Xbox User ID of the person of the subscription. + /// The title ID of the subscription. + /// RealTimeActivityDevicePresenceChangeSubscription containing the initial value of the PresenceDeviceRecord. + /// Register for device presence changes via the DevicePresenceChanged event. + _XSAPIIMP xbox_live_result> subscribe_to_title_presence_change( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId + ); + + /// + /// Registers for title presence change notifications. Event handlers will receive RealTimeActivityTitlePresenceChangeEventArgs^. + /// + _XSAPIIMP xbox_live_result unsubscribe_from_title_presence_change( + _In_ std::shared_ptr subscription + ); + + /// + /// Registers an event handler for device presence change notifications. + /// Event handlers receive a device_presence_change_event_args& object. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_device_presence_changed_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for device presence change notifications. + /// + /// The function_context object that was returned when the event handler was registered. + /// The callback function that recieves notifications. + _XSAPIIMP void remove_device_presence_changed_handler(_In_ function_context context); + + /// + /// Registers an event handler for title presence change notifications. + /// Event handlers receive a title_presence_change_event_args& object. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_title_presence_changed_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for title presence change notifications. + /// + /// The function_context object that was returned when the event handler was registered. + /// The callback function that recieves notifications. + _XSAPIIMP void remove_title_presence_changed_handler(_In_ function_context context); + + /// + /// Internal function + /// + std::shared_ptr _Xbox_live_context_settings(); + + /// + /// Internal function + /// + std::shared_ptr _Impl() const { return m_presenceServiceImpl; } + +private: + presence_service(); + + presence_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivityService + ); + + static string_t set_presence_sub_path(_In_ const string_t& xboxUserId); + static string_t get_presence_sub_path(_In_ const string_t& xboxUserId); + static string_t get_presence_user_batch_subpath(); + static string_t get_presence_for_social_group_subpath(_In_ const string_t& xboxUserId, _In_ const string_t& socialGroup); + + pplx::task> set_presence_helper(_In_ bool isUserActive, _In_ presence_data presenceData); + + std::shared_ptr m_presenceServiceImpl; + + friend xbox_live_context_impl; +}; + +}}} \ No newline at end of file diff --git a/Include/xsapi/privacy.h b/Include/xsapi/privacy.h new file mode 100644 index 00000000..d958e9c8 --- /dev/null +++ b/Include/xsapi/privacy.h @@ -0,0 +1,309 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { +namespace services { + class xbox_live_context_impl; +/// +/// Contains classes and enumerations that let you retrieve +/// information about a player's privacy settings from Xbox Live. +/// +namespace privacy { + +/// +/// Contains the reason why permission was denied. +/// +class permission_deny_reason +{ +public: + permission_deny_reason(); + + /// + /// The reason why permission was denied. + /// + _XSAPIIMP const string_t& reason() const; + + /// + /// If the deny reason is privilege check, this indicates which privilege failed. + /// + _XSAPIIMP const string_t& restricted_setting() const; + + static xbox_live_result _Deserializer(_In_ const web::json::value& json); + +private: + string_t m_reason; + string_t m_restrictedSetting; +}; + +/// +/// Contains the result of a permission check. +/// +class permission_check_result +{ +public: + + /// + /// Creates a new permission_check_result object. + /// + _XSAPIIMP permission_check_result(); + + /// + /// Indicates if the user is allowed the requested access. + /// + _XSAPIIMP bool is_allowed() const; + + /// + /// The permission requested. + /// + _XSAPIIMP const string_t& permission_requested() const; + + /// + /// If IsAllowed is false, contains the reasons why the permissions were denied. + /// + _XSAPIIMP const std::vector& deny_reasons() const; + + /// + /// Internal function + /// + _XSAPIIMP void initialize(_In_ const string_t& permissionIdRequested); + + static xbox_live_result _Deserializer(_In_ const web::json::value& json); + +private: + bool m_isAllowed; + std::vector m_denyReasons; + string_t m_permissionRequested; +}; + +/// +/// Contains the results of multiple permission checks. +/// +class multiple_permissions_check_result +{ +public: + + /// + /// Creates a new multiple_permissions_check_result object. + /// + _XSAPIIMP multiple_permissions_check_result(); + + /// + /// Xbox User Id for the target user of the permission request. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Contains a collection of results returned when checking multiple permissions for a user. + /// + _XSAPIIMP const std::vector& items() const; + + /// + /// Internal function + /// + void initialize( + _In_ uint32_t index, + _In_ const string_t& permissionIdRequested + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserializer(_In_ const web::json::value& json); + +private: + string_t m_xboxUserId; + std::vector m_items; +}; + +/// +/// Manages constant values for permission IDs. +/// +class permission_id_constants +{ +public: + /// + /// Check whether or not the user can send a message with text content to the target user. + /// + _XSAPIIMP static const string_t communicate_using_text() { return _T("CommunicateUsingText"); } + + /// + /// Check whether or not the user can communicate using video with the target user. + /// + _XSAPIIMP static const string_t communicate_using_video() { return _T("CommunicateUsingVideo"); } + + /// + /// Check whether or not the user can communicate using voice with the target user. + /// + _XSAPIIMP static const string_t communicate_using_voice() { return _T("CommunicateUsingVoice"); } + + /// + /// Check whether or not the user can view the profile of the target user. + /// + _XSAPIIMP static const string_t view_target_profile() { return _T("ViewTargetProfile"); } + + /// + /// Check whether or not the user can view the game history of the target user. + /// + _XSAPIIMP static const string_t view_target_game_history() { return _T("ViewTargetGameHistory"); } + + /// + /// Check whether or not the user can view the details video watching history of the target user. + /// + _XSAPIIMP static const string_t view_target_video_history() { return _T("ViewTargetVideoHistory"); } + + /// + /// Check whether or not the user can view the detailed music listening history of the target user. + /// + _XSAPIIMP static const string_t view_target_music_history() { return _T("ViewTargetMusicHistory"); } + + /// + /// Check whether or not the user can view the exercise info of the target user. + /// + _XSAPIIMP static const string_t view_target_exercise_info() { return _T("ViewTargetExerciseInfo"); } + + /// + /// Check whether or not the user can view the online status of the target user. + /// + _XSAPIIMP static const string_t view_target_presence() { return _T("ViewTargetPresence"); } + + /// + /// Check whether or not the user can view the details of the targets video status (extended online presence). + /// + _XSAPIIMP static const string_t view_target_video_status() { return _T("ViewTargetVideoStatus"); } + + /// + /// Check whether or not the user can view the details of the targets music status (extended online presence). + /// + _XSAPIIMP static const string_t view_target_music_status() { return _T("ViewTargetMusicStatus"); } + + /// + /// Check whether or not a user can play multiplayer with the target user. + /// + _XSAPIIMP static const string_t play_multiplayer() { return _T("PlayMultiplayer"); } + + /// + /// Checks whether or not the user can view information about how audio buffers are broadcast for the target user. + /// + _XSAPIIMP static const string_t broadcast_with_twitch() { return _T("BroadcastWithTwitch"); } + + /// + /// Check whether or not the user can view the user-created content of other users. + /// + _XSAPIIMP static const string_t view_target_user_created_content() { return _T("ViewTargetUserCreatedContent"); } +}; + +/// +/// Provides an endpoint for managing privacy settings. +/// +class privacy_service +{ +public: + /// + /// Get the list of Xbox Live Ids the calling user should avoid during multiplayer matchmaking. + /// + /// A collection of XboxUserIds that correspond to the calling user's avoid list. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/xuid({xuid})/people/avoid + /// + _XSAPIIMP pplx::task>> get_avoid_list(); + + /// + /// Check a single permission with a single target user. + /// + /// The ID of the permission to check. + /// See microsoft::xbox::services::privacy::permission_id_constants for the latest options. + /// The target user's xbox Live ID for validation + /// The permission check result against a single user. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/{requestorId}/permission/validate + /// + _XSAPIIMP pplx::task> check_permission_with_target_user( + _In_ const string_t& permissionId, + _In_ const string_t& targetXboxUserId + ); + + /// + /// Check multiple permissions with multiple target users. + /// + /// The collection of IDs of the permissions to check. + /// See microsoft::xbox::services::privacy::permission_id_constants for the latest options. + /// The collection of target Xbox user IDs to check permissions against. + /// A multiple permission check result which contains a collection of permission information. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 POST /users/{requestorId}/permission/validate + /// + _XSAPIIMP pplx::task>> check_multiple_permissions_with_multiple_target_users( + _In_ std::vector permissionIds, + _In_ std::vector targetXboxUserIds + ); + + /// + /// Get the list of Xbox Live Ids that the calling user should not hear (mute) during multiplayer matchmaking. + /// + /// The collection of Xbox user IDs that represent the mute list for a user. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/xuid({xuid})/people/mute + /// + _XSAPIIMP pplx::task>> get_mute_list(); + + /// + /// Get either a user's avoid list or a user's mute list. + /// + /// A string indicating what type of list to get for the user. + /// The valid values are "avoid" and "mute". + /// The collection of Xbox user IDs that represent the either the avoid list or the mute list for a user. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/xuid({xuid})/people/mute + /// + _XSAPIIMP pplx::task>> get_avoid_or_mute_list(_In_ const string_t& subPathName); + +private: + privacy_service() {}; + + privacy_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static const string_t avoid_mute_list_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& subPathName + ); + + static const string_t permission_validate_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& setting, + _In_ const string_t& targetXboxUserId + ); + + static const string_t permission_batch_validate_sub_path( + _In_ const string_t& xboxUserId + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend xbox_live_context_impl; +}; + +} } } \ No newline at end of file diff --git a/Include/xsapi/profile.h b/Include/xsapi/profile.h new file mode 100644 index 00000000..80ed613c --- /dev/null +++ b/Include/xsapi/profile.h @@ -0,0 +1,191 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that let you retrieve + /// information about a player's Xbox Live profile. + /// + namespace social { + +/// +/// Represents a user's Xbox Live profile. +/// +class xbox_user_profile +{ +public: + /// Constructor for a user profile object. + /// The user's display name to be used in application UI. + /// Uri for the user's display picture to be used in application UI. + /// The user's display name to be used in game UI. + /// Uri for the user's display picture to be used in games. + /// The user's Gamerscore. + /// The user's Gamertag. + /// The user's Xbox user ID. + _XSAPIIMP xbox_user_profile( + _In_ string_t appDisplayName, + _In_ web::uri appDisplayPictureResizeUri, + _In_ string_t gameDisplayName, + _In_ web::uri gameDisplayPictureResizeUri, + _In_ string_t gamerscore, + _In_ string_t gamertag, + _In_ string_t xboxUserId + ); + + /// + /// Internal function + /// + _XSAPIIMP xbox_user_profile(); + + /// + /// The user's display name to be used in application UI. This value is privacy gated and could + /// be a user's real name or their Gamertag. + /// + _XSAPIIMP const string_t& app_display_name() const; + + /// + /// Uri for the user's display picture to be used in application UI. + /// The Uri is a resizable Uri. It can be used to specify one of the following sizes and formats by appending '&format={format}&w={width}&h={height}: + /// Format: png + /// Width Height + /// 64 64 + /// 208 208 + /// 424 424 + /// + _XSAPIIMP const web::uri& app_display_picture_resize_uri() const; + + /// + /// The user's display name to be used in game UI. This value is privacy gated and could + /// be a user's real name or their Gamertag. + /// + _XSAPIIMP const string_t& game_display_name() const; + + /// + /// Uri for the user's display picture to be used in games. + /// The Uri is a resizable Uri. It can be used to specify one of the following sizes and formats by appending '&format={format}&w={width}&h={height}: + /// Format: png + /// Width Height + /// 64 64 + /// 208 208 + /// 424 424 + /// + _XSAPIIMP const web::uri& game_display_picture_resize_uri() const; + + /// + /// The user's Gamerscore. + /// + _XSAPIIMP const string_t& gamerscore() const; + + /// + /// The user's Gamertag. + /// + _XSAPIIMP const string_t& gamertag() const; + + /// + /// The user's Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_appDisplayName; + web::uri m_appDisplayPictureResizeUri; + string_t m_gameDisplayName; + web::uri m_gameDisplayPictureResizeUri; + string_t m_gamerscore; + string_t m_gamertag; + string_t m_xboxUserId; +}; + +/// +/// Services that manage user profile. +/// +class profile_service +{ +public: + /// + /// Gets a user profile for a specific Xbox user. + /// + /// The Xbox User ID of the user to get the profile for. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is an xbox_user_profile object. + /// + /// Calls V2 GET /users/batch/profile/settings + _XSAPIIMP pplx::task> get_user_profile( + _In_ string_t xboxUserId + ); + + /// + /// Gets one or more user profiles for a collection of specified Xbox users. + /// + /// The collection of Xbox User IDs of the users to get profiles for + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is a collection of xbox_user_profile objects. + /// + /// Calls V2 GET /users/batch/profile/settings + _XSAPIIMP pplx::task>> get_user_profiles( + _In_ const std::vector& xboxUserIds + ); + + /// + /// Gets user profiles for users in a specified social group. + /// + /// The name of the social group of users to search. + /// See xbox::services::social::social_group_constants for the latest options. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is a collection of xbox_user_profile objects. + /// + /// Calls V2 GET /users/{userId}/profile/settings/people/{socialGroup} + _XSAPIIMP pplx::task>> get_user_profiles_for_social_group( + _In_ const string_t& socialGroup + ); + +private: + profile_service() {}; + + profile_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + static const string_t settings_query(); + + static const string_t pathandquery_user_profiles_for_social_group( + _In_ const string_t& socialGroup + ); + + static web::json::value serialize_settings_json(); + + static const string_t SETTINGS_ARRAY[]; + + static const web::json::value SETTINGS_SERIALIZED; + + static const string_t SETTINGS_QUERY; + + static std::mutex m_settingsLock; + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend xbox_live_context_impl; +}; + + +}}} diff --git a/Include/xsapi/real_time_activity.h b/Include/xsapi/real_time_activity.h new file mode 100644 index 00000000..f67c67ce --- /dev/null +++ b/Include/xsapi/real_time_activity.h @@ -0,0 +1,386 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#include + +namespace xbox { namespace services { + class web_socket_connection; + class xbox_web_socket_client; + class xbox_live_context_impl; + enum class web_socket_connection_state; +}} + +namespace xbox { +namespace services { +namespace real_time_activity { + class real_time_activity_service_factory; + class real_time_activity_subscription_error_event_args; +}}} + +namespace xbox { namespace services { + /// + /// Contains classes and enumerations that let you subscribe + /// to real time activity information for a player statistic + /// on Xbox Live. + /// + namespace real_time_activity { + +/// +/// Enumeration for the message types for the Xbox Live service. +/// The value of each enum should not be changed. +/// +enum class real_time_activity_message_type +{ + /// + /// Indicates that this is a Subscribe message. + /// + subscribe = 1, + + /// + /// Indicates that this is a Unsubscribe message. + /// + unsubscribe = 2, + + /// + /// Indicates that this is a ChangeEvent message. + /// + change_event = 3, + + /// + /// Indicates that this is a Resync message. + /// + resync = 4 +}; + +/// +/// Enumeration for the possible states of a statistic subscription request +/// to the real-time activity service. +/// +enum real_time_activity_subscription_state +{ + /// + /// The subscription state is unknown. + /// + unknown, + + /// + /// Waiting for the server to respond to the subscription request. + /// + pending_subscribe, + + /// + /// Subscription confirmed. + /// + subscribed, + + /// + /// Waiting for the server to respond to the unsubscribe request. + /// + pending_unsubscribe, + + /// + /// Unsubscribe confirmed. + /// + closed +}; + +/// +/// Enumeration for the possible connection states of the connection +/// to the real-time activity service. +/// +enum real_time_activity_connection_state +{ + /// + /// Currently connected to the real-time activity service. + /// + connected, + + /// + /// Currently connecting to the real-time activity service. + /// + connecting, + + /// + /// Currently disconnected from the real-time activity service. + /// + disconnected +}; + +/// +/// The base class for real time activity subscriptions. +/// +class real_time_activity_subscription +{ +public: + /// + /// Internal function + /// + real_time_activity_subscription(_In_ std::function subscriptionErrorHandler); + + /// The state of the subscription request. + _XSAPIIMP real_time_activity_subscription_state state() const; + virtual void _Set_state(_In_ real_time_activity_subscription_state newState); + + /// The resource uri for the request. + _XSAPIIMP const string_t& resource_uri() const; + + /// The unique subscription id for the request. + _XSAPIIMP uint32_t subscription_id() const; + + virtual ~real_time_activity_subscription() {} + +protected: + void set_resource_uri(_In_ string_t uri); + void set_subscription_id(_In_ uint32_t id); + + // Callback for each subcription's initial message + virtual void on_subscription_created(_In_ uint32_t id, _In_ const web::json::value& data); + + // Callback for each subcription's coming events + virtual void on_event_received(_In_ const web::json::value& data); + + // Callback for each subcription's state change + virtual void on_state_changed(_In_ real_time_activity_subscription_state state); + + real_time_activity_subscription_state m_state; + string_t m_resourceUri; + uint32_t m_subscriptionId; + std::function m_subscriptionErrorHandler; + string_t m_guid; + + friend class real_time_activity_service; +}; + +class real_time_activity_subscription_error_event_args +{ +public: + /// + /// The subscription this refers to + /// + _XSAPIIMP const real_time_activity_subscription& subscription(); + + /// + /// The error returned by the operation. + /// + _XSAPIIMP const std::error_code& err(); + + /// + /// The error message + /// + _XSAPIIMP const std::string& err_message(); + + /// + /// Internal function + /// + real_time_activity_subscription_error_event_args( + real_time_activity_subscription subscription, + std::error_code errc, + std::string errMessage + ); + +private: + real_time_activity_subscription m_subscription; + std::error_code m_err; + std::string m_errorMessage; +}; + +/// +/// Represents a client side service that handles connections and communications with +/// the Xbox Live real-time activity service. +/// +class real_time_activity_service : public std::enable_shared_from_this +{ +public: + /// + /// Starts a background task that creates and initializes a websocket connection to the Xbox Live real-time activity service. + /// Its recommended that titles do not activate more than MAXIMUM_WEBSOCKETS_ACTIVATIONS_ALLOWED_PER_USER (5) per user per title instance. + /// Upon reaching the limit, titles will hit an assert during development that can be temporarily disabled via + /// xbox_live_context_settings::disable_asserts_for_maximum_number_of_websockets_activated(). + /// + _XSAPIIMP void activate(); + + /// + /// Cancels all existing subscriptions to the Xbox Live real-time activity service, + /// unhooks from the websocket connection, and stops the background task. + /// + _XSAPIIMP void deactivate(); + + /// + /// Registers a handler function to recieve a notification that is sent when the client service + /// loses or gains connectivity to the real time activity service. + /// Event handlers recieve a real_time_activity_connection_state object. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_connection_state_change_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for real time activity connectivity state changes. + /// + /// The function_context object that was returned when the event handler was registered. + _XSAPIIMP void remove_connection_state_change_handler(_In_ function_context remove); + + /// + /// Registers a handler function to recieve a notification that is sent when there is an + /// error in the real time activity service. + /// Event handlers recieve a real_time_activity_subscription_error_event_args& object. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_subscription_error_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for real time activity error notifications. + /// + /// The function_context object that was returned when the event handler was registered. + _XSAPIIMP void remove_subscription_error_handler(_In_ function_context remove); + + /// + /// Registers a handler function to recieve a notification that is sent when there is a + /// resync message from the real time activity serivce. + /// This message indicates that data may have been lost and to resync all data by calling + /// corresponding REST API's + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_resync_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for real time activity resync notifications. + /// + /// The function_context object that was returned when the event handler was registered. + _XSAPIIMP void remove_resync_handler(_In_ function_context remove); + + /// + /// Internal function + /// + void _Trigger_subscription_error( + real_time_activity_subscription_error_event_args args + ); + + /// + /// Internal function + /// + ~real_time_activity_service(); + + /// + /// Internal function + /// + real_time_activity_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + /// + /// Internal function + /// Add a subscription to real_time_activity_service to manage. + /// + xbox_live_result _Add_subscription( + _In_ std::shared_ptr subscription + ); + + /// + /// Internal function + /// Remove a subscription from real_time_activity_service. + /// + xbox_live_result _Remove_subscription( + _In_ std::shared_ptr subscription + ); + + std::shared_ptr _Xbox_live_context_settings() { return m_xboxLiveContextSettings; } + + /// + /// Internal function + /// Remove total count of subscription + /// + inline size_t _Subscription_Count() + { + return m_pendingSubmission.size() + m_pendingResponseSubscriptions.size() + m_subscriptions.size() + m_pendingUnsubscriptions.size(); + } + + /// + /// Internal function + /// + static std::unordered_map _Rta_activation_map(); + + /// + /// Internal function + /// + static std::unordered_map _Rta_manager_activation_map(); + +private: + std::unordered_map> m_connectionStateChangeHandler; + std::unordered_map> m_subscriptionErrorHandler; + std::unordered_map> m_resyncHandler; + + void _Close_websocket(); + + void complete_subscribe( + _In_ web::json::value& message + ); + + void complete_unsubscribe( + _In_ web::json::value& message + ); + + void handle_change_event( + _In_ web::json::value& message + ); + + void trigger_resync_event(); + void trigger_connection_state_changed_event(_In_ real_time_activity_connection_state connectionState); + + void submit_subscriptions(); + + std::error_code convert_rta_error_code_to_xbox_live_error_code(_In_ int32_t rtaErrorCode); + + void clear_all_subscriptions(); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + // web socket events callbacks + void on_socket_message_received(_In_ const string_t& message); + void on_socket_closed(_In_ web::websockets::client::websocket_close_status closeStatus, _In_ string_t closeReason); + void on_socket_connection_state_change(_In_ web_socket_connection_state oldState, _In_ web_socket_connection_state newState); + + volatile long m_sequenceNumber; + + std::vector> m_pendingSubmission; + std::map> m_pendingResponseSubscriptions; + std::map> m_subscriptions; + std::map> m_pendingUnsubscriptions; + std::recursive_mutex m_lock; + + real_time_activity_connection_state m_connectionState; + std::shared_ptr m_webSocketConnection; + +#if UWP_API || TV_API + Windows::Foundation::EventRegistrationToken m_rtaShutdownToken; +#endif + + function_context m_connectionStateChangeHandlerCounter; + function_context m_subscriptionErrorHandlerCounter; + function_context m_resyncHandlerCounter; + + friend xbox_live_context_impl; + friend real_time_activity_service_factory; +}; + +}}} diff --git a/Include/xsapi/service_call_logging_config.h b/Include/xsapi/service_call_logging_config.h new file mode 100644 index 00000000..3212dfb6 --- /dev/null +++ b/Include/xsapi/service_call_logging_config.h @@ -0,0 +1,55 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { + class xbox_live_context_impl; + +class service_call_logging_config +{ +public: + + /// + /// Gets the service_call_logger singleton instance + /// + _XSAPIIMP static std::shared_ptr get_singleton_instance(); + + /// + /// Enables the tracking of service calls + /// + _XSAPIIMP void enable(); + + /// + /// Disables the tracking of service calls + /// + _XSAPIIMP void disable(); + +#if TV_API || UWP_API || UNIT_TEST_SERVICES + /// + /// Internal API + /// Enables Logs to be enabled/disabled through protocal activation + /// + void _Register_for_protocol_activation(); +#endif + + /// + /// Internal API + /// + void _ReadLocalConfig(); + +private: + + service_call_logging_config(); + service_call_logging_config(const service_call_logging_config&); + void operator=(const service_call_logging_config&); + friend xbox_live_context_impl; +}; + +}} \ No newline at end of file diff --git a/Include/xsapi/services.h b/Include/xsapi/services.h new file mode 100644 index 00000000..9e9c86f7 --- /dev/null +++ b/Include/xsapi/services.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#pragma warning(disable: 4265) +#pragma warning(disable: 4266) +#pragma warning(disable: 4062) + +#include +#include "xsapi/types.h" +#include "xsapi/errors.h" +#include "xsapi/xbox_live_context_settings.h" +#include "xsapi/system.h" +#include "xsapi/profile.h" +#include "xsapi/social.h" +#include "xsapi/achievements.h" +#include "xsapi/leaderboard.h" +#include "xsapi/user_statistics.h" +#include "xsapi/multiplayer.h" +#include "xsapi/matchmaking.h" +#include "xsapi/real_time_activity.h" +#include "xsapi/presence.h" +#include "xsapi/game_server_platform.h" +#include "xsapi/title_storage.h" +#include "xsapi/contextual_search_service.h" +#include "xsapi/privacy.h" +#include "xsapi/marketplace.h" +#include "xsapi/events.h" +#include "xsapi/title_callable_ui.h" +#include "xsapi/xbox_live_context.h" +#include "xsapi/http_call.h" +#include "xsapi/social_manager.h" +#include "xsapi/multiplayer_manager.h" +#include "xsapi/service_call_logging_config.h" +#include "xsapi/entertainment_profile.h" + +#ifdef U + #undef U // clean up cpprest's global define in case it's used by app +#endif diff --git a/Include/xsapi/social.h b/Include/xsapi/social.h new file mode 100644 index 00000000..96a5ef1e --- /dev/null +++ b/Include/xsapi/social.h @@ -0,0 +1,653 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/real_time_activity.h" +#include "xsapi/multiplayer.h" +#include "xsapi/system.h" + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that let you retrieve + /// information about player reputation and relationship with + /// other players from Xbox Live. + /// + namespace social { + +class social_service_impl; + +enum class xbox_social_relationship_filter +{ + /// All the people on the user's people list. + all, + + /// Filters to only the people on the user's people list that have the attribute "Favorite" associated with them. + favorite, + + /// Filters to only the people on the user's people list that are also legacy Xbox Live friends. + legacy_xbox_live_friends +}; +/// +/// Defines values used to identify the type of reputation feedback. +/// +enum class reputation_feedback_type +{ + /// + /// Titles that are able to automatically determine that a user kills a teammate + /// may send this feedback without user intervention. + /// + fair_play_kills_teammates, + + /// + /// Titles that are able to automatically determine that a user is cheating + /// may send this feedback without user intervention. + /// + fair_play_cheater, + + /// + /// Titles that are able to automatically determine that a user has tampered with on-disk content + /// may send this feedback without user intervention. + /// + fair_play_tampering, + + /// + /// Titles that are able to automatically determine that a user quit a game early + /// may send this feedback without user intervention. + /// + fair_play_quitter, + + /// + /// When a user is voted out of a game (kicked), titles + /// may send this feedback without user intervention. + /// + fair_play_kicked, + + /// + /// Titles that allow users to report inappropriate video communications + /// may send this feedback. + /// + communications_inappropiate_video, + + /// + /// Titles that allow users to report inappropriate voice communications + /// may send this feedback. + /// + communications_abusive_voice, + + /// + /// Titles that allow users to report inappropriate user generated content + /// may send this feedback. + /// + inappropiate_user_generated_content, + + /// + /// Titles that allow users to vote on a most valuable player at the end of a multiplayer session + /// may send this feedback. + /// + positive_skilled_player, + + /// + /// Titles that allow users to submit positive feedback on helpful fellow players + /// may send this feedback. + /// + positive_helpful_player, + + /// + /// Titles that allow users to submit positive feedback on shared user generated content + /// may send this feedback. + /// + positive_high_quality_user_generated_content, + + /// + /// Titles that allow users to report phishing message may send this feedback. + /// + comms_phishing, + + /// + /// Titles that allow users to report communication based on a picture may send this feedback. + /// + comms_picture_message, + + /// + /// Titles that allow users to report spam messages may send this feedback. + /// + comms_spam, + + /// + /// Titles that allow users to report text messages may send this feedback. + /// + comms_text_message, + + /// + /// Titles that allow users to report voice messages may send this feedback. + /// + comms_voice_message, + + /// + /// Titles that allow users to report voice messages may send this feedback. + /// + fair_play_console_ban_request, + + /// + /// Titles that allow users to report if determine if a user stands idle on purpose in a game, usually round after round, may send this feedback. + /// + fair_play_idler, + + /// + /// Titles that report a recommendation to ban a user from Xbox Live may send this feedback. + /// + fair_play_user_ban_request, + + /// + /// Titles that allow users to report inappropriate gamer picture may send this feedback. + /// + user_content_gamerpic, + + /// + /// Titles that allow users to report inappropriate biography and other personal information may send this feedback. + /// + user_content_personalinfo, + + /// + /// Titles that allow users to report unsporting behavior may send this feedback. + /// + fair_play_unsporting, + + /// + /// Titles that allow users to report leaderboard cheating may send this feedback. + /// + fair_play_leaderboard_cheater +}; + +enum class social_notification_type +{ + /// + /// unknown + /// + unknown, + + /// + /// User(s) were added. + /// + added, + + /// + /// User(s) data changed. + /// + changed, + + /// + /// User(s) were removed. + /// + removed +}; + +class social_group_constants +{ +public: + /// + /// Returns Favorites constant string + /// + static const string_t favorite() { return _T("Favorites"); } + + /// + /// Returns People constant string + /// + static const string_t people() { return _T("People"); } +}; + +class xbox_social_relationship +{ +public: + /// + /// Represents the relationship between the user and another Xbox user. + /// + xbox_social_relationship(); + + xbox_social_relationship( + _In_ string_t xboxUserId, + _In_ bool isFavorite, + _In_ bool isFollowingCaller, + _In_ std::vector socialNetworks + ); + + /// + /// The person's Xbox user identifier. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Indicates whether the person is one that the user cares about more. + /// Users can have a very large number of people in their people list, + /// favorite people should be prioritized first in experiences and shown before others that are not favorites. + /// + _XSAPIIMP bool is_favorite() const; + + /// + /// Indicates whether the person is following the person that requested the information. + /// + _XSAPIIMP bool is_following_caller() const; + + /// + /// A collection of strings indicating which social networks this person has a relationship with. + /// + _XSAPIIMP const std::vector< string_t >& social_networks() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_xboxUserId; + bool m_isFavorite; + bool m_isFollowingCaller; + std::vector m_socialNetworks; +}; + +/// +/// Services that manage user relationship. +/// +class xbox_social_relationship_result +{ + // Example: + // { + // "people": [ + // { + // "xuid": "2603643534573573", + // "isFavorite": true, + // "isFollowingCaller": true, + // "socialNetworks": ["MyNetwork1", "MyNetwork2"] + // }, + // { + // "xuid": "2603643534573572", + // "isFavorite": true, + // "isFollowingCaller": false, + // "socialNetworks": ["MyNetwork1"] + // }, + // { + // "xuid": "2603643534573577", + // "isFavorite": false + // "isFollowingCaller": false + // }, + // ], + // "totalCount": 3 + // } + +public: + /// + /// Internal function + /// + xbox_social_relationship_result(); + + /// + /// Internal function + /// + xbox_social_relationship_result( + _In_ std::vector< xbox_social_relationship > socialRelationships, + _In_ uint32_t totalCount + ); + + /// + /// Collection of XboxSocialRelationship objects returned by a request. + /// + _XSAPIIMP const std::vector< xbox_social_relationship >& items() const; + + /// + /// The total number of XboxSocialRelationship objects that can be requested. + /// + _XSAPIIMP uint32_t total_count() const; + + /// + /// Returns a boolean value that indicates if there are more pages of social relationships to retrieve. + /// + /// True if there are more pages, otherwise false. + _XSAPIIMP bool has_next(); + + /// + /// Returns an XboxSocialRelationshipResult object containing the next page. + /// + /// The maximum number of items the response can contain. Pass 0 to attempt + /// retrieving all items. + /// Returns an XboxSocialRelationshipResult object. + /// Calls V1 GET /users/{ownerId}/people + _XSAPIIMP pplx::task> get_next( + _In_ uint32_t maxItems + ); + + /// + /// Internal function + /// + void _Init_next_page_info( + _In_ std::shared_ptr socialImpl, + _In_ xbox_social_relationship_filter filter, + _In_ uint32_t continuationSkip + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::shared_ptr m_socialImpl; + + std::vector< xbox_social_relationship > m_socialRelationships; + uint32_t m_totalCount; + xbox_social_relationship_filter m_filter; + uint32_t m_continuationSkip; +}; + +class social_relationship_change_event_args +{ +public: + /// + /// The Xbox user ID for the user who's social graph changes are being listed for. + /// + _XSAPIIMP const string_t& caller_xbox_user_id() const; + + /// + /// The type of notification change. + /// + _XSAPIIMP social_notification_type social_notification() const; + + /// + /// The Xbox user ids who the event is for + /// + _XSAPIIMP const std::vector& xbox_user_ids() const; + + /// + /// Internal function + /// + social_relationship_change_event_args(); + + /// + /// Internal function + /// + social_relationship_change_event_args( + _In_ string_t callerXboxUserId, + _In_ social_notification_type notificationType, + _In_ std::vector xboxUserIds + ); + +private: + string_t m_callerXboxUserId; + social_notification_type m_notificationType; + std::vector m_xboxUserIds; +}; + +class social_relationship_change_subscription : public xbox::services::real_time_activity::real_time_activity_subscription +{ +public: + /// + /// The Xbox user ID. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// Internal function + /// + social_relationship_change_subscription( + _In_ string_t xboxUserId, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ); + +protected: + void on_subscription_created(_In_ uint32_t id, _In_ const web::json::value& data) override; + + void on_event_received(_In_ const web::json::value& data) override; + +private: + social_notification_type convert_string_type_to_notification_type( + _In_ const string_t& notificationType + ) const; + + string_t m_xboxUserId; + std::function m_handler; +}; + +/// +/// Services that manage user relationship. +/// +class social_service +{ +public: + /// + /// Returns a XboxSocialRelationshipResult containing a the list of people that the user is connected to. + /// Defaults to filtering to PersonView.All. + /// Defaults to startIndex and maxItems of 0 to return entire list if possible. + /// + /// An XboxSocialRelationshipResult object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + _XSAPIIMP pplx::task> get_social_relationships(); + + /// + /// Returns a xbox_social_relationship_result containing a the list of people that the user is connected to. + /// + /// Controls how the list is filtered. + /// An xbox_social_relationship_result object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + _XSAPIIMP pplx::task> get_social_relationships( + _In_ xbox_social_relationship_filter socialRelationshipFilter + ); + + /// + /// Returns a xbox_social_relationship_result containing a the list of people that the user is connected to. + /// + /// The Xbox User Id to get the social relationships for. + /// An xbox_social_relationship_result object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + _XSAPIIMP pplx::task> get_social_relationships( + _In_ const string_t& xboxUserId + ); + + /// + /// Returns a xbox_social_relationship_result containing a the list of people that the user is connected to. + /// + /// Controls how the list is filtered. + /// Controls the starting index to return. + /// Controls the number of xbox_social_relationship_result objects to get. 0 will return as many as possible + /// An xbox_social_relationship_result object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + _XSAPIIMP pplx::task> get_social_relationships( + _In_ xbox_social_relationship_filter socialRelationshipFilter, + _In_ uint32_t startIndex, + _In_ uint32_t maxItems + ); + + /// + /// Subscribes to the social service for people changed events + /// + /// The Xbox User ID of the player requesting the subscription. + /// + /// You can register an event handler for social relationship changes by calling set_social_changed_handler(). + /// + _XSAPIIMP xbox_live_result> subscribe_to_social_relationship_change( + _In_ const string_t& xboxUserId + ); + + /// + /// Unsubscribes a previously created social relationship change subscription. + /// + /// The subscription object to unsubscribe + _XSAPIIMP xbox_live_result unsubscribe_from_social_relationship_change( + _In_ std::shared_ptr subscription + ); + + /// + /// Registers an event handler for social relationship change notifications. + /// Event handlers receive social_relationship_change_event_args. + /// + /// The callback function that recieves notifications. + _XSAPIIMP function_context add_social_relationship_changed_handler( + _In_ std::function handler + ); + + /// + /// Removes a social relationship change handler + /// + /// The handler to remove. + _XSAPIIMP void remove_social_relationship_changed_handler( + _In_ function_context context + ); + + std::shared_ptr _Xbox_live_context_settings() { return m_xboxLiveContextSettings; } + +private: + social_service() {}; + + social_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivityService + ); + + pplx::task> get_social_relationships( + _In_ const string_t& xboxUserId, + _In_ xbox_social_relationship_filter socialRelationshipFilter, + _In_ uint32_t startIndex, + _In_ uint32_t maxItems + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_socialServiceImpl; + + friend xbox_live_context_impl; + friend xbox_social_relationship_result; +}; + +/// +/// Represents the parameters for submitting reputation feedback on a user +/// +class reputation_feedback_item +{ +public: + /// + /// Internal function + /// + reputation_feedback_item(); + + /// + /// Construct a reputation_feedback_item object + /// + /// The Xbox User ID of the user that reputation feedback is being submitted on. + /// The reputation feedback type being submitted. + /// The session reference of the multiplayer session directory session the user is sending feedback from. (Optional) + /// User supplied text added to explain the reason for the feedback. (Optional) + /// The Id of a resource that can be used as evidence for the feedback. Example: the Id of a video file. (Optional) + reputation_feedback_item( + _In_ string_t xboxUserId, + _In_ reputation_feedback_type reputationFeedbackType, + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef = xbox::services::multiplayer::multiplayer_session_reference(), + _In_ string_t reasonMessage = string_t(), + _In_ string_t evidenceResourceId = string_t() + ); + + /// + /// The Xbox User ID of the user that reputation feedback is being submitted on. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The reputation feedback type being submitted. + /// + _XSAPIIMP reputation_feedback_type feedback_type() const; + + /// + /// The reference to the multiplayer session directory session the user is sending feedback from. + /// + _XSAPIIMP const xbox::services::multiplayer::multiplayer_session_reference& session_reference() const; + + /// + /// User supplied text added to explain the reason for the feedback. + /// + _XSAPIIMP const string_t& reason_message() const; + + /// + /// The Id of a resource that can be used as evidence for the feedback. Example: the Id of a video file. + /// + _XSAPIIMP const string_t& evidence_resource_id() const; + +private: + string_t m_xboxUserId; + reputation_feedback_type m_reputationFeedbackType; + xbox::services::multiplayer::multiplayer_session_reference m_sessionRef; + string_t m_reasonMessage; + string_t m_evidenceResourceId; +}; + + +/// +/// Manages the reputation service. +/// +class reputation_service +{ +public: + /// + /// Submits reputation feedback on the specified user. + /// + /// The Xbox User ID of the user that reputation feedback is being submitted on. + /// The reputation feedback type being submitted. + /// The name of the multiplayer session directory session the user is sending feedback from. (Optional) + /// User supplied text added to explain the reason for the feedback. (Optional) + /// The Id of a resource that can be used as evidence for the feedback. Example: the Id of a video file. (Optional) + /// The async object for notifying when the operation has been completed. + /// Calls V100 POST /users/xuid({xuid})/feedback + _XSAPIIMP pplx::task> submit_reputation_feedback( + _In_ const string_t& xboxUserId, + _In_ reputation_feedback_type reputationFeedbackType, + _In_ const string_t& sessionName = string_t(), + _In_ const string_t& reasonMessage = string_t(), + _In_ const string_t& evidenceResourceId = string_t() + ); + + /// + /// Submits batch reputation feedback on the specified users. + /// + /// A vector of reputation_feedback_item objects to submit reputation feedback on. + /// The async object for notifying when the operation has been completed. + /// Calls V101 POST /users/batchfeedback + _XSAPIIMP pplx::task> submit_batch_reputation_feedback( + _In_ const std::vector< reputation_feedback_item >& feedbackItems + ); + +private: + reputation_service() {}; + + reputation_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + string_t reputation_feedback_subpath( + _In_ const string_t& xboxUserId + ); + + string_t reputation_history_subpath( + _In_ const string_t& xboxUserId + ); + + string_t reputation_history_subpath( + _In_ const string_t& xboxUserId, + _In_ uint32_t days + ); + + friend xbox_live_context_impl; +}; + +}}} diff --git a/Include/xsapi/social_manager.h b/Include/xsapi/social_manager.h new file mode 100644 index 00000000..221a4830 --- /dev/null +++ b/Include/xsapi/social_manager.h @@ -0,0 +1,928 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/presence.h" + +#if !XSAPI_CPP & !TV_API +#include "User_WinRT.h" +#endif +#include "xsapi/mem.h" + +namespace xbox { namespace services { + namespace system { + class xbox_live_user; + } +}} + +#if TV_API | XBOX_UWP +typedef Windows::Xbox::System::User^ xbox_live_user_t; +#else +typedef std::shared_ptr xbox_live_user_t; +#endif + +namespace xbox { + namespace services { + + namespace social { + /// + /// Contains classes and enumerations for more easily managing social + /// scenarios. + /// + namespace manager { + +class social_graph; +struct xbox_social_user_context; +struct user_group_status_change; +enum class change_list_enum; + +static const uint32_t GAMERSCORE_CHAR_SIZE = 16; +static const uint32_t GAMERTAG_CHAR_SIZE = 16; +static const uint32_t XBOX_USER_ID_CHAR_SIZE = 17; +static const uint32_t DISPLAY_NAME_CHAR_SIZE = 30; +static const uint32_t REAL_NAME_CHAR_SIZE = 255; +static const uint32_t DISPLAY_PIC_URL_RAW_CHAR_SIZE = 225; +static const uint32_t COLOR_CHAR_SIZE = 7; +static const uint32_t RICH_PRESENCE_CHAR_SIZE = 100; +static const uint32_t NUM_PRESENCE_RECORDS = 6; + +static const uint32_t MAX_USERS_FROM_LIST = 100; +/// +/// Detail level controls how much information is exposed in each xbox_live_social_graph_user +/// Detail level can only be set on construction of social_manager +/// +enum class social_manager_extra_detail_level +{ + /// Only get default PeopleHub information (presence, profile) + no_extra_detail, + + /// Add extra detail for the title history for the users + title_history_level = 0x1, + + /// Add extra detail for the preferred color for the users + preferred_color_level = 0x2 +}; + +social_manager_extra_detail_level inline operator&(_In_ social_manager_extra_detail_level lhs, _In_ social_manager_extra_detail_level rhs) +{ + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +social_manager_extra_detail_level inline operator|(_In_ social_manager_extra_detail_level lhs, _In_ social_manager_extra_detail_level rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +/// +/// The filter level of information +/// Title will only show users associated with a particular title +/// +enum class presence_filter +{ + /// Unknown + unknown, + + /// Is currently playing current title and is online + title_online, + + /// Has played this title and is offline + title_offline, + + /// Everyone currently online + all_online, + + /// Everyone currently offline + all_offline, + + /// Everyone who has played or is playing the title + all_title, + + /// Everyone + all +}; + +/// +/// The types of possible events +/// +enum class social_event_type +{ + /// Users added to social graph + users_added_to_social_graph, + + /// Users removed from social graph + users_removed_from_social_graph, + + /// Users presence record has changed + presence_changed, + + /// Users profile information has changed + profiles_changed, + + /// Relationship to users has changed + social_relationships_changed, + + /// Social graph load complete from adding a local user + local_user_added, + + /// Social graph removal complete + local_user_removed, + + /// Xbox Social User Group load complete (will only trigger for views that take a list of users) + social_user_group_loaded, + + /// Social user group updated + social_user_group_updated, + + /// unknown. + unknown +}; + +/// +/// Possible relationship types to filter by +/// +enum class relationship_filter +{ + /// Friends of the user (user is following) + friends, + + /// Favorites of the user + favorite +}; + +/// +/// Identifies type of social user group created +/// +enum class social_user_group_type +{ + /// Social user group based off of filters + filter_type, + + /// Social user group based off of list of users + user_list_type +}; + +/// +/// Data about whether the user has played the title +/// +class title_history +{ +public: + /// + /// Whether the user has played this title + /// + _XSAPIIMP bool has_user_played() const; + + /// + /// The last time the user had played + /// + _XSAPIIMP const utility::datetime& last_time_user_played() const; + + /// + /// Internal function + /// + title_history(); + + /// + /// Internal function + /// + bool operator!= ( + _In_ const title_history& previousTitleHistory + ) const; + + /// + /// Internal function + /// + static xbox::services::xbox_live_result _Deserialize( + _In_ const web::json::value& json, + _In_ std::error_code& errcOut + ); + +private: + bool m_userHasPlayed; + uint32_t m_titleId; + utility::datetime m_lastTimeUserPlayed; +}; + +/// +/// Preferred color for the user. Set via the shell. +/// +class preferred_color +{ +public: + /// + /// Users primary color + /// + _XSAPIIMP const char_t* primary_color() const; + + /// + /// Users secondary color + /// + _XSAPIIMP const char_t* secondary_color() const; + + /// + /// Users tertiary color + /// + _XSAPIIMP const char_t* tertiary_color() const; + + /// + /// Does a comparison on if preferred colors are equal + /// + _XSAPIIMP bool operator!=(const preferred_color& rhs) const; + + /// + /// Internal function + /// + preferred_color(); + + /// + /// Internal function + /// + static xbox::services::xbox_live_result _Deserialize( + _In_ const web::json::value& json, + _In_ std::error_code& errcOut + ); + +private: + char_t m_primaryColor[COLOR_CHAR_SIZE]; + char_t m_secondaryColor[COLOR_CHAR_SIZE]; + char_t m_tertiaryColor[COLOR_CHAR_SIZE]; +}; + +/// +/// Social manager version of the presence title record +/// Gives information about different titles presence information +/// +class social_manager_presence_title_record +{ +public: + /// + /// The title ID. + /// + _XSAPIIMP uint32_t title_id() const; + + /// + /// The active state for the title. + /// + _XSAPIIMP bool is_title_active() const; + + /// + /// The formatted and localized presence string. + /// + _XSAPIIMP const char_t* presence_text() const; + + /// + /// The active state for the title. + /// + _XSAPIIMP bool is_broadcasting() const; + + /// + /// Device type + /// + _XSAPIIMP xbox::services::presence::presence_device_type device_type() const; + + /// + /// Internal function + /// + social_manager_presence_title_record(); + + /// + /// Internal function + /// + social_manager_presence_title_record(_In_ const xbox::services::presence::presence_title_record& presenceTitleRecord, _In_ xbox::services::presence::presence_device_type deviceType); + + /// + /// internal function + /// + bool _Is_null() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + bool m_isTitleActive; + bool m_isBroadcasting; + bool m_isNull; + xbox::services::presence::presence_device_type m_deviceType; + uint32_t m_titleId; + char_t m_presenceText[RICH_PRESENCE_CHAR_SIZE]; +}; + +/// +/// Social manager presence record. Shows information on users current presence status and stores title records +/// +class social_manager_presence_record +{ +public: + /// + /// The user's presence state. + /// + _XSAPIIMP xbox::services::presence::user_presence_state user_state() const; + + /// + /// Collection of presence title record objects returned by a request. + /// + _XSAPIIMP const std::vector presence_title_records() const; + + /// + /// Returns whether the user is playing this title id + /// + _XSAPIIMP bool is_user_playing_title(_In_ uint32_t titleId) const; + + /// + /// Internal function + /// + uint64_t _Xbox_user_id() const; + + /// + /// Internal function + /// + social_manager_presence_record(); + + /// + /// Internal function + /// + social_manager_presence_record(_In_ const xbox::services::presence::presence_record& presenceRecord); + + /// + /// Internal function + /// + void _Update_device( + _In_ xbox::services::presence::presence_device_type deviceType, + _In_ bool isUserLoggedIn + ); + + /// + /// Internal function + /// + void _Remove_title( + _In_ uint32_t titleId + ); + + /// + /// Internal function + /// + bool _Compare(_In_ const social_manager_presence_record& presenceRecord); + + /// + /// Internal function + /// + void _Set_xbox_user_id(_In_ uint64_t xboxUserId); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize( + _In_ const web::json::value& json, + _Inout_ std::error_code& errc + ); + +private: + xbox::services::presence::user_presence_state m_userState; + uint64_t m_xboxUserId; + social_manager_presence_title_record m_presenceVec[NUM_PRESENCE_RECORDS]; + + friend class user_buffers_holder; +}; + +/// +/// Xbox Social User that contains profile, presence, preferred color, and title history data +/// +class xbox_social_user +{ +public: + /// + /// The xbox user id + /// + _XSAPIIMP const char_t* xbox_user_id() const; + + /// + /// Whether they are a favorite + /// + _XSAPIIMP bool is_favorite() const; + + /// + /// Whether the calling user is following them + /// + _XSAPIIMP bool is_following_user() const; + + /// + /// Whether they calling user is followed by this person + /// + _XSAPIIMP bool is_followed_by_caller() const; + + /// + /// The display name + /// + _XSAPIIMP const char_t* display_name() const; + + /// + /// The real name + /// + _XSAPIIMP const char_t* real_name() const; + + /// + /// The display pic uri + /// + _XSAPIIMP const char_t* display_pic_url_raw() const; + + /// + /// Whether to use the players avatar + /// + _XSAPIIMP bool use_avatar() const; + + /// + /// Players gamerscore + /// + _XSAPIIMP const char_t* gamerscore() const; + + /// + /// Players gamertag + /// + _XSAPIIMP const char_t* gamertag() const; + + /// + /// Users presence record + /// + _XSAPIIMP const xbox::services::social::manager::social_manager_presence_record& presence_record() const; + + /// + /// Title history for the user + /// + _XSAPIIMP const xbox::services::social::manager::title_history& title_history() const; + + /// + /// Preferred color for the user + /// + _XSAPIIMP const preferred_color& preferred_color() const; + + xbox_social_user(); + + /// + /// Internal function + /// + uint64_t _Xbox_user_id_as_integer() const; + + /// + /// Internal function + /// + void _Set_presence_record(_In_ const xbox::services::social::manager::social_manager_presence_record& presenceRecord); + + /// + /// Internal function + /// + void _Set_is_followed_by_caller(_In_ bool isFollowed); + + /// + /// Internal function + /// + static change_list_enum _Compare(_In_ const xbox_social_user& previous, _In_ const xbox_social_user& current); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + bool m_isFavorite; + bool m_isFollowingCaller; + bool m_isFollowedByCaller; + bool m_useAvatar; + uint64_t m_xboxUserIdAsInt; + char_t m_gamerscore[GAMERSCORE_CHAR_SIZE]; + char_t m_gamertag[GAMERTAG_CHAR_SIZE]; + char_t m_xboxUserId[XBOX_USER_ID_CHAR_SIZE]; + char_t m_displayName[DISPLAY_NAME_CHAR_SIZE]; + char_t m_realName[REAL_NAME_CHAR_SIZE]; + char_t m_displayPicUrlRaw[DISPLAY_PIC_URL_RAW_CHAR_SIZE]; + xbox::services::social::manager::title_history m_titleHistory; + xbox::services::social::manager::preferred_color m_preferredColor; + xbox::services::social::manager::social_manager_presence_record m_presenceRecord; + + friend class social_graph; + friend class user_buffers_holder; +}; + +/// +/// Base class for social event args +/// +class social_event_args +{ +public: + social_event_args() {} + virtual ~social_event_args() {} +}; + +/// +/// Contains an xbox user id for purposes of storing in stl data types +/// +class xbox_user_id_container +{ +public: + /// + /// A users xbox user id + /// + const char_t* xbox_user_id() const; + + /// + /// Internal function + /// + xbox_user_id_container(); + + /// + /// Internal function + /// + xbox_user_id_container(const char_t* xboxUserId); + +private: + char_t m_xboxUserId[XBOX_USER_ID_CHAR_SIZE]; +}; + +/// +/// An event that something in the social graph has changed +/// +class social_event +{ +public: + /// + /// The user whose graph got changed + /// + _XSAPIIMP xbox_live_user_t user() const; + + /// + /// The type of event this is + /// Tells the caller what to cast the event_args to + /// + _XSAPIIMP social_event_type event_type() const; + + /// + /// List of users this event affects + /// + _XSAPIIMP const std::vector& users_affected() const; + + /// + /// The social event args + /// + _XSAPIIMP const std::shared_ptr& event_args() const; + + /// + /// Error that occurred + /// + _XSAPIIMP const std::error_code& err() const; + + /// + /// Error message + /// + _XSAPIIMP const std::string& err_message() const; + + /// + /// Internal function + /// + social_event(); + + /// + /// Internal function + /// + social_event( + _In_ xbox_live_user_t user, + _In_ social_event_type eventType, + _In_ std::vector usersAffected, + _In_ std::shared_ptr socialEventArgs = nullptr, + _In_ std::error_code errCode = xbox_live_error_code::no_error, + _In_ std::string errMessage = std::string() + ); + +#if defined(XSAPI_CPPWINRT) + _XSAPIIMP const winrt::Windows::Xbox::System::User& user_cppwinrt() + { + return convert_user_to_cppwinrt(user()); + } +#endif + +private: + social_event_type m_eventType; + std::error_code m_errCode; + xbox_live_user_t m_user; + std::shared_ptr m_eventArgs; + std::vector m_usersAffected; + std::string m_errMessage; +}; + +/// +/// Internal structure +/// +struct xbox_removal_struct +{ + uint64_t xuidNum; + xbox_user_id_container xuidContainer; +}; + +/// +/// A subset snapshot of the users social graph +/// +class xbox_social_user_group +{ +public: + /// + /// Gets an up to date list of users from the social graph + /// The returned value remains valid until the next call to do_work + /// + _XSAPIIMP const std::vector& users(); + + /// + /// Returns copied group of users from social user group + /// + /// Vector of social users to populate + /// An xbox_live_result representing the success of copying the users + _XSAPIIMP xbox_live_result get_copy_of_users( + _Inout_ std::vector& socialUserVector + ); + + /// + /// Type of social user group + /// + _XSAPIIMP social_user_group_type social_user_group_type(); + + /// + /// Users who are contained in this user group currently + /// For list this is static, for filter this is dynamic and will change on do_work + /// + _XSAPIIMP const std::vector& users_tracked_by_social_user_group(); + + /// + /// The local user who the user group is related to + /// + _XSAPIIMP const xbox_live_user_t& local_user(); + + /// + /// Returns the presence filter used if group type is filter type + /// + _XSAPIIMP presence_filter presence_filter_of_group() { return m_presenceFilter; } + + /// + /// Returns the relationship filter used if group type is filter type + /// + _XSAPIIMP relationship_filter relationship_filter_of_group() { return m_relationshipFilter; } + + /// + /// Returns users from xuids. Pointers become invalidated by next do_work + /// + _XSAPIIMP std::vector get_users_from_xbox_user_ids(_In_ const std::vector& xboxUserIds); + + /// + /// Internal function + /// + xbox_social_user_group( + _In_ string_t viewHash, + _In_ presence_filter presenceFilter, + _In_ relationship_filter relationshipFilter, + _In_ uint32_t titleId, + _In_ xbox_live_user_t xboxLiveUser + ); + + /// + /// Internal function + /// + xbox_social_user_group( + _In_ string_t viewHash, + _In_ std::vector userList, + _In_ xbox_live_user_t xboxLiveUser + ); + +#if defined(XSAPI_CPPWINRT) + _XSAPIIMP const winrt::Windows::Xbox::System::User& local_user_cppwinrt() + { + return convert_user_to_cppwinrt(local_user()); + } +#endif +private: + void destroy(); + + const string_t& hash() const; + + const std::vector& tracking_users(); + + void update_view( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& snapshotList, + _In_ const std::vector& socialEvents + ); + + void initialize_filter_list( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& users + ); + + void filter_list( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& snapshotList, + _In_ const std::vector& socialEvents + ); + + bool get_presence_filter_result( + _In_ const xbox_social_user* user, + _In_ presence_filter presenceFilter + ) const; + + bool needs_update(); + + void remove_users(_In_ const std::vector& usersToRemove); + + user_group_status_change _Update_users_in_group(_In_ const std::vector& userList); + + bool m_needsUpdate; + xbox::services::social::manager::social_user_group_type m_userGroupType; + social_manager_extra_detail_level m_detailLevel; + presence_filter m_presenceFilter; + relationship_filter m_relationshipFilter; + uint32_t m_titleId; + xbox_live_user_t m_xboxLiveUser; + std::vector m_userUpdateListString; + std::vector m_userGroupVector; + std::vector m_userUpdateListInt; + string_t m_viewHash; + std::mutex m_groupMutex; + + friend class social_manager; +}; + +/// +/// Social user group args for when a social user group loads +/// +class social_user_group_loaded_event_args : public social_event_args +{ +public: + /// + /// The loaded social user group + /// + _XSAPIIMP const std::shared_ptr& social_user_group() const; + + /// + /// internal function + /// + social_user_group_loaded_event_args(_In_ std::shared_ptr socialUserGroup); + +private: + std::shared_ptr m_socialUserGroup; +}; + +/// +/// Social Manager that handles core logic +/// +class social_manager : public std::enable_shared_from_this +{ +public: + /// + /// Gets the social_manager singleton instance + /// + _XSAPIIMP static std::shared_ptr get_singleton_instance(); + + /// + /// Create a social graph for the specified local user + /// The result of a local user being added will be triggered through the local_user_added event in do_work + /// + /// Xbox Live User + /// The level of verbosity that should be in the xbox_social_user + /// An xbox_live_result to report any potential error + _XSAPIIMP virtual xbox_live_result add_local_user( + _In_ xbox_live_user_t user, + _In_ social_manager_extra_detail_level extraDetailLevel + ); + + /// + /// Removes a social graph for the specified local user + /// The result of a local user being added will be triggered through the local_user_removed event in do_work + /// + /// Xbox Live User + /// An xbox_live_result to report any potential error + _XSAPIIMP virtual xbox_live_result remove_local_user( + _In_ xbox_live_user_t user + ); + + /// + /// Called whenever the title wants to update the social graph and get list of change events + /// Must be called every frame for data to be up to date + /// + /// The list of what has changed in between social graph updates + _XSAPIIMP std::vector do_work(); + + /// + /// Constructs a social Xbox Social User Group, which is a collection of users with social information + /// The result of a user group being loaded will be triggered through the social_user_group_loaded event in do_work + /// + /// Xbox Live User + /// The restriction of users based on their presence and title activity + /// The restriction of users based on their relationship to the calling user + /// An xbox_live_result of the created Xbox Social User Group + _XSAPIIMP xbox_live_result> create_social_user_group_from_filters( + _In_ xbox_live_user_t user, + _In_ presence_filter presenceDetailLevel, + _In_ relationship_filter filter + ); + + /// + /// Constructs a social Xbox Social User Group, which is a collection of users with social information + /// The result of a user group being loaded will be triggered through the social_user_group_loaded event in do_work + /// + /// Xbox Live User + /// List of users to populate the Xbox Social User Group with. This is currently capped at 100 users total. + /// An xbox_live_result of the created Xbox Social User Group + _XSAPIIMP xbox_live_result> create_social_user_group_from_list( + _In_ xbox_live_user_t user, + _In_ std::vector xboxUserIdList + ); + + /// + /// Destroys a created social Xbox Social User Group + /// This will stop updating the Xbox Social User Group and remove tracking for any users the Xbox Social User Group holds + /// + /// The social Xbox Social User Group to destroy and stop tracking + /// An xbox_live_result to report any potential error + _XSAPIIMP xbox_live_result destroy_social_user_group( + _In_ std::shared_ptr socialUserGroup + ); + + /// + /// Returns all local users who have been added to the social manager + /// + _XSAPIIMP const std::vector& local_users() const; + + /// + /// Updates specified social user group to new group of users + /// Does a diff to see which users have been added or removed from + /// The result of a user group being updated will be triggered through the social_user_group_updated event in do_work + /// + /// The xbox social user group to add users to + /// List of users to add to the xbox social user group. Total number of users not in social graph is limited at 100. + /// An xbox_live_result representing the success of adding the users to the group + _XSAPIIMP xbox_live_result update_social_user_group( + _In_ const std::shared_ptr& group, + _In_ const std::vector& users + ); + + /// + /// Internal function + /// + void _Log_state(); + +#if defined(XSAPI_CPPWINRT) + _XSAPIIMP virtual xbox_live_result add_local_user( + _In_ const winrt::Windows::Xbox::System::User& user, + _In_ social_manager_extra_detail_level extraDetailLevel + ) + { + return add_local_user(convert_user_to_cppcx(user), extraDetailLevel); + } + + _XSAPIIMP virtual xbox_live_result remove_local_user( + _In_ const winrt::Windows::Xbox::System::User& user + ) + { + return remove_local_user(convert_user_to_cppcx(user)); + } + + _XSAPIIMP xbox_live_result> create_social_user_group_from_filters( + _In_ const winrt::Windows::Xbox::System::User& user, + _In_ presence_filter presenceDetailLevel, + _In_ relationship_filter filter + ) + { + return create_social_user_group_from_filters(convert_user_to_cppcx(user), presenceDetailLevel, filter); + } + + _XSAPIIMP xbox_live_result> create_social_user_group_from_list( + _In_ const winrt::Windows::Xbox::System::User& user, + _In_ std::vector xboxUserIdList + ) + { + return create_social_user_group_from_list(convert_user_to_cppcx(user), xboxUserIdList); + } + + _XSAPIIMP const std::vector& local_users_cppwinrt() const + { + return convert_user_vector_to_cppwinrt(local_users()); + } + +#endif + +protected: + + social_manager(); + + std::vector m_eventQueue; + std::vector m_localUserList; + xsapi_internal_unordered_map(string_t, std::shared_ptr) m_xboxSocialUserGroups; + xsapi_internal_unordered_map(string_t, xsapi_internal_vector(string_t)) m_userToViewMap; + xsapi_internal_unordered_map(string_t, std::shared_ptr) m_localGraphs; + std::mutex m_socialMangerLock; + std::mutex m_socialManagerEventLock; + + static std::shared_ptr m_socialManager; + friend class xbox_social_user_group; +}; + +}}}} \ No newline at end of file diff --git a/Include/xsapi/system.h b/Include/xsapi/system.h new file mode 100644 index 00000000..b4fd0cc8 --- /dev/null +++ b/Include/xsapi/system.h @@ -0,0 +1,718 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "types.h" +#include "errors.h" +#include "xbox_live_context_settings.h" +#include "xbox_live_app_config.h" + +#ifdef __OBJC__ +#import +#import "MSAAuthentication/MSAAccountManager.h" +#endif +#ifndef _WIN32 +#include "pplx/pplxtasks.h" +#endif + +namespace xbox { namespace services { + class http_call_impl; + class xbox_live_context_impl; + + namespace events { + class events_service; + } + namespace events { + class events_service; + } + + namespace multiplayer { namespace manager { + class multiplayer_client_manager; + class multiplayer_local_user; + }} +} } + +namespace xbox { namespace services { + /// + /// Configuration information for Xbox Live service objects. + /// + namespace system { + +// Forward declaration +class sign_out_completed_event_args; +class user_impl; +class user_factory; +class xbox_live_server_impl; +class auth_config; + +class xbox_live_services_settings : public std::enable_shared_from_this +{ +public: + /// + /// Gets the singleton instance + /// + _XSAPIIMP static std::shared_ptr get_singleton_instance(); + + /// + /// Used by titles to register memory allocation hooks that are used by XSAPI when it + /// needs to allocate a large block of memory such as SocialManager which uses a large block + /// of memory to keep track of the friends list. + /// + /// Note that not all memory that XSAPI uses goes through this allocator (for example std::string), + /// but these allocations are typically small and transient. + /// + /// The title's allocation function. Input is size of memory block that's being requested. Return is pointer to the allocated memory block + /// The title's memory free function. Input is address of memory to free + /// + /// If titles choose not to provide their own allocation hooks, these system default allocators will be used instead. + /// To unwire your hooks, call the same routine with nullptr passed in for both parameters. + /// It is important to provide an implementation for both memAllocHandler and memFreeHandler if you hook them; + /// hooking only one of them will be considered an error. + /// + _XSAPIIMP void set_memory_allocation_hooks( + _In_ const std::function<_Ret_maybenull_ _Post_writable_byte_size_(dwSize) void*(_In_ size_t dwSize)>& memAllocHandler, + _In_ const std::function& memFreeHandler + ); + + /// + /// Registers to recieve logging messages for levels that are enabled. Event handlers will receive the level, category, and content of the message. + /// + /// The event handler function to call. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_logging_handler(_In_ std::function handler); + + /// + /// Unregisters from recieving logging messages. + /// + /// The function_context object that was returned when the event handler was registered. + _XSAPIIMP void remove_logging_handler(_In_ function_context context); + + /// + /// Indicates the level of debug messages to send to the debugger's Output window. + /// + _XSAPIIMP xbox_services_diagnostics_trace_level diagnostics_trace_level() const; + + /// + /// Sets the level of debug messages to send to the debugger's Output window. + /// + _XSAPIIMP void set_diagnostics_trace_level(_In_ xbox_services_diagnostics_trace_level value); + + /// + /// Internal function + /// + void _Raise_logging_event(_In_ xbox_services_diagnostics_trace_level level, _In_ const std::string& category, _In_ const std::string& message); + + /// + /// Internal function + /// + bool _Is_at_diagnostics_trace_level(_In_ xbox_services_diagnostics_trace_level level); + +private: + xbox_live_services_settings(); + + std::function<_Ret_maybenull_ _Post_writable_byte_size_(dwSize) void*(_In_ size_t dwSize)> m_pMemAllocHook; + std::function m_pMemFreeHook; + + void set_log_level_from_diagnostics_trace_level(); + + xbox_services_diagnostics_trace_level m_traceLevel; + std::mutex m_loggingWriteLock; + std::unordered_map> m_loggingHandlers; + function_context m_loggingHandlersCounter; + + friend class xsapi_memory; +}; + +/// +/// Contains information about the authorization token and digital signature for an HTTP request by a user. +/// This class is returned as the result of a call to xbox_live_user.get_token_and_signature(). +/// +class token_and_signature_result +{ +public: + /// + /// Internal function + /// + token_and_signature_result(); + + /// + /// Internal function + /// + token_and_signature_result( + _In_ string_t token, + _In_ string_t signature, + _In_ string_t xuid, + _In_ string_t gamertag, + _In_ string_t userHash, + _In_ string_t ageGroup, + _In_ string_t privileges, + _In_ string_t webAccountId, + _In_ string_t reserved + ); + +#ifndef DEFAULT_MOVE_ENABLED + _XSAPIIMP token_and_signature_result(token_and_signature_result&& other); + _XSAPIIMP token_and_signature_result& operator=(token_and_signature_result&& other); +#endif + + /// + /// The authorization token for the HTTP request. + /// + _XSAPIIMP const string_t& token() const; + + /// + /// The digital signature for the HTTP request. + /// + _XSAPIIMP const string_t& signature() const; + + /// + /// The unique ID tied to the Xbox user's account. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The gamertag name associated with the Xbox user's account. + /// + _XSAPIIMP const string_t& gamertag() const; + + /// + /// The hashcode that identifies the user. This value is used for HTTP calls. + /// + _XSAPIIMP const string_t& xbox_user_hash() const; + + /// + /// Internal function + /// + _XSAPIIMP const string_t& reserved() const; + + /// + /// The age group + /// + _XSAPIIMP const string_t& age_group() const; + + /// + /// The privileges + /// + _XSAPIIMP const string_t& privileges() const; + + /// + /// The web account id + /// + _XSAPIIMP const string_t& web_account_id() const; + +private: + + string_t m_token; + string_t m_signature; + string_t m_xboxUserId; + string_t m_gamerTag; + string_t m_xboxUserHash; + string_t m_ageGroup; + string_t m_privileges; + string_t m_webAccountId; + string_t m_reserved; + +#if UWP_API +public: + token_and_signature_result( + Windows::Security::Authentication::Web::Core::WebTokenRequestResult^ tokenResult + ); + + Windows::Security::Authentication::Web::Core::WebTokenRequestResult^ token_request_result() const; + +private: + Windows::Security::Authentication::Web::Core::WebTokenRequestResult^ m_tokenResult; +#endif +}; + +#if (XSAPI_SERVER || UNIT_TEST_SYSTEM) +class xbox_live_server +{ +public: + _XSAPIIMP xbox_live_server(); + + _XSAPIIMP pplx::task> signin(_In_ cert_context cert); + + _XSAPIIMP pplx::task> + get_token_and_signature( + _In_ const string_t& httpMethod, + _In_ const string_t& url, + _In_ const string_t& headers + ); + + _XSAPIIMP pplx::task> + get_token_and_signature( + _In_ const string_t& httpMethod, + _In_ const string_t& url, + _In_ const string_t& headers, + _In_ const string_t& requestBodyString + ); + + _XSAPIIMP pplx::task> + get_token_and_signature_array( + _In_ const string_t& httpMethod, + _In_ const string_t& url, + _In_ const string_t& headers, + _In_ const std::vector& requestBodyArray + ); + + _XSAPIIMP bool is_signed_in() const; + +private: + std::shared_ptr m_server_impl; + + friend xbox::services::user_context; +}; + +#endif //#if XSAPI_SERVER + +#if !TV_API + +/// +/// Enumeration values that indicate the result status of sign in. +/// +enum sign_in_status +{ + /// + /// Signed in successfully. + /// + success = 0, + + /// + /// Need to invoke the signin API (w/ UX) to let the user take necessary actions for the sign-in operation to continue. + /// Can only be returned from signin_silently(). + /// + user_interaction_required, + + /// + /// The user decided to cancel the sign-in operation. + /// Can only be returned from signin(). + /// + user_cancel +}; + + +/// +/// Represents the result of the sign in operation. +/// +class sign_in_result +{ +public: + /// + /// Internal function + /// + sign_in_result() : + m_status(success) + {} + + /// + /// Internal function + /// + sign_in_result(_In_ sign_in_status status) : + m_status(status), + m_newAccount(false) + {} + + /// + /// Internal function + /// + sign_in_result(_In_ sign_in_status status, _In_ bool newAccount) : + m_status(status), + m_newAccount(newAccount) + {} + + /// + /// The status of sign in operation. + /// + _XSAPIIMP sign_in_status status() const { return m_status; } + +#ifdef XSAPI_U + /// + /// Tells if signed in to a new or existing account. + /// Only relevant when status() == sign_in_status::success. + /// + _XSAPIIMP bool is_new_account() const { return m_newAccount; } +#endif + +private: + sign_in_status m_status; + bool m_newAccount; +}; + +/// +/// Represents a player that is associated with a device or a controller. +/// +class xbox_live_user : public std::enable_shared_from_this +{ +public: +#if XSAPI_SERVER + _XSAPIIMP pplx::task> signin( + _In_ std::shared_ptr server, + _In_ const string_t& user_delegation_ticket + ); +#endif + + /// + /// Attempt to sign a player into their Xbox Live account. This call may bring up + /// a sign-in user interface. + /// + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// + /// + /// You should only call this method if silent sign-in indicates that user interaction is required. + /// For UWA, this API is to be called from UI thread, if you're calling from non-UI thread or not sure, please use + /// signin_silently(Platform::Object^ coreDispatcherObj) version instead. + /// + _XSAPIIMP pplx::task> signin(); + + /// + /// Attempt to silently sign a player into their Xbox Live account. + /// + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// If silent sign-in is not successfull, result.err() indicates the error. + /// + /// + /// If the app is unable to silently sign-in, the API return sign_in_result with user_interaction_required status . + /// to sign-in, so the app should then call signin(). + /// For UWA, this API is to be called from UI thread, if you're not calling from non-UI thread or not sure, please use + /// signin_silently(Platform::Object^ coreDispatcherObj) version instead. + /// + _XSAPIIMP pplx::task> signin_silently(); + + /// + /// Set the session id to be used in telemetry events. + /// + /// The titleSessionId to be set in telemetery events + _XSAPIIMP void set_title_telemetry_session_id(_In_ const string_t& sessionId); + + /// + /// Internal function + /// + _XSAPIIMP const string_t& _Title_telemetry_session_id(); + +#if XSAPI_U + _XSAPIIMP static std::shared_ptr get_last_signed_in_user(); + _XSAPIIMP pplx::task> signout(); +#endif + +#if WINAPI_FAMILY && WINAPI_FAMILY==WINAPI_FAMILY_APP + /// + /// Attempt to sign a player into their Xbox Live account. This call may bring up + /// a sign-in user interface. + /// + /// The Windows Runtime core event message dispatcher. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// + /// + /// You should only call this method if silent sign-in indicates that user interaction is required. + /// If you're calling this API from non-UI thread, parameter coreDispatcherObj is requried, so that app UI + /// can be rendered and locale can be generated. + /// + _XSAPIIMP pplx::task> signin(_In_opt_ Platform::Object^ coreDispatcherObj); + + /// + /// Attempt to silently sign a player into their Xbox Live account. + /// + /// The Windows Runtime core event message dispatcher. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// If silent sign-in is not successfull, result.err() indicates the error. + /// + /// + /// If the app is unable to silently sign-in, the API return sign_in_result with user_interaction_required status . + /// to sign-in, so the app should then call signin(). + /// If you're calling this API from non-UI thread, parameter coreDispatcherObj is requried, so that app locale can be generated. + /// + _XSAPIIMP pplx::task> signin_silently(_In_opt_ Platform::Object^ coreDispatcherObj); + + /// + /// Attempt to silently sign a player into their Xbox Live account. + /// + /// The Windows Runtime core event message dispatcher. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// If silent sign-in is not successfull, result.err() indicates the error. + /// + /// + /// You should only call this method if silent sign-in indicates that user interaction is required. + /// If you're calling this API from non-UI thread, parameter coreDispatcherObj is requried, so that app UI + /// can be rendered and locale can be generated. + /// + _XSAPIIMP pplx::task> switch_account(_In_opt_ Platform::Object^ coreDispatcherObj); + +#else + _XSAPIIMP pplx::task> switch_account(); +#endif + + /// + /// Creates a new instance of xbox_live_user. + /// + _XSAPIIMP xbox_live_user(); + + /// + /// Gets a unique ID that is tied to the user's account which persists across multiple devices. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The Xbox Live public gamertag name associated with the user. + /// + _XSAPIIMP const string_t& gamertag() const; + + /// + /// Gets the age group of the user. + /// + _XSAPIIMP const string_t& age_group() const; + + /// + /// Gets the privileges of the user. + /// + _XSAPIIMP const string_t& privileges() const; + + std::shared_ptr auth_config(); + + /// + /// Indicates if the Xbox Live user is currently signed in. + /// + _XSAPIIMP bool is_signed_in() const; + +#if WINAPI_FAMILY && WINAPI_FAMILY==WINAPI_FAMILY_APP + /// + /// Gets id of WebAccount returned by the Xbox live WebAccountProvider. + /// + /// + /// Check https://msdn.microsoft.com/en-us/library/windows/apps/windows.security.credentials.webaccount.aspx + /// for more information about WebAccount + /// + _XSAPIIMP const string_t& web_account_id() const; +#endif + + /// + /// Retrieves an authorization token and digital signature for an HTTP request by this user. + /// + /// The HTTP method (GET, PUT, POST, etc.) for this request. + /// The URL for which to retrieve the authorization token and digital signature. + /// The headers to be included in the HTTP request. + /// + /// An interface for tracking the progress of the asynchronous call. The result is an object + /// indicating the token and the digital signature of the entire request, including the token. + /// + _XSAPIIMP pplx::task > + get_token_and_signature( + _In_ const string_t& httpMethod, + _In_ const string_t& url, + _In_ const string_t& headers + ); + + /// + /// Retrieves an authorization token and digital signature for an HTTP request by this user, + /// with a request body expressed as an array of bytes. + /// + /// The HTTP method (GET, PUT, POST, etc.) for this request. + /// The URL for which to retrieve the authorization token and digital signature. + /// The headers to be included in the HTTP request. + /// The body of the request, expressed as a string. + /// + /// An interface for tracking the progress of the asynchronous call. The result is an object + /// indicating the token and the digital signature of the entire request, including the token. + /// + _XSAPIIMP pplx::task > + get_token_and_signature( + _In_ const string_t& httpMethod, + _In_ const string_t& url, + _In_ const string_t& headers, + _In_opt_ const string_t& requestBodyString + ); + + /// + /// Retrieves an authorization token and digital signature for an HTTP request by this user, + /// with a request body expressed as an array of bytes. + /// + /// The HTTP method (GET, PUT, POST, etc.) for this request. + /// The URL for which to retrieve the authorization token and digital signature. + /// The headers to be included in the HTTP request. + /// The body of the request, expressed as an array of bytes. + /// + /// An interface for tracking the progress of the asynchronous call. The result is an object + /// indicating the token and the digital signature of the entire request, including the token. + /// + _XSAPIIMP pplx::task > + get_token_and_signature_array( + _In_ const string_t& httpMethod, + _In_ const string_t& url, + _In_ const string_t& headers, + _In_ const std::vector& requestBodyArray + ); + + xbox_live_user(_In_ std::shared_ptr userImpl) : m_user_impl(std::move(userImpl)) { } + + /// + /// Registers an event handler for when user sign out completes. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP static function_context add_sign_out_completed_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for sign-out completion notifications. + /// + /// The function_context object that was returned when the event handler was registered. + /// The callback function that recieves notifications. + _XSAPIIMP static void remove_sign_out_completed_handler(_In_ function_context context); + + std::shared_ptr _User_impl() { return m_user_impl; } + +protected: + std::shared_ptr m_user_impl; + +}; + +/// +/// Arguments for the SignOutCompleted event. +/// +class sign_out_completed_event_args +{ +public: + sign_out_completed_event_args(_In_ std::weak_ptr weakUser, _In_ std::shared_ptr user_impl); + + /// + /// The user that completed signing out. + /// + _XSAPIIMP std::shared_ptr user() const; + + /// + /// Internal function + /// + std::shared_ptr _Internal_user(); + +private: + std::shared_ptr m_user; + std::shared_ptr m_user_impl; +}; + +#endif //!TV_API + +/// Enumeration values that indicate the result code from string verification. +/// These values are defined on the service side and should not be modified. +/// +enum class verify_string_result_code +{ + /// No issues were found with the string. + success = 0, + + /// The string contains offensive content. + offensive = 1, + + /// The string is too long to verify. + too_long = 2, + + /// An unknown error was encountered during string verification. + unknown_error +}; + +/// +/// Contains information about the results of a string verification. +/// +class verify_string_result +{ +public: + /// + /// The result code for the string verification. + /// + _XSAPIIMP verify_string_result_code result_code() const; + + /// + /// first_offending_substring() contains the first offending substring if the + /// result code is verify_string_result_code::offensive. + /// + _XSAPIIMP const string_t& first_offending_substring() const; + + /// + /// Internal function + /// + verify_string_result(); + + /// + /// Internal function + /// + verify_string_result( + verify_string_result_code resultCode, + string_t firstOffendingSubstring + ); + + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + +private: + verify_string_result_code m_resultCode; + string_t m_firstOffendingSubstring; +}; + +/// +/// Provides methods to validate a string for use with Xbox live. +/// +class string_service +{ +public: + + /// + /// Verifies if a string contains acceptable text for use with Xbox Live. + /// + /// The string to verify. + /// + /// A verify_string_result object which indicates if the string contains unacceptable text. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V2 GET /system/strings/validate + /// + _XSAPIIMP pplx::task> verify_string(_In_ const string_t& stringToVerify); + + /// + /// Verifies a collection of strings to see if each string contains acceptable text for use with Xbox Live. + /// + /// The collection of strings to verify. + /// + /// A collection of verify_string_result objects which indicate if the strings contain unacceptable text. + /// + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// + /// Calls V2 GET /system/strings/validate + /// + _XSAPIIMP pplx::task>> verify_strings(_In_ const std::vector& stringsToVerify); + + /// + /// Internal function + /// + string_service(); + + /// + /// Internal function + /// + string_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + +private: + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; +}; +}}} diff --git a/Include/xsapi/title_callable_ui.h b/Include/xsapi/title_callable_ui.h new file mode 100644 index 00000000..1083dcce --- /dev/null +++ b/Include/xsapi/title_callable_ui.h @@ -0,0 +1,407 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/multiplayer.h" + +namespace xbox { namespace services { namespace system { + +/// List of gaming privilege that a user can have. +enum class gaming_privilege +{ + /// The user can broadcast live gameplay. + broadcast = 190, + + /// The user can view other user's friends list if this privilege is present. + view_friends_list = 197, + + /// The user can upload recorded in-game videos to the cloud if this privilege is present. Viewing GameDVRs is subject to privacy controls. + game_dvr = 198, + + /// Kinect recorded content can be uploaded to the cloud for the user and made accessible to anyone if this privilege is present. Viewing other user's Kinect content is subject to a privacy setting. + share_kinect_content = 199, + + /// The user can join a party session if this privilege is present + multiplayer_parties = 203, + + /// The user can participate in voice chat during parties and multiplayer game sessions if this privilege is present. Communicating with other users is subject to additional privacy permission checks + communication_voice_ingame = 205, + + /// The user can use voice communication with Skype on Xbox One if this privilege is present + communication_voice_skype = 206, + + /// The user can allocate a cloud compute cluster and manage a cloud compute cluster for a hosted game session if this privilege is present + cloud_gaming_manage_session = 207, + + /// The user can join a cloud compute session if this privilege is present + cloud_gaming_join_session = 208, + + /// The user can save games in cloud title storage if this privilege is present + cloud_saved_games = 209, + + /// The user can share content with others if this privilege is present + share_content = 211, + + /// The user can purchase, download and launch premium content available with the Xbox LIVE Gold subscription if this privilege is present + premium_content = 214, + + /// The user can purchase and download premium subscription content and use premium subscription features when this privilege is present + subscription_content = 219, + + /// The user is allowed to share progress information on social networks when this privilege is present + social_network_sharing = 220, + + /// The user can access premium video services if this privilege is present + premium_video = 224, + + /// The user can use video communication with Skype or other providers when this privilege is present. Communicating with other users is subject to additional privacy permission checks + video_communications = 235, + + /// The user is authorized to purchase content when this privilege is present + purchase_content = 245, + + /// The user is authorized to download and view online user created content when this privilege is present. + user_created_content = 247, + + /// The user is authorized to view other user's profiles when this privilege is present. Viewing other user's profiles is subject to additional privacy checks + profile_viewing = 249, + + /// The user can use asynchronous text messaging with anyone when this privilege is present. Extra privacy permissions checks are required to determine who the user is authorized to communicate with. Communicating with other users is subject to additional privacy permission checks + communications = 252, + + /// The user can join a multiplayer sessions for a game when this privilege is present. + multiplayer_sessions = 254, + + /// The user can follow other Xbox LIVE users and add Xbox LIVE friends when this privilege is present. + add_friend = 255 +}; + +/// This class contains functions used for displaying stock UI during a game such as showing a people picker. +class title_callable_ui +{ +public: +#if UWP_API + /// + /// Shows a picker UI that allows a person playing the game to select players + /// from a presented list of other people. + /// After the operation is complete, the list of selected Xbox User IDs is returned to the calling app. + /// + /// The prompt display text. + /// A list of Xbox User IDs which the user can select from. + /// A list of Xbox User IDs which will be pre-selected. + /// The minimum number of people the user must select. + /// The maximum number of people the user can select. + /// System user that identifies which user is sending the invite + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.payload() contains the list of users that were selected by the player. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task>> + show_player_picker_ui( + _In_ const string_t& promptDisplayText, + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount, + _In_opt_ Windows::System::User^ user = nullptr + ); + + /// + /// Shows a picker UI populated from the selected user's friend list and suggested friend list. + /// After selection, the user can send an invitation to play a game and/or party chat for a + /// specified game session to the selected people. + /// + /// A reference to the multiplayer session to invite people to. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with "///". Pass an empty string if + /// you dont want a custom string added to the invite. + /// System user that identifies which user is sending the invite + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_game_invite_ui( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionReference, + _In_ const string_t& contextStringId, + _In_opt_ Windows::System::User^ user = nullptr + ); + + /// + /// Shows UI displaying the profile card for a specified user. + /// + /// The Xbox User ID to show information about. + /// System user that identifies the user to show the UI on behalf of + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_profile_card_ui( + _In_ const string_t& targetXboxUserId, + _In_opt_ Windows::System::User^ user = nullptr + ); + + /// + /// Shows UI for adding or removing a specified person to or from the requesting user's friend list. + /// + /// The Xbox User ID to show information about. + /// System user that identifies the user to show the UI on behalf of + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_change_friend_relationship_ui( + _In_ const string_t& targetXboxUserId, + _In_opt_ Windows::System::User^ user = nullptr + ); + + /// + /// Shows UI presenting the requesting user's achievements for the specified title. + /// + /// The Xbox titleId to show information about. + /// System user that identifies the user to show the UI on behalf of + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_title_achievements_ui( + _In_ uint32_t titleId, + _In_opt_ Windows::System::User^ user = nullptr + ); + + /// + /// Checks if the current user has a specific privilege + /// + /// The privilege to check. + /// System user that identifies the user to show the UI on behalf of + /// + /// result.payload() contains a boolean which is true if the current user has the privilege. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static xbox::services::xbox_live_result + check_gaming_privilege_silently( + _In_ gaming_privilege privilege, + _In_opt_ Windows::System::User^ user = nullptr + ); + + /// + /// Checks if the current user has a specific privilege and if it doesn't, it shows UI + /// + /// The privilege to check. + /// Text to display in addition to the stock text about the privilege. + /// Pass an empty string if you dont want a message added. + /// System user that identifies the user to show the UI on behalf of + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.payload() contains a boolean which is true if the current user has the privilege. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + check_gaming_privilege_with_ui( + _In_ gaming_privilege privilege, + _In_ string_t friendlyMessage, + _In_opt_ Windows::System::User^ user = nullptr + ); + +#else + + /// + /// Shows a picker UI that allows a person playing the game to select players + /// from a presented list of other people. + /// After the operation is complete, the list of selected Xbox User IDs is returned to the calling app. + /// + /// The prompt display text. + /// A list of Xbox User IDs which the user can select from. + /// A list of Xbox User IDs which will be pre-selected. + /// The minimum number of people the user must select. + /// The maximum number of people the user can select. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.payload() contains the list of users that were selected by the player. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task>> + show_player_picker_ui( + _In_ const string_t& promptDisplayText, + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount + ); + + /// + /// Shows a picker UI populated from the selected user's friend list and suggested friend list. + /// After selection, the user can send an invitation to play a game and/or party chat for a + /// specified game session to the selected people. + /// + /// A reference to the multiplayer session to invite people to. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with "///". Pass an empty string if + /// you dont want a custom string added to the invite. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_game_invite_ui( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionReference, + _In_ const string_t& contextStringId + ); + + /// + /// Shows UI displaying the profile card for a specified user. + /// + /// The Xbox User ID to show information about. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_profile_card_ui( + _In_ const string_t& targetXboxUserId + ); + + /// + /// Shows UI for adding or removing a specified person to or from the requesting user's friend list. + /// + /// The Xbox User ID to show information about. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_change_friend_relationship_ui( + _In_ const string_t& targetXboxUserId + ); + + /// + /// Shows UI presenting the requesting user's achievements for the specified title. + /// + /// The Xbox titleId to show information about. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_title_achievements_ui( + _In_ uint32_t titleId + ); + + /// + /// Checks if the current user has a specific privilege + /// + /// The privilege to check. + /// + /// result.payload() contains a boolean which is true if the current user has the privilege. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static xbox::services::xbox_live_result + check_gaming_privilege_silently( + _In_ gaming_privilege privilege + ); + + /// + /// Checks if the current user has a specific privilege and if it doesn't, it shows UI + /// + /// The privilege to check. + /// Text to display in addition to the stock text about the privilege. + /// Pass an empty string if you dont want a message added. + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.payload() contains a boolean which is true if the current user has the privilege. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + check_gaming_privilege_with_ui( + _In_ gaming_privilege privilege, + _In_ string_t friendlyMessage + ); +#endif + +#if defined(XSAPI_U) + /// + /// Shows UI displaying the friend finder app, so the user can get more friends + /// + /// + /// Returns a pplx::task<T> object that represents the state of the asynchronous operation. + /// The task completes when the UI is closed. + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_friend_finder_ui(); + + /// + /// Invokes the Xbox App to show full user profile for the target user + /// + /// The Xbox target xuid to show the profile for. + /// + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_user_profile_ui(_In_ const string_t& targetXboxUserId); + + /// + /// Invokes the Xbox App to show the title app for the calling application. + /// + /// + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_title_hub_ui(); + + /// + /// Invokes the Xbox App to show the user settings + /// + /// + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_user_settings_ui(); + + /// + /// Invokes the Xbox App to show add friends functionality. + /// + /// + /// result.err() contains the error based on what happened in the case of an error. + /// + _XSAPIIMP static pplx::task> + show_add_friends_ui(); +#endif + +private: +#if UWP_API + static void _Get_gaming_privilege_scope_policy( + _Out_ Platform::String^& scope, + _Out_ Platform::String^& policy + ); +#endif +}; + +}}} + + diff --git a/Include/xsapi/title_storage.h b/Include/xsapi/title_storage.h new file mode 100644 index 00000000..dd9ca601 --- /dev/null +++ b/Include/xsapi/title_storage.h @@ -0,0 +1,753 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include + +namespace xbox { namespace services { + class http_call; + class xbox_live_context_impl; +}} + +namespace xbox { namespace services { + /// + /// Classes for handling title data in the cloud. + /// + namespace title_storage { + +/// Defines values used to indicate title storage type. +enum class title_storage_type +{ + /// + /// Per-user data storage such as game state or game settings that can be only be accessed by Xbox One. + /// User restrictions can be configured to public or owner only in the service configuration. + /// + trusted_platform_storage, + + /// + /// JSON storage has been deprecated. Use universal instead + /// + /// Per-user JSON data storage such as game state, game settings, and user generated content for any platforms + /// Data type is restricted to TitleStorageBlobType::Json + /// User restrictions can be configured to public or owner only in the service configuration. + /// + json_storage, + + /// + /// Global data storage. This storage type is only writable via the Xbox Developer Portal (XDP). + /// Any platform may read from this storage type. Data could be rosters, maps, challenges, art resources, etc. + /// + global_storage, + + /// + /// Session storage has been deprecated + /// + /// Per-session data storage for multiplayer game sessions. This storage type is only writable to users joined + /// to the session. Read access is configurable to public or session-joined only in the service configuration. + /// + session_storage, + + /// + /// Untrusted platform storage has been deprecated. Use universal instead + /// + /// Per-user data storage such as game state or game settings for untrusted platforms + /// User restrictions can be configured to public or owner only in the service configuration. + /// + untrusted_platform_storage, + + /// + /// Per-user data storage such as game state or game settings the can be accessed by Xbox One, Windows 10, and Windows Phone 10 devices + /// User restrictions can be configured to public or owner only in the service configuration. + /// + universal +}; + +/// Defines values used to indicate title storage blob type. +enum class title_storage_blob_type +{ + /// Unknown blob type. + unknown, + + /// Binary blob type. + binary, + + /// JSON blob type. + json, + + /// Config blob type. + config +}; + +/// Defines values used to indicate the ETag match condition used when downloading, uploading or deleting title storage data. +enum class title_storage_e_tag_match_condition +{ + /// There is no match condition. + not_used, + + /// Perform the request if the Etag value specified matches the service value. + if_match, + + /// Perform the request if the Etag value specified does not match the service value. + if_not_match +}; + +/// +/// Returns the amount of storage space allocated and used. +/// +class title_storage_quota +{ +public: + /// + /// Internal function + /// + _XSAPIIMP title_storage_quota(); + + /// + /// The service configuration ID associated with the quota. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The TitleStorageType associated with the quota. + /// + _XSAPIIMP title_storage_type storage_type() const; + + /// + /// The Xbox User ID associated with the quota if StorageType is TrustedPlatformStorage or JsonStorage, otherwise null. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The multiplayer session template name associated with the quota if StorageType is SessionStorage, otherwise null. + /// + _XSAPIIMP const string_t& multiplayer_session_template_name() const; + + /// + /// The multiplayer session name associated with the quota if StorageType is SessionStorage, otherwise null. + /// + _XSAPIIMP const string_t& multiplayer_session_name() const; + + /// + /// Number of bytes used in title storage of type StorageType. + /// + _XSAPIIMP uint64_t used_bytes() const; + + /// + /// Maximum number of bytes that can be used in title storage of type StorageType. + /// Note that this is a soft limit and the used bytes may actually exceed this value. + /// + _XSAPIIMP uint64_t quota_bytes() const; + + /// + /// Internal function + /// + void _Initialize( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_serviceConfigurationId; + title_storage_type m_storageType; + string_t m_xboxUserId; + string_t m_multiplayerSessionTemplateName; + string_t m_multiplayerSessionName; + uint64_t m_usedBytes; + uint64_t m_quotaBytes; +}; + +/// +/// Metadata about a blob. +/// +class title_storage_blob_metadata +{ +public: + /// + /// Internal function + /// + title_storage_blob_metadata(); + + /// + /// Internal function + /// + title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ string_t displayName, + _In_ string_t eTag + ); + + /// + /// Initializes a new instance of the title_storage_blob_metadata class. + /// + /// The service configuration ID (SCID) of the title + /// The TitleStorageType to get blob metadata objects for. Valid values are TrustedPlatormStorage, JsonStorage and GlobalStorage. + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The Xbox User ID of the title storage to enumerate. Ignored when dealing with GlobalStorage, so passing nullptr is acceptable in that case. (Optional) + /// + /// All other properties of this class are optional. To initialize optional properties, use the other constructors. + /// ClientTimestamp.UniversalTime will be initialized to 0. Length is initialized to 0. + /// title_storage_blob_metadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + _XSAPIIMP title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId + ); + + /// + /// Initializes a new instance of the title_storage_blob_metadata class including support for all optional properties except ClientTimestamp. + /// + /// The service configuration ID (SCID) of the title + /// The TitleStorageType to get blob metadata objects for. Valid values are TrustedPlatormStorage, JsonStorage and GlobalStorage. + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The Xbox User ID of the title storage to enumerate. Ignored when dealing with GlobalStorage, so passing nullptr is acceptable in that case. (Optional) + /// A display name suitable for displaying to the user. (Optional) + /// An ETag value to be associated with this instance. It is used for upload, download and delete operations. (Optional) + /// + /// ClientTimestamp.UniversalTime will be initialized to 0. Length is initialized to 0. + /// title_storage_blob_metadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + _XSAPIIMP title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId, + _In_ string_t displayName, + _In_ string_t eTag + ); + + /// + /// Initializes a new instance of the title_storage_blob_metadata class including support for all optional properties. + /// + /// The service configuration ID (SCID) of the title + /// The TitleStorageType to get blob metadata objects for. Valid values are TrustedPlatormStorage, JsonStorage and GlobalStorage. + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The Xbox User ID of the title storage to enumerate. Ignored when dealing with GlobalStorage, so passing nullptr is acceptable in that case. (Optional) + /// A display name suitable for displaying to the user. (Optional) + /// An ETag value to be associated with this instance. It is used for upload, download and delete operations. (Optional) + /// A client provided timestamp value to be associated with this instance. + /// + /// Length is initialized to 0. + /// title_storage_blob_metadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + _XSAPIIMP title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId, + _In_ string_t displayName, + _In_ string_t eTag, + _In_ utility::datetime clientTimestamp + ); + + /// + /// Initializes a new instance of the title_storage_blob_metadata class for SessionStorage including support for all optional properties except ClientTimestamp. + /// ClientTimestamp.UniversalTime will be initialized to 0. Length is initialized to 0. + /// title_storage_blob_metadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + /// The service configuration ID (SCID) of the title + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The multiplayer session template name associated with this object. + /// The multiplayer session name associated with this object. + /// A display name suitable for displaying to the user. (Optional) + /// An ETag value to be associated with this instance. It is used for upload, download and delete operations. (Optional) + _XSAPIIMP static title_storage_blob_metadata create_title_storage_blob_metadata_for_session_storage( + _In_ string_t serviceConfigurationId, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ string_t displayName = string_t(), + _In_ string_t eTag = string_t() + ); + + /// + /// Blob path is a unique string that conforms to a SubPath\file format (example: "foo\bar\blob.txt"). + /// + _XSAPIIMP const string_t& blob_path() const; + + /// + /// Type of blob data. Possible values are: Binary, Json, and Config. + /// + _XSAPIIMP title_storage_blob_type blob_type() const; + + /// + /// Type of storage. + /// + _XSAPIIMP title_storage_type storage_type() const; + + /// + /// [optional] Friendly display name to show in app UI. + /// + _XSAPIIMP const string_t& display_name() const; + + /// + /// ETag for the file used in read and write requests. + /// + _XSAPIIMP const string_t& e_tag() const; + + /// + /// [optional] Timestamp assigned by the client. + /// + _XSAPIIMP const utility::datetime& client_timestamp() const; + + /// + /// [optional] Timestamp assigned by the client. + /// + _XSAPIIMP void set_client_timestamp(_In_ utility::datetime value); + + /// + /// Gets the number of bytes of the blob data. + /// + _XSAPIIMP uint64_t length() const; + + /// + /// The service configuration ID of the title + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The Xbox User ID of the player this file belongs to. + /// This value will be null for Global and Session files. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The multiplayer session template name this file belongs to if StorageType is SessionStorage, otherwise null. + /// + _XSAPIIMP const string_t& multiplayer_session_template_name() const; + + /// + /// The multiplayer session name this file belongs to if StorageType is SessionStorage, otherwise null. + /// + _XSAPIIMP const string_t& multiplayer_session_name() const; + + /// + /// Internal function + /// + void _Set_e_tag_and_length( + _In_ string_t etag, + _In_ uint64_t length + ); + + /// + /// Internal function + /// + void _Initialize( + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType + ); + + /// + /// Internal function + /// + static const xbox_live_result _Convert_title_storage_blob_type_to_string(_In_ title_storage_blob_type blobType); + + /// + /// Internal function + /// + static title_storage_blob_type _Convert_string_to_title_storage_blob_type(_In_ const string_t& value); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_serviceConfigurationId; + title_storage_type m_storageType; + string_t m_blobPath; + title_storage_blob_type m_blobType; + string_t m_displayName; + string_t m_eTag; + utility::datetime m_clientTimestamp; + uint64_t m_lengthBytes; + string_t m_xboxUserId; + string_t m_multiplayerSessionTemplateName; + string_t m_multiplayerSessionName; +}; + +/// +/// Metadata about blob data returned from the cloud. +/// +class title_storage_blob_metadata_result +{ +public: + /// + /// Internal function + /// + _XSAPIIMP title_storage_blob_metadata_result(); + + /// + /// Collection of title_storage_blob_metadata objects returned by a service request + /// + _XSAPIIMP const std::vector& items() const; + + /// + /// Returns an title_storage_blob_metadata_result object containing the next page of title_storage_blob_metadata objects + /// + /// The maximum number of items the result can contain. Pass 0 to attempt retrieving all items. + /// title_storage_blob_metadata_result object for the next page. + _XSAPIIMP pplx::task> get_next( + _In_ uint32_t maxItems + ); + + /// + /// Indicates if there is additional data to retrieve from a get_next call + /// + _XSAPIIMP bool has_next() const; + + /// + /// Internal function + /// + void _Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName + ); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + std::vector m_items; + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + string_t m_serviceConfigurationId; + title_storage_type m_storageType; + string_t m_blobPath; + string_t m_xboxUserId; + string_t m_continuationToken; + string_t m_multiplayerSessionTemplateName; + string_t m_multiplayerSessionName; +}; + +/// +/// Blob data returned from the cloud. +/// +class title_storage_blob_result +{ +public: + /// + /// Internal function + /// + title_storage_blob_result(); + + /// + /// Internal function + /// + title_storage_blob_result( + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_blob_metadata blobMetadata + ); + + /// + /// The contents of the title storage blob. + /// + _XSAPIIMP std::shared_ptr> const blob_buffer() const; + + /// + /// Updated title_storage_blob_metadata object following an upload or download. + /// + _XSAPIIMP const title_storage_blob_metadata& blob_metadata() const; + +private: + std::shared_ptr> m_blobBuffer; + title_storage_blob_metadata m_blobMetadata; +}; + +/// +/// Services that manage title storage. +/// +class title_storage_service +{ +public: + /// + /// Gets title storage quota information for the specified service configuration and storage type. + /// For user storage types (TrustedPlatform and Json) the request will be made for the calling user's + /// Xbox user Id. + /// + /// The service configuration ID (SCID) of the title + /// The storage type to get quota information for. + /// title_storage_quota object containing the quota information. + /// Calls + /// V1 GET trustedplatform/users/xuid({xuid})/scids/{scid} or + /// V1 GET json/users/xuid({xuid})/scids/{scid} or + /// V1 GET global/scids/{scid} + /// + _XSAPIIMP pplx::task> get_quota( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType + ); + + /// + /// Gets title storage quota information for the SessionStorage associated with the specified multiplayer session. + /// + /// The service configuration ID (SCID) of the title + /// The multiplayer session template name for the session to get quota information for. + /// The multiplayer session name for the session to get quota information for. + /// title_storage_quota object containing the quota information. + /// Calls + /// V1 GET sessions/{sessionId}/scids/{scid} + /// + _XSAPIIMP pplx::task> get_quota_for_session_storage( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName + ); + + /// + /// Gets a list of blob metadata objects under a given path for the specified service configuration, storage type and storage ID. + /// + /// The service configuration ID (SCID) of the title + /// The storage type to get blob metadata objects for. + /// The root path to enumerate. Results will be for blobs contained in this path and all subpaths. (Optional) + /// The Xbox User ID of the title storage to enumerate. Ignored when enumerating GlobalStorage, so passing nullptr is acceptable. (Optional) + /// The number of items to skip before returning results. (Optional) + /// The maximum number of items to return. (Optional) + /// title_storage_blob_metadata_result object containing the list of enumerated blob metadata objects. + /// Calls + /// V1 GET trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] or + /// V1 GET json/users/xuid({xuid})/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] or + /// V1 GET global/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] + /// + _XSAPIIMP pplx::task> get_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath = string_t(), + _In_ string_t xboxUserId = string_t(), + _In_ uint32_t skipItems = 0, + _In_ uint32_t maxItems = 0 + ); + + /// + /// Gets a list of blob metadata objects in SessionStorage under a given path for the specified multiplayer session. + /// + /// The service configuration ID (SCID) of the title + /// The root path to enumerate. Results will be for blobs contained in this path and all subpaths. (Optional) + /// The multiplayer session template name for the session to get blob metadata objects for. + /// The multiplayer session name for the session to get blob metadata objects for. + /// The number of items to skip before returning results. + /// The maximum number of items to return. + /// title_storage_blob_metadata_result object containing the list of enumerated blob metadata objects. + /// Calls + /// V1 GET sessions/{sessionId}/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] + /// + _XSAPIIMP pplx::task> get_blob_metadata_for_session_storage( + _In_ string_t serviceConfigurationId, + _In_ string_t blobPath, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ uint32_t skipItems = 0, + _In_ uint32_t maxItems = 0 + ); + + /// + /// Deletes a blob from title storage. + /// + /// The blob metadata for the title storage blob to delete. + /// Specifies whether or not to have the delete operation check that the ETag matches before deleting the blob. + /// Calls + /// V1 DELETE trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 DELETE json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 DELETE sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + _XSAPIIMP pplx::task> delete_blob( + _In_ const title_storage_blob_metadata& blobMetadata, + _In_ bool deleteOnlyIfEtagMatches + ); + + /// + /// Downloads blob data from title storage. + /// + /// The blob metadata for the title storage blob to download. + /// The client provided buffer to store the downloaded blob data in. This buffer needs to be large enough to store the blob being downloaded. + /// If necessary, the length required for the buffer can be retrieved by getting the blob metadata. + /// The ETag match condition used to determine if the blob should be downloaded. + /// ConfigStorage filter string or JSONStorage json property name string to filter. (Optional) + /// TitleStorageBlobResult object containing the client provided blob buffer and an updated title_storage_blob_metadata object. + /// The metadata object will contain updated ETag and Length properties. + /// + /// This method will throw ERROR_INSUFFICIENT_BUFFER (0x8007007A) if the blobBuffer doesn't have enough capacity to hold the blob data. + /// Calls V1 GET trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET global/scids/{scid}/data/{path},{type} or + /// V1 GET sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + _XSAPIIMP pplx::task> download_blob( + _In_ title_storage_blob_metadata blobMetadata, + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_e_tag_match_condition etagMatchCondition, + _In_ string_t selectQuery = string_t() + ); + + /// + /// Downloads blob data from title storage. + /// + /// The blob metadata for the title storage blob to download. + /// The client provided buffer to store the downloaded blob data in. This buffer needs to be large enough to store the blob being downloaded. + /// If necessary, the length required for the buffer can be retrieved by getting the blob metadata. + /// The ETag match condition used to determine if the blob should be downloaded. + /// ConfigStorage filter string or JSONStorage json property name string to filter. (Optional) + /// The preferred download block size in bytes for binary blobs. + /// TitleStorageBlobResult object containing the client provided blob buffer and an updated title_storage_blob_metadata object. + /// The metadata object will contain updated ETag and Length properties. + /// + /// This method will throw ERROR_INSUFFICIENT_BUFFER (0x8007007A) if the blobBuffer doesn't have enough capacity to hold the blob data. + /// Calls V1 GET trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET global/scids/{scid}/data/{path},{type} or + /// V1 GET sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + _XSAPIIMP pplx::task> download_blob( + _In_ title_storage_blob_metadata blobMetadata, + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_e_tag_match_condition etagMatchCondition, + _In_ string_t selectQuery, + _In_ uint32_t preferredDownloadBlockSize + ); + + /// + /// Uploads blob data to title storage. + /// + /// Contains properties required to upload the buffer to title storage. Uploads require a service configuration Id, blob path, blob type and storage type at a minimum. + /// The buffer containing the blob data to upload. This buffer must be available for the duration of the async operation. Clients should not modify the buffer while an upload is in progress. + /// The ETag match condition used to determine if the blob data should be uploaded. + /// The preferred upload block size in bytes for binary blobs. Binary blobs will be + /// uploaded in multiple chunks of this size if they exceed it. Larger sizes are preferred by the service. + /// If timeouts occur, the app should retry with a smaller size. Block size must be within the 1K to 4MB range. This method + /// will use a default size if this parameter is not within the acceptable range. The current minimum size is 1024 bytes, + /// maximum size is 4194304 bytes and the default size is 262144 bytes. + /// + /// title_storage_blob_metadata object with updated Etag and Length properties. + /// + /// V1 PUT json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 PUT global/scids/{scid}/data/{path},{type} or + /// V1 PUT sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + _XSAPIIMP pplx::task> upload_blob( + _In_ title_storage_blob_metadata blobMetadata, + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_e_tag_match_condition etagMatchCondition, + _In_ uint32_t preferredUploadBlockSize = DEFAULT_UPLOAD_BLOCK_SIZE + ); + + _XSAPIIMP static const uint32_t MIN_UPLOAD_BLOCK_SIZE; + _XSAPIIMP static const uint32_t MAX_UPLOAD_BLOCK_SIZE; + _XSAPIIMP static const uint32_t DEFAULT_UPLOAD_BLOCK_SIZE; + _XSAPIIMP static const uint32_t MIN_DOWNLOAD_BLOCK_SIZE; + _XSAPIIMP static const uint32_t DEFAULT_DOWNLOAD_BLOCK_SIZE; + +private: + title_storage_service() {} + + title_storage_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + pplx::task> internal_get_blob_metadata( + _In_ const string_t& serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ const string_t& blobPath, + _In_ const string_t& xboxUserId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ); + + static void set_e_tag_header( + _In_ std::shared_ptr httpCall, + _In_ string_t etag, + _In_ title_storage_e_tag_match_condition eTagMatchCondition + ); + + static void set_range_header( + _In_ std::shared_ptr httpCall, + _In_ uint32_t startByte, + _In_ uint32_t endByte + ); + + static xbox_live_result title_storage_quota_subpath( + _In_ title_storage_type storageType, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& xboxUserId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName + ); + + static xbox_live_result title_storage_blob_metadata_subpath( + _In_ title_storage_type storageType, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& xboxUserId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName, + _In_ const string_t& blobPath, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ); + + static xbox_live_result title_storage_download_blob_subpath( + _In_ const title_storage_blob_metadata& blobMetadata, + _In_ const string_t& selectQuery + ); + + static xbox_live_result title_storage_upload_blob_subpath( + _In_ const title_storage_blob_metadata& blobMetadata, + _In_ const string_t& continuationToken, + _In_ bool finalBlock + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + friend xbox_live_context_impl; + friend class title_storage_blob_metadata_result; +}; + +}}} \ No newline at end of file diff --git a/Include/xsapi/types.h b/Include/xsapi/types.h new file mode 100644 index 00000000..a87109ae --- /dev/null +++ b/Include/xsapi/types.h @@ -0,0 +1,180 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include +#include +#include + +#ifdef _WIN32 +#include + +#ifndef _WIN32_WINNT_WIN10 +#define _WIN32_WINNT_WIN10 0x0A00 +#endif + +#ifndef TV_API +#define TV_API (WINAPI_FAMILY == WINAPI_FAMILY_TV_APP || WINAPI_FAMILY == WINAPI_FAMILY_TV_TITLE) +#endif + +#ifndef UWP_API +#define UWP_API (WINAPI_FAMILY == WINAPI_FAMILY_APP && _WIN32_WINNT >= _WIN32_WINNT_WIN10 ) +#endif + +#endif //#ifdef _WIN32 + +#ifndef _WIN32 + #ifdef _In_ + #undef _In_ + #endif + #define _In_ + #ifdef _Ret_maybenull_ + #undef _Ret_maybenull_ + #endif + #define _Ret_maybenull_ + #ifdef _Post_writable_byte_size_ + #undef _Post_writable_byte_size_ + #endif + #define _Post_writable_byte_size_(X) +#endif + +#ifndef _T + #ifdef _WIN32 + #define _T(x) L ## x + #else + #define _T(x) x + #endif +#endif + +#if defined _WIN32 + #ifdef _NO_XSAPIIMP + #define _XSAPIIMP + #define _XSAPIIMP_DEPRECATED __declspec(deprecated) + #else + #ifdef _XSAPIIMP_EXPORT + #define _XSAPIIMP __declspec(dllexport) + #define _XSAPIIMP_DEPRECATED __declspec(dllexport, deprecated) + #else + #define _XSAPIIMP __declspec(dllimport) + #define _XSAPIIMP_DEPRECATED __declspec(dllimport, deprecated) + #endif + #endif +#else + #if defined _NO_XSAPIIMP || __GNUC__ < 4 + #define _XSAPIIMP + #define _XSAPIIMP_DEPRECATED __attribute__ ((deprecated)) + #else + #define _XSAPIIMP __attribute__ ((visibility ("default"))) + #define _XSAPIIMP_DEPRECATED __attribute__ ((visibility ("default"), deprecated)) + #endif +#endif + +#if !defined(_WIN32) | (defined(_MSC_VER) && (_MSC_VER >= 1900)) +// VS2013 doesn't support default move constructor and assignment, so we implemented this. +// However, a user defined move constructor and assignment will implicitly delete default copy +// constructor and assignment in other compiler like clang. So we only define this in Win32 under VS2013 +#define DEFAULT_MOVE_ENABLED +#endif + +typedef int32_t function_context; +#ifdef _WIN32 +typedef wchar_t char_t; +typedef std::wstring string_t; +typedef std::wstringstream stringstream_t; +typedef std::wregex regex_t; +typedef std::wsmatch smatch_t; +#else +typedef char char_t; +typedef std::string string_t; +typedef std::stringstream stringstream_t; +typedef std::regex regex_t; +typedef std::smatch smatch_t; +#endif + +#if _MSC_VER <= 1800 +typedef std::chrono::system_clock chrono_clock_t; +#else +typedef std::chrono::steady_clock chrono_clock_t; +#endif + +// Forward declarations +namespace xbox { namespace services { + class user_context; + class xbox_live_context_settings; + class local_config; +}} + +#if !TV_API +// SSL client certificate context +#ifdef _WIN32 +#include +typedef PCCERT_CONTEXT cert_context; +#else +#include +#include +#include +typedef boost::asio::ssl::context* cert_context; +#endif +#endif + +#if UWP_API || UNIT_TEST_SERVICES +typedef Windows::System::User^ user_creation_context; +#else +typedef void* user_creation_context; +#endif + +#if defined(XSAPI_CPPWINRT) +inline Windows::Xbox::System::User^ convert_user_to_cppcx(_In_ const winrt::Windows::Xbox::System::User& user) +{ + winrt::ABI::Windows::Xbox::System::IUser* abiUser = winrt::get(user); + return reinterpret_cast(abiUser); +} + +#if TV_API | XBOX_UWP +inline Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ convert_eventargs_to_cppcx( + _In_ const winrt::Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs& eventArgs +) +{ + winrt::ABI::Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs* abiEventArgs = winrt::get(eventArgs); + return reinterpret_cast(abiEventArgs); +} +#endif + +inline std::vector convert_user_vector_to_cppcx( + _In_ const std::vector& users +) +{ + std::vector cppCxUsers; + for (winrt::Windows::Xbox::System::User u : users) + { + cppCxUsers.push_back(convert_user_to_cppcx(u)); + } + return cppCxUsers; +} + +inline winrt::Windows::Xbox::System::User convert_user_to_cppwinrt(_In_ Windows::Xbox::System::User^ user) +{ + winrt::Windows::Xbox::System::User cppWinrtUser(nullptr); + winrt::copy_from(cppWinrtUser, reinterpret_cast(user)); + return cppWinrtUser; +} + +inline std::vector convert_user_vector_to_cppwinrt( + _In_ const std::vector& users +) +{ + std::vector cppWinRtUsers; + for (xbox_live_user_t u : users) + { + cppWinRtUsers.push_back(convert_user_to_cppwinrt(u)); + } + return cppWinRtUsers; +} +#endif diff --git a/Include/xsapi/user_statistics.h b/Include/xsapi/user_statistics.h new file mode 100644 index 00000000..7fd4c6f6 --- /dev/null +++ b/Include/xsapi/user_statistics.h @@ -0,0 +1,449 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/real_time_activity.h" + +namespace xbox { namespace services { + class xbox_live_context_impl; + /// + /// Contains classes and enumerations that let you retrieve + /// player statistics from Xbox Live. + /// + namespace user_statistics { + +class user_statistics_service_impl; + +/// +/// Contains information about a user statistic. +/// +class statistic +{ +public: + + /// + /// Internal function + /// + statistic(); + + /// + /// Internal function + /// + statistic( + _In_ string_t name, + _In_ string_t type, + _In_ string_t value + ); + + /// + /// The name of the statistic. + /// + _XSAPIIMP const string_t& statistic_name() const; + + /// + /// The type of the statistic. + /// + _XSAPIIMP const string_t& statistic_type() const; + + /// + /// The value of the statistic. + /// + _XSAPIIMP const string_t& value() const; + + /// + /// Internal function + /// + void _Set_statistic_name(_In_ string_t name); + + /// + /// Internal function + /// + void _Set_statistic_type(_In_ string_t type); + + /// + /// Internal function + /// + void _Set_statistic_value(_In_ string_t value); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_statName; + string_t m_statType; + string_t m_value; +}; + +/// +/// Contains statistical information from a service configuration. +/// +class service_configuration_statistic +{ +public: + /// + /// Internal function + /// + service_configuration_statistic(); + + /// + /// Internal function + /// + service_configuration_statistic( + _In_ string_t serviceConfigurationId, + _In_ std::vector stats + ); + + /// + /// The service configuration ID (SCID) associated with the leaderboard. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// A collection of statistics used in leaderboards. + /// + _XSAPIIMP const std::vector& statistics() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + + /// + /// Internal function + /// + void _Set_input_service_configuration_id(string_t serviceConfigId); + +private: + string_t m_serviceConfigurationId; + std::vector m_stats; +}; + +/// +/// Represents the results of a user statistic query. +/// +class user_statistics_result +{ +public: + /// + /// Internal function + /// + user_statistics_result(); + + /// + /// Internal function + /// + user_statistics_result( + _In_ string_t xboxUserId, + _In_ std::vector serviceConfigStatistics + ); + + /// + /// The Xbox User ID for the user in a statistic. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// A collection of statistics from a service configuration. + /// + _XSAPIIMP const std::vector& service_configuration_statistics() const; + + /// + /// Internal function + /// + void _Set_input_service_configuration_id(string_t serviceConfigId); + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_xboxUserId; + std::vector m_serviceConfigStatistics; +}; + +/// +/// Contains requested statistics. +/// +class requested_statistics +{ +public: + /// + /// Internal function + /// + requested_statistics(); + + /// + /// Constructor for an RequestedStatistics object. + /// + /// The service configuration ID (SCID) of the title + /// A collection of statistics. + _XSAPIIMP requested_statistics( + _In_ string_t m_serviceConfigurationId, + _In_ std::vector m_statistics + ); + + /// + /// The service configuration ID in use. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// A collection of statistics. + /// + _XSAPIIMP const std::vector& statistics() const; + + /// + /// Internal function + /// + static xbox_live_result _Deserialize(_In_ const web::json::value& json); + +private: + string_t m_serviceConfigurationId; + std::vector m_statistics; +}; + +/// +/// Contains information about a change to a subscribed statistic. +/// +class statistic_change_event_args +{ +public: + /// + /// The Xbox user ID used to create the subscription. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The service configuration ID used to create the subscription. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The statistic with an updated value. + /// + _XSAPIIMP const statistic& latest_statistic() const; + + /// + /// Internal function + /// + statistic_change_event_args(); + + /// + /// Internal function + /// + statistic_change_event_args( + _In_ string_t xboxUserId, + _In_ string_t serviceConfigurationId, + _In_ statistic latestStatistic + ); + +private: + string_t m_xboxUserId; + string_t m_serviceConfigurationId; + statistic m_latestStatistic; +}; + +/// +/// Handles notification when the state of a statistic subscription changes. +/// +class statistic_change_subscription : public xbox::services::real_time_activity::real_time_activity_subscription +{ +public: + /// + /// The Xbox user ID used to create the subscription. + /// + _XSAPIIMP const string_t& xbox_user_id() const; + + /// + /// The service config ID used to create the subscription. + /// + _XSAPIIMP const string_t& service_configuration_id() const; + + /// + /// The statistic the subscription is for. + /// + _XSAPIIMP const xbox::services::user_statistics::statistic& statistic() const; + + /// + /// Internal function + /// + statistic_change_subscription( + _In_ string_t xboxUserId, + _In_ string_t serviceConfigurationId, + _In_ xbox::services::user_statistics::statistic newStat, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ); + + /// + /// Internal function + /// + void _Set_statistic_change_subscription_handler(_In_ std::function statisticChangeHandler); + +protected: + void on_subscription_created(_In_ uint32_t id, _In_ const web::json::value& data) override; + void on_event_received(_In_ const web::json::value& data) override; + +private: + std::function m_statisticChangeHandler; + string_t m_xboxUserId; + string_t m_serviceConfigurationId; + xbox::services::user_statistics::statistic m_statistic; +}; + +/// +/// Represents an endpoint that you can use to access the user statistic service. +/// +class user_statistics_service +{ +public: + /// + /// Get a specified statistic for a specified user. + /// + /// The Xbox User ID of the player to get statistics for. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to return. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is the requested statistic. + /// + /// + /// Calls V1 GET /users/xuid({xuid})/scids/{scid}/stats/{statname1} + /// + _XSAPIIMP pplx::task> get_single_user_statistics( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& statisticName + ); + + /// + /// Get specified statistics for a single user. + /// + /// The Xbox User ID of the player to get statistics for. + /// The service configuration ID (SCID) of the title + /// A collection of statistic names to lookup. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result is a user_statistics_result object that contains the requested statisitics. + /// Only statistics with values are returned. For example, if you ask for 3 statistic names and only 2 have values, + /// only 2 statistics are returned by the service. + /// + /// Calls V1 GET /users/xuid({xuid})/scids/{scid}/stats/{statname1},...,{statnameN} + _XSAPIIMP pplx::task> get_single_user_statistics( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const std::vector& statisticNames + ); + + /// + /// Get statistics for multiple users. + /// + /// A list of the user Xbox user IDs to get stats for. + /// The service configuration ID (SCID) of the title + /// A collection of statistic names to lookup. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result is a collection of user_statistics_result objects that contain the requested statisitics. + /// Only statistics with values are returned. For example, if you ask for 3 statistic names and only 2 have values, + /// only 2 statistics are returned by the service. + /// + /// Calls V1 POST /batch + _XSAPIIMP pplx::task>> get_multiple_user_statistics( + _In_ const std::vector& xboxUserIds, + _In_ const string_t& serviceConfigurationId, + _In_ std::vector& statisticNames + ); + + /// + /// Get statistics for users across different Service configurations. + /// + /// A list of the user Xbox user ID to get stats for. + /// A list of the service config IDs and its associated array of statistics. + /// + /// Returns a concurrency::task<T> object that represents the state of the asynchronous operation. + /// The result is a collection of user_statistics_result objects that contain the requested statisitics. + /// Only statistics with values are returned. For example, if you ask for 3 statistic names and only 2 have values, + /// only 2 statistics are returned by the service. + /// + /// Calls V1 POST /batch + _XSAPIIMP pplx::task>> get_multiple_user_statistics_for_multiple_service_configurations( + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& requestedServiceConfigurationStatisticsCollection + ); + + /// + /// Subscribes to statistic update notifications via the StatisticChanged event. + /// + /// The Xbox User ID of the player requesting the subscription. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to subscribe to. + /// A statistic_change_subscription object that contains the state of the subscription. + /// You can register an event handler for statistic changes by calling set_statistic_changed_handler(). + /// + _XSAPIIMP xbox_live_result> subscribe_to_statistic_change( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& statisticName + ); + + /// + /// Unsubscribes a previously created statistic change subscription. + /// + /// The subscription object to unsubscribe + _XSAPIIMP xbox_live_result unsubscribe_from_statistic_change( + _In_ std::shared_ptr subscription + ); + + /// + /// Registers an event handler for statistic change notifications. + /// Event handlers receive a statistic_change_event_args object. + /// + /// The callback function that recieves notifications. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_statistic_changed_handler(_In_ std::function handler); + + /// + /// Unregisters an event handler for statistic change notifications. + /// + /// The function_context object that was returned when the event handler was registered. + /// The callback function that recieves notifications. + _XSAPIIMP void remove_statistic_changed_handler(_In_ function_context context); + + std::shared_ptr _Xbox_live_context_settings() { return m_xboxLiveContextSettings; } + +private: + user_statistics_service(); + + user_statistics_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr rtaService + ); + + static string_t user_stats_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ std::vector statNames + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::shared_ptr m_userStatisticsServiceImpl; + + friend xbox_live_context_impl; +}; + +}}} diff --git a/Include/xsapi/xbox_cll.h b/Include/xsapi/xbox_cll.h new file mode 100644 index 00000000..96f4f476 --- /dev/null +++ b/Include/xsapi/xbox_cll.h @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#ifdef XSAPI_I +#include "iOSCll.h" + +namespace xbox { namespace services { + +class xbox_cll : public std::enable_shared_from_this +{ +public: + static std::shared_ptr get_xbox_cll_singleton(); + + xbox_cll(); + ~xbox_cll(); + + std::shared_ptr raw_cll(); + +private: + std::shared_ptr m_cll; + static std::shared_ptr s_xboxCll; +}; + +}} +#endif diff --git a/Include/xsapi/xbox_live_app_config.h b/Include/xsapi/xbox_live_app_config.h new file mode 100644 index 00000000..42fa6e93 --- /dev/null +++ b/Include/xsapi/xbox_live_app_config.h @@ -0,0 +1,321 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include + +#ifdef __OBJC__ +#import +#endif + +namespace xbox { namespace services { + + namespace system { + class user_impl_idp; + } + +#if UWP_API || UNIT_TEST_SERVICES +class signin_ui_settings +{ +public: + /// + /// Enum for current game category, sign in UI will adjust accordingly based on + /// your game category. + /// + enum class game_category + { + /// + /// Enum for setting current title as standard game category. + /// + standard, + + /// + /// Enum for setting current title as casual game category + /// + casual + }; + + /// + /// Enum for emphasizing Xbox Live features your title has. + /// + enum class emphasis_feature + { + /// + /// Enum for emphasizing Xbox Live achievement feature. + /// + achievements, + + /// + /// Enum for emphasizing Xbox Live connected storage feature. + /// + connected_storage, + + /// + /// Enum for emphasizing Xbox Live find players feature. + /// + find_players, + + /// + /// Enum for emphasizing Xbox Live game bar feature. + /// + game_bar, + + /// + /// Enum for emphasizing Xbox Live game DVR feature. + /// + game_dvr, + + /// + /// Enum for emphasizing Xbox Live leaderboards feature. + /// + leaderboards, + + /// + /// Enum for emphasizing Xbox Live multiplayer feature. + /// + multiplayer, + + /// + /// Enum for emphasizing Xbox Live purchase feature. + /// + purchase, + + /// + /// Enum for emphasizing Xbox Live shared content feature. + /// + shared_content, + + /// + /// Enum for emphasizing Xbox Live social feature. + /// + social, + + /// + /// Enum for emphasizing Xbox Live tournaments feature. + /// + tournaments + }; + + /// + /// Get current game_category setting + /// + _XSAPIIMP game_category title_category() const { return m_gameCategory; } + + /// + /// Set your title's category, sign in UI will adjust accordingly based on your game category. + /// + _XSAPIIMP void set_game_category(game_category category) { m_gameCategory = category; } + + /// + /// Specify which emphasized Xbox Live feature you want to show on the sign in page, up to 3. + /// + _XSAPIIMP void add_emphasis_feature(emphasis_feature feature) { m_features.insert(feature); } + + /// + /// Retrieve the emphasis features added to show on the UI, only first 3 will be displayed. + /// + _XSAPIIMP const std::set& emphasis_features() const { return m_features; } + + /// + /// Specify the background image you want to show in the sign in page, in raw binary form. + /// + /// + /// An Image can be one of the following format: jpeg, jpg, png, bmp, gif, tiff and ico. + /// The input source will always be stretched to 300X400 pixels , thus the file larger than that + /// is not recommended. + /// + _XSAPIIMP void set_background_image(const std::vector& image); + + /// + /// Retrieve the background color of sign in page the title has set. + /// + _XSAPIIMP const string_t& background_hex_color() const { return m_backgroundColor; } + + /// + /// Set the background color of your sign in page, in hex string. Example: "0F2C55". + /// + _XSAPIIMP void set_background_hex_color(const string_t& backgroundColor) { m_backgroundColor = backgroundColor; } + + signin_ui_settings() : + m_gameCategory(game_category::standard) + {} + + /// + /// Internal function + /// + const string_t& _Background_image_base64_encoded() const { return m_backgroundImageBase64Encoded; } + + /// + /// Internal function + /// + static string_t _Feature_to_string(emphasis_feature); + + /// + /// Internal function + /// + bool _Enabled(); + +private: + // Disable copy, settings must be accessed via reference. + signin_ui_settings(const signin_ui_settings&); + signin_ui_settings& operator=(const signin_ui_settings&); + + game_category m_gameCategory; + string_t m_backgroundColor; + string_t m_backgroundImageBase64Encoded; + std::set m_features; +}; + +#endif + +/// +/// Represents the configuration of an Xbox Live application. +/// +class xbox_live_app_config +{ +public: + /// + /// Gets the app config singleton. + /// + static std::shared_ptr get_app_config_singleton(); + + /// + /// Returns the title id of the app. + /// + _XSAPIIMP uint32_t title_id(); + + /// + /// Returns the service config id of the app. + /// + _XSAPIIMP string_t scid(); + + /// + /// Returns the Xbox Live environment being used, it is empty before you sign in or using prodction. + /// + _XSAPIIMP const string_t& environment() const; + + /// + /// Returns the sandbox such as "XDKS.1", it is empty until you sign in. + /// + _XSAPIIMP const string_t& sandbox() const; + + /// + /// internal function + /// + uint32_t _Override_title_id_for_multiplayer() const; + + /// + /// internal function + /// + const string_t& _Override_scid_for_multiplayer() const; + + /// + /// internal function + /// + const string_t& _Apns_Environment() const; + + /// + /// internal function + /// + const web::uri& _Proxy() const; + + /// + /// Set the titles device id that is used for telemetry + /// + _XSAPIIMP void set_title_telemetry_device_id(_In_ const string_t& deviceId); + + /// + /// Get the titles device id that is used for telemetry + /// + _XSAPIIMP const string_t& title_telemetry_device_id() const; + +private: + /// + /// Internal function + /// + xbox_live_app_config(); + + /// + /// Reads the configuration data. + /// + xbox_live_result read(); +#if XSAPI_U +public: +#ifdef __OBJC__ + /// Set the view controller that your app wants to launch any xbox live services ui like sign in, profile + /// card, etc from. This will set a weak pointer to this view controller. If at any point this view controller + /// is no longer the desired presenting view controller, then set this to nil. If the weak pointer that backs + /// this view controller ever is nil, then the fallback view controller for the app is the application's + /// key window's root view controller. + /// + /// @param viewController The view controller to present any xbox live services ui from. Can be nil. + /// + /// Usage for using a view controller as the presenting view controller only once: + /// + /// xbox_live_app_config::set_launch_view_controller(viewController) + /// user->signin().then... + /// // Then when done with sign in or any ui + /// xbox_live_app_config::set_launch_view_controller(nil) + /// + /// Usage for setting the view controller that will always be used: + /// + /// xbox_live_app_config::set_launch_view_controller(viewController) + /// // Some time later in your application + /// title_callable_ui::show_profile_card_ui(xuid) + /// + _XSAPIIMP static void set_launch_view_controller(_In_ UIViewController *viewController); + _XSAPIIMP static void set_notification_registration_token(_In_ NSString *registrationToken); +#endif + + /// + /// Sets the Xbox Live Sandbox + /// + _XSAPIIMP void set_sandbox(_In_ const string_t& sandbox); + + /// + /// Sets the Xbox Live environment + /// + _XSAPIIMP void set_environment(_In_ const string_t& environment); +private: +#else + void set_sandbox(const string_t& sandbox); + void set_environment(const string_t& environment); +#endif + +#if XSAPI_U + string_t get_proxy_string(); +#endif + + string_t m_apnsEnvironment; + + uint32_t m_titleId; + uint32_t m_overrideTitleId; + string_t m_environment; + string_t m_sandbox; + string_t m_scid; + string_t m_overrideScid; + web::uri m_proxy; + string_t m_titleTelemetryDeviceId; + + friend class system::user_impl_idp; + +#if UWP_API || UNIT_TEST_SERVICES +public: + /// + /// Returns the reference to sign in UI settings. + /// + _XSAPIIMP signin_ui_settings& app_signin_ui_settings() { return m_signinUISettings; } + +private: + signin_ui_settings m_signinUISettings; +#endif +}; + + +}} diff --git a/Include/xsapi/xbox_live_context.h b/Include/xsapi/xbox_live_context.h new file mode 100644 index 00000000..76a2fd4d --- /dev/null +++ b/Include/xsapi/xbox_live_context.h @@ -0,0 +1,258 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#if !(TV_API | XBOX_UWP) + +#if !XSAPI_CPP +#include "User_WinRT.h" +#else +#include "xsapi/system.h" +#endif + +#endif + +#include "xsapi/contextual_search_service.h" +#if TV_API || UNIT_TEST_SERVICES +#include "xsapi/entertainment_profile.h" +#endif +#include "xsapi/multiplayer.h" + +namespace xbox { namespace services { +class xbox_live_context_server_impl; + +#if XSAPI_SERVER +/// +/// Defines pointers to objects that access Xbox Live to create features for player interactions. +/// +class xbox_live_server_context +{ +public: + + /// + /// Internal function + /// + _XSAPIIMP xbox_live_server_context( + _In_ std::shared_ptr server + ); + + /// + /// Returns the associated system User. + /// + _XSAPIIMP std::shared_ptr server(); + + /// + /// Returns an object containing settings that apply to all REST calls made such as retry and diagnostic settings. + /// + _XSAPIIMP std::shared_ptr settings(); + + /// + /// Returns an object containing Xbox Live app config such as title ID + /// + _XSAPIIMP std::shared_ptr application_config(); + +private: + + std::shared_ptr m_xboxLiveContextImpl; +}; + +#endif + + +/// +/// Defines pointers to objects that access Xbox Live to create features for player interactions. +/// +/// Note: the XboxLiveContext is unique per instance. Changing state on one instance for a user does not affect a second instance of the context for the same user. Using multiple instances can therefore result in unexpected behavior. Titles should ensure to only use one instance of the XboxLiveContext per user. +/// +class xbox_live_context +{ +public: +#if TV_API | XBOX_UWP + /// + /// Creates an xbox_live_context from a Windows::Xbox::System::User^ + /// + _XSAPIIMP xbox_live_context( + _In_ Windows::Xbox::System::User^ user + ); + + /// + /// Returns the associated system User + /// + _XSAPIIMP Windows::Xbox::System::User^ user(); + +#else + +#if XSAPI_CPP + /// + /// Creates an xbox_live_context from a xbox_live_user + /// + _XSAPIIMP xbox_live_context( + _In_ std::shared_ptr user + ); + + /// + /// Returns the associated system User. + /// + _XSAPIIMP std::shared_ptr user(); + +#else + /// + /// Creates an xbox_live_context from a Microsoft::Xbox::Services::System::XboxLiveUser^ + /// + _XSAPIIMP xbox_live_context( + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user + ); + + /// + /// Returns the associated system XboxLiveUser. + /// + _XSAPIIMP Microsoft::Xbox::Services::System::XboxLiveUser^ user(); +#endif + +#endif + + /// + /// Returns the current user's Xbox Live User ID. + /// + _XSAPIIMP const string_t& xbox_live_user_id(); + + /// + /// A service for managing user profiles. + /// + _XSAPIIMP social::profile_service& profile_service(); + + /// + /// A service for managing social networking links. + /// + _XSAPIIMP social::social_service& social_service(); + + /// + /// A service for managing reputation reports. + /// + _XSAPIIMP social::reputation_service& reputation_service(); + + /// + /// A service for managing leaderboards. + /// + _XSAPIIMP leaderboard::leaderboard_service& leaderboard_service(); + + /// + /// A service for managing achievements. + /// + _XSAPIIMP achievements::achievement_service& achievement_service(); + + /// + /// A service for managing user statistics. + /// + _XSAPIIMP user_statistics::user_statistics_service& user_statistics_service(); + + /// + /// A service for managing multiplayer games. + /// + _XSAPIIMP multiplayer::multiplayer_service& multiplayer_service(); + + /// + /// A service for managing matchmaking sessions. + /// + _XSAPIIMP matchmaking::matchmaking_service& matchmaking_service(); + + /// + /// Returns an object containing settings that apply to all REST calls made such as retry and diagnostic settings. + /// + _XSAPIIMP std::shared_ptr settings(); + + /// + /// Returns an object containing Xbox Live app config such as title ID + /// + _XSAPIIMP std::shared_ptr application_config(); + + /// + /// A service for managing real-time activity. + /// + _XSAPIIMP const std::shared_ptr& real_time_activity_service(); + + /// + /// A service for using the Game Server Platform. + /// + _XSAPIIMP game_server_platform::game_server_platform_service& game_server_platform_service(); + + /// + /// A service for managing Rich Presence. + /// + _XSAPIIMP presence::presence_service& presence_service(); + + /// + /// A service for storing data in the cloud. + /// + _XSAPIIMP title_storage::title_storage_service& title_storage_service(); + + /// + /// A service for managing privacy settings. + /// + _XSAPIIMP privacy::privacy_service& privacy_service(); + + /// + /// A service used to check for offensive strings. + /// + _XSAPIIMP system::string_service& string_service(); + + /// + /// A service for contextual search. + /// + _XSAPIIMP contextual_search::contextual_search_service& contextual_search_service(); + +#if UWP_API || XSAPI_U + /// + /// A service used to write in game events. + /// + _XSAPIIMP events::events_service& events_service(); +#endif + +#if TV_API || UNIT_TEST_SERVICES + /// + /// A service for managing catalogs. + /// + _XSAPIIMP marketplace::catalog_service& catalog_service(); + + /// + /// A service for managing inventory. + /// + _XSAPIIMP marketplace::inventory_service& inventory_service(); + + /// + /// A service for the entertainment profile. + /// + _XSAPIIMP entertainment_profile::entertainment_profile_list_service& entertainment_profile_list_service(); +#endif + +#if TV_API | XBOX_UWP +#if defined(XSAPI_CPPWINRT) + _XSAPIIMP xbox_live_context( + _In_ winrt::Windows::Xbox::System::User user + ) : xbox_live_context(convert_user_to_cppcx(user)) + { + } + + inline winrt::Windows::Xbox::System::User user_cppwinrt() + { + winrt::Windows::Xbox::System::User cppWinrtUser(nullptr); + winrt::copy_from(cppWinrtUser, reinterpret_cast(user())); + return cppWinrtUser; + } +#endif +#endif + +private: + + std::shared_ptr m_xboxLiveContextImpl; +}; + + +}} diff --git a/Include/xsapi/xbox_live_context_settings.h b/Include/xsapi/xbox_live_context_settings.h new file mode 100644 index 00000000..fe966635 --- /dev/null +++ b/Include/xsapi/xbox_live_context_settings.h @@ -0,0 +1,328 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#include +#include +#include +#include "xsapi/xbox_service_call_routed_event_args.h" + +namespace xbox { namespace services { + +#define DEFAULT_HTTP_TIMEOUT_SECONDS (30) +#if UNIT_TEST_SERVICES + #define MIN_HTTP_TIMEOUT_SECONDS (0) // speed up unit tests +#else + #define MIN_HTTP_TIMEOUT_SECONDS (5) +#endif +#define MIN_HTTP_TIMEOUT_MILLISECONDS (MIN_HTTP_TIMEOUT_SECONDS * 1000) +#define DEFAULT_LONG_HTTP_TIMEOUT_SECONDS (5 * 60) +#define DEFAULT_WEBSOCKET_TIMEOUT_SECONDS (60) +#define MAXIMUM_WEBSOCKETS_ACTIVATIONS_ALLOWED_PER_USER (5) +#define DEFAULT_HTTP_RETRY_WINDOW_SECONDS (20) +#define DEFAULT_RETRY_DELAY_SECONDS (2) +#define MIN_RETRY_DELAY_SECONDS (2) + +/// +/// Enumeration values that indicate the trace levels of debug output for service diagnostics. +/// +/// Setting the debug trace level to error or higher reports the last HRESULT, the current +/// function, the source file, and the line number for many trace points in the Xbox live code. +/// +enum class xbox_services_diagnostics_trace_level +{ + /// + /// Output no tracing and debugging messages. + /// + off, + + /// + /// Output error-handling messages. + /// + error, + + /// + /// Output warnings and error-handling messages. + /// + warning, + + /// + /// Output informational messages, warnings, and error-handling messages. + /// + info, + + /// + /// Output all debugging and tracing messages. + /// + verbose +}; + +/// +/// Enum used with disable_asserts_for_xbox_live_throttling_in_dev_sandboxes() +/// +enum class xbox_live_context_throttle_setting +{ + /// + /// Passed to xboxLiveContext->settings()->disable_asserts_for_xbox_live_throttling_in_dev_sandboxes() + /// to warn code reviewers that there's an outstanding Xbox Live calling pattern issue that needs to be addressed. + /// + this_code_needs_to_be_changed_to_avoid_throttling +}; + +/// +/// Enum used with disable_asserts_ APIs +/// +enum class xbox_live_context_recommended_setting +{ + /// + /// Passed to xboxLiveContext->settings()->disable_asserts_ APIs + /// to warn code reviewers that there's an outstanding calling pattern issue that needs to be addressed. + /// + this_code_needs_to_be_changed_to_follow_best_practices +}; + +/// +/// Represents settings for an HTTP call. +/// +class xbox_live_context_settings +{ +public: + /// + /// Creates a new xbox_live_context_settings object. + /// + _XSAPIIMP xbox_live_context_settings(); + + /// + /// Registers for all service call notifications. Event handlers will receive xbox::services::xbox_service_call_routed_event_args + /// + /// The event handler function to call. + /// + /// A function_context object that can be used to unregister the event handler. + /// + _XSAPIIMP function_context add_service_call_routed_handler(_In_ std::function handler); + + /// + /// Unregisters from all service call notifications. + /// + /// The function_context object that was returned when the event handler was registered. + _XSAPIIMP void remove_service_call_routed_handler(_In_ function_context context); + + /// + /// Indicates if events should be generated for service_call_routed_handler. + /// + _XSAPIIMP bool enable_service_call_routed_events() const; + + /// + /// Set if events should be generated for service_call_routed_handler. + /// + _XSAPIIMP void set_enable_service_call_routed_events(_In_ bool value); + + /// + /// DEPRECATED. Instead call xbox_live_services_settings::get_singleton_instance()->diagnostics_trace_level() + /// Indicates the level of debug messages to send to the debugger's Output window. + /// + _XSAPIIMP_DEPRECATED xbox_services_diagnostics_trace_level diagnostics_trace_level() const; + + /// + /// DEPRECATED. Instead call xbox_live_services_settings::get_singleton_instance()->set_diagnostics_trace_level(value) + /// Sets the level of debug messages to send to the debugger's Output window. + /// + _XSAPIIMP_DEPRECATED void set_diagnostics_trace_level(_In_ xbox_services_diagnostics_trace_level value); + + /// + /// DEPRECATED. This value is ignored and is now automatically calcuated to ensure the http_timeout_window() is obeyed + /// This means that calls will be more deterministic about the time window they return in. + /// + _XSAPIIMP const std::chrono::seconds& http_timeout() const; + + /// + /// DEPRECATED. This value is ignored and is now automatically calcuated to ensure the http_timeout_window() is obeyed + /// This means that calls will be more deterministic about the time window they return in. + /// + _XSAPIIMP void set_http_timeout(_In_ std::chrono::seconds value); + + /// + /// Gets the connect, send, and receive timeouts for HTTP socket operations of long calls such as Title Storage calls. + /// Default is 5 minutes. Calls that take longer than this are aborted. + /// + _XSAPIIMP const std::chrono::seconds& long_http_timeout() const; + + /// + /// Sets the connect, send, and receive timeouts for HTTP socket operations of long calls such as Title Storage calls. + /// Default is 5 minutes. Calls that take longer than this are aborted. + /// Take care when setting this to smaller values as some calls like Title Storage may take a few minutes to complete. + /// + _XSAPIIMP void set_long_http_timeout(_In_ std::chrono::seconds value); + + /// + /// Gets the HTTP retry delay in seconds. + /// + /// Retries are delayed using a exponential back off. By default, it will delay 2 seconds then the + /// next retry will delay 4 seconds, then 8 seconds, and so on up to a max of 1 min until either + /// the call succeeds or the http_timeout_window is reached, at which point the call will fail. + /// The delay is also jittered between the current and next delay to spread out service load. + /// The default for http_timeout_window is 20 seconds and can be changed using set_http_timeout_window() + /// + /// If the service returns an an HTTP error with a "Retry-After" header, then all future calls to that API + /// will immediately fail with the original error without contacting the service until the "Retry-After" + /// time has been reached. + /// + /// Idempotent service calls are retried when a network error occurs or the server responds with one of these HTTP status codes: + /// 408 (Request Timeout) + /// 429 (Too Many Requests) + /// 500 (Internal Server Error) + /// 502 (Bad Gateway) + /// 503 (Service Unavailable) + /// 504 (Gateway Timeout) + /// + _XSAPIIMP const std::chrono::seconds& http_retry_delay() const; + + /// + /// Sets the HTTP retry delay in seconds. The default and minimum delay is 2 seconds. + /// + /// Retries are delayed using a exponential back off. By default, it will delay 2 seconds then the + /// next retry will delay 4 seconds, then 8 seconds, and so on up to a max of 1 min until either + /// the call succeeds or the http_timeout_window is reached, at which point the call will fail. + /// The delay is also jittered between the current and next delay to spread out service load. + /// The default for http_timeout_window is 20 seconds and can be changed using set_http_timeout_window() + /// + /// If the service returns an an HTTP error with a "Retry-After" header, then all future calls to that API + /// will immediately fail with the original error without contacting the service until the "Retry-After" + /// time has been reached. + /// + /// Idempotent service calls are retried when a network error occurs or the server responds with one of these HTTP status codes: + /// 408 (Request Timeout) + /// 429 (Too Many Requests) + /// 500 (Internal Server Error) + /// 502 (Bad Gateway) + /// 503 (Service Unavailable) + /// 504 (Gateway Timeout) + /// + _XSAPIIMP void set_http_retry_delay(_In_ std::chrono::seconds value); + + /// + /// Gets the HTTP timeout window in seconds. + /// + /// This controls how long to spend attempting to retry idempotent service calls before failing. + /// The default is 20 seconds + /// + /// Idempotent service calls are retried when a network error occurs or the server responds with one of these HTTP status codes: + /// 408 (Request Timeout) + /// 429 (Too Many Requests) + /// 500 (Internal Server Error) + /// 502 (Bad Gateway) + /// 503 (Service Unavailable) + /// 504 (Gateway Timeout) + /// + _XSAPIIMP const std::chrono::seconds& http_timeout_window() const; + + /// + /// Sets the HTTP timeout window in seconds. + /// + /// This controls how long to spend attempting to retry idempotent service calls before failing. + /// The default is 20 seconds. Set to 0 to turn off retry. + /// + /// Idempotent service calls are retried when a network error occurs or the server responds with one of these HTTP status codes: + /// 408 (Request Timeout) + /// 429 (Too Many Requests) + /// 500 (Internal Server Error) + /// 502 (Bad Gateway) + /// 503 (Service Unavailable) + /// 504 (Gateway Timeout) + /// + _XSAPIIMP void set_http_timeout_window(_In_ std::chrono::seconds value); + + /// + /// Gets the web socket timeout window in seconds. + /// + _XSAPIIMP const std::chrono::seconds& websocket_timeout_window() const; + + /// + /// Sets the web socket timeout window in seconds. + /// Controls how long to spend attempting to retry establishing a websocket connection before failing. + /// Default is 300 seconds. Set to 0 to turn off retry. + /// + _XSAPIIMP void set_websocket_timeout_window(_In_ std::chrono::seconds value); + + /// + /// Gets whether to use the dispatcher for event routing + /// + _XSAPIIMP bool use_core_dispatcher_for_event_routing() const; + + /// + /// Controls whether to use the CoreDispatcher from the User object to route events through. + /// This is required to be true if using events with JavaScript. + /// + _XSAPIIMP void set_use_core_dispatcher_for_event_routing(_In_ bool value); + + /// + /// Disables asserts for Xbox Live throttling in dev sandboxes. + /// The asserts will not fire in RETAIL sandbox, and this setting has has no affect in RETAIL sandboxes. + /// It is best practice to not call this API, and instead adjust the calling pattern but this is provided + /// as a temporary way to get unblocked while in early stages of game development. + /// + _XSAPIIMP void disable_asserts_for_xbox_live_throttling_in_dev_sandboxes( + _In_ xbox_live_context_throttle_setting setting + ); + + /// + /// Disables asserts for having maximum number of websockets being activated + /// i.e. MAXIMUM_WEBSOCKETS_ACTIVATIONS_ALLOWED_PER_USER (5) per user per title instance. + /// It is best practice to not call this API, and instead adjust the calling pattern but this is provided + /// as a temporary way to get unblocked while in early stages of game development. + /// + _XSAPIIMP void disable_asserts_for_maximum_number_of_websockets_activated( + _In_ xbox_live_context_recommended_setting setting + ); + +public: + // Internal public function +#if UWP_API || UNIT_TEST_SERVICES + /// + /// Sets the CoreDispatcher + /// + static void _Set_dispatcher(_In_opt_ Platform::Object^ coreDispatcherObj); + + static Windows::UI::Core::CoreDispatcher^ _s_dispatcher; +#endif + +#if (XSAPI_SERVER || UNIT_TEST_SYSTEM) + /// + /// Sets the SSL Cert + /// + static void _Set_SSL_cert(_In_ cert_context cert); + + static cert_context _s_certContext; +#endif + + void _Raise_service_call_routed_event(_In_ const xbox::services::xbox_service_call_routed_event_args& result); + bool _Is_disable_asserts_for_xbox_live_throttling_in_dev_sandboxes(); + bool _Is_disable_asserts_for_max_number_of_websockets_activated(); + +private: + + bool m_enableServiceCallRoutedEvents; + std::chrono::seconds m_httpTimeout; + std::chrono::seconds m_longHttpTimeout; + std::chrono::seconds m_httpRetryDelay; + std::chrono::seconds m_httpTimeoutWindow; + + std::mutex m_writeLock; + std::unordered_map> m_serviceCallRoutedHandlers; + function_context m_serviceCallRoutedHandlersCounter; + + std::chrono::seconds m_websocketTimeoutWindow; + bool m_useCoreDispatcherForEventRouting; + bool m_disableAssertsForXboxLiveThrottlingInDevSandboxes; + bool m_disableAssertsForMaxNumberOfWebsocketsActivated; +}; + + +}} diff --git a/Include/xsapi/xbox_service_call_routed_event_args.h b/Include/xsapi/xbox_service_call_routed_event_args.h new file mode 100644 index 00000000..64f7e5ce --- /dev/null +++ b/Include/xsapi/xbox_service_call_routed_event_args.h @@ -0,0 +1,141 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/http_call_request_message.h" + +namespace xbox { namespace services { + +/// +/// Contains information about a service call. +/// +class xbox_service_call_routed_event_args +{ +public: + + /// + /// Returns the XboxUserId of the User contacting the service + /// + _XSAPIIMP const string_t& xbox_user_id() const { return m_xboxUserId; } + + /// + /// Returns the HTTP method used to contact the service. For example, "GET". + /// + _XSAPIIMP const string_t& http_method() const { return m_httpMethod; } + + /// + /// Returns the URI used to contact the service. + /// + _XSAPIIMP const string_t& uri() const { return m_uri; } + + /// + /// Returns the request headers that were sent to the service. + /// + _XSAPIIMP const string_t& request_headers() const { return m_requestHeaders; } + + /// + /// Returns the request body that was sent to the service. + /// + _XSAPIIMP const http_call_request_message& request_body() const { return m_requestBody; } + + /// + /// Returns the number of responses in this session. + /// + _XSAPIIMP uint32_t response_count() const { return m_responseCount; } + + /// + /// Returns the response headers returned by the service. + /// + _XSAPIIMP const string_t& response_headers() const { return m_responseHeaders; } + + /// + /// Returns the response body returned by the service. + /// + _XSAPIIMP const string_t& response_body() const { return m_responseBody; } + + /// + /// Returns the ETag returned by the service. + /// + _XSAPIIMP const string_t& etag() const { return m_etag; } + + /// + /// Returns the authentication token returned by GetTokenAndSignatureAsync. + /// + _XSAPIIMP const string_t& token() const { return m_token; } + + /// + /// Returns the authentication signature returned by GetTokenAndSignatureAsync. + /// + _XSAPIIMP const string_t& signature() const { return m_signature; } + + /// + /// Returns the HTTP status code. For example, 200. + /// + _XSAPIIMP uint32_t http_status() const { return m_httpStatus; } + + /// + /// Returns the a full response log formatted message of all the properties in XboxServiceCallRoutedEventArgs. + /// + _XSAPIIMP const string_t full_response_formatted() const; + + /// + /// Returns the time when the request was sent. + /// + _XSAPIIMP const chrono_clock_t::time_point& request_time() const { return m_requestTime; } + + /// + /// Returns the time when the response was received. + /// + _XSAPIIMP const chrono_clock_t::time_point& response_time() const { return m_responseTime; } + + /// + /// Returns the elapsed time span between sending a request and receiving a response. + /// + _XSAPIIMP const std::chrono::milliseconds& elapsed_call_time() const { return m_elapsedCallTime; } + + /// + /// Internal function + /// + xbox_service_call_routed_event_args( + _In_ string_t xboxUserId, + _In_ string_t httpMethod, + _In_ string_t uri, + _In_ string_t requestHeaders, + _In_ http_call_request_message requestBody, + _In_ uint32_t responseCount, + _In_ string_t responseHeaders, + _In_ string_t responseBody, + _In_ string_t etag, + _In_ string_t token, + _In_ string_t signature, + _In_ uint32_t httpStatus, + _In_ chrono_clock_t::time_point requestTime, + _In_ chrono_clock_t::time_point responseTime + ); + +private: + string_t m_xboxUserId; + string_t m_httpMethod; + string_t m_uri; + string_t m_requestHeaders; + http_call_request_message m_requestBody; + uint32_t m_responseCount; + string_t m_responseHeaders; + string_t m_responseBody; + string_t m_etag; + string_t m_token; + string_t m_signature; + uint32_t m_httpStatus; + std::chrono::milliseconds m_elapsedCallTime; + chrono_clock_t::time_point m_requestTime; + chrono_clock_t::time_point m_responseTime; +}; + + +}} \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..100220a6 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,11 @@ +Microsoft Xbox Live Service API (XSAPI) + +The MIT License (MIT) +Copyright (c) 2016 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/README.md b/README.md index 52a0c49a..b004ac33 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,30 @@ -# xbox-live-api +## Welcome! The Microsoft Xbox Live Service API (XSAPI) enables game developers to access Xbox Live. To get access to the Xbox Live service, please apply to the ID@Xbox program at http://www.xbox.com/en-us/Developers/id + + +## What's in the API: + +* Xbox Live Features - profile, social, presence, leaderboards, achievements, multiplayer, matchmaking, title storage +* Platforms - Windows Store, Xbox One XDK, iOS, and Android +* Support for Visual Studio 2012 and 2015 +* NuGet package with binaries for Windows and Xbox One platforms + +## Contribute Back! + +Is there a feature missing that you'd like to see, or found a bug that you have a fix for? Or do you have an idea or just interest in helping out in building the library? Let us know and we'd love to work with you. For a good starting point on where we are headed and feature ideas, take a look at our [requested features and bugs](https://github.com/Microsoft/xbox-live-api/issues). + +Big or small we'd like to take your contributions back to help improve the Xbox Live Service API for everyone. + +## Having Trouble? + +We'd love to get your review score, whether good or bad, but even more than that, we want to fix your problem. If you submit your issue as a Review, we won't be able to respond to your problem and ask any follow-up questions that may be necessary. The most efficient way to do that is to open a an issue in our [issue tracker](https://github.com/Microsoft/xbox-live-api/issues). + +### Quick Links + +* [Issue Tracker](https://github.com/Microsoft/xbox-live-api/issues) +* [ID@Xbox](http://www.xbox.com/en-us/Developers/id +) + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + diff --git a/Source/Services/Achievements/WinRT/AchievementMediaAssetType_WinRT.h b/Source/Services/Achievements/WinRT/AchievementMediaAssetType_WinRT.h new file mode 100644 index 00000000..cf7d7746 --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementMediaAssetType_WinRT.h @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Enumeration values that indicate the media asset type associated with +/// the achievement. +/// +public enum class AchievementMediaAssetType +{ + /// The media asset type is unknown. + Unknown = xbox::services::achievements::achievement_media_asset_type::unknown, + + /// An icon media asset. + Icon = xbox::services::achievements::achievement_media_asset_type::icon, + + /// An art media asset. + Art = xbox::services::achievements::achievement_media_asset_type::art +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END diff --git a/Source/Services/Achievements/WinRT/AchievementOrderBy_WinRT.h b/Source/Services/Achievements/WinRT/AchievementOrderBy_WinRT.h new file mode 100644 index 00000000..0b871b46 --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementOrderBy_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// Enumeration values that indicate the achievement sort order. +public enum class AchievementOrderBy +{ + /// Default order does not guarantee sort order. + Default = xbox::services::achievements::achievement_order_by::default_order, + + /// Sort by title id. + TitleId = xbox::services::achievements::achievement_order_by::title_id, + + /// Sort by achievement unlock time. + UnlockTime = xbox::services::achievements::achievement_order_by::unlock_time +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/AchievementProgression_WinRT.cpp b/Source/Services/Achievements/WinRT/AchievementProgression_WinRT.cpp new file mode 100644 index 00000000..8dc3144e --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementProgression_WinRT.cpp @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "AchievementProgression_winrt.h" +#include "Utils_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::achievements; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +AchievementProgression::AchievementProgression( + _In_ xbox::services::achievements::achievement_progression cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_requirements = ref new Vector(); + auto& cppRequirements = m_cppObj.requirements(); + for (const auto& requirement : cppRequirements) + { + m_requirements->Append(ref new AchievementRequirement(requirement)); + } + +} + +IVectorView^ +AchievementProgression::Requirements::get() +{ + return m_requirements->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/AchievementProgression_WinRT.h b/Source/Services/Achievements/WinRT/AchievementProgression_WinRT.h new file mode 100644 index 00000000..6a1d9076 --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementProgression_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi\achievements.h" +#include "AchievementRequirement_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents progress details about the achievement, including requirements. +/// +public ref class AchievementProgression sealed +{ +public: + /// + /// The actions and conditions that are required to unlock the achievement. + /// + property Windows::Foundation::Collections::IVectorView^ Requirements { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The timestamp when the achievement was first unlocked. + /// + DEFINE_PROP_GET_DATETIME_OBJ(TimeUnlocked, time_unlocked); + +internal: + AchievementProgression( + _In_ xbox::services::achievements::achievement_progression cppObj + ); + +private: + xbox::services::achievements::achievement_progression m_cppObj; + Windows::Foundation::Collections::IVector^ m_requirements; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/AchievementRequirement_WinRT.h b/Source/Services/Achievements/WinRT/AchievementRequirement_WinRT.h new file mode 100644 index 00000000..5193c0bd --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementRequirement_WinRT.h @@ -0,0 +1,49 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents requirements for unlocking the achievement. +/// +public ref class AchievementRequirement sealed +{ +public: + /// + /// The achievement requirement ID. + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// A value that indicates the current progress of the player towards meeting + /// the requirement. + /// + DEFINE_PROP_GET_STR_OBJ(CurrentProgressValue, current_progress_value); + + /// + /// The target progress value that the player must reach in order to meet + /// the requirement. + /// + DEFINE_PROP_GET_STR_OBJ(TargetProgressValue, target_progress_value); + +internal: + AchievementRequirement( + _In_ xbox::services::achievements::achievement_requirement cppObj + ) : + m_cppObj(std::move(cppObj)) + { + } + +private: + xbox::services::achievements::achievement_requirement m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END diff --git a/Source/Services/Achievements/WinRT/AchievementRewardType_WinRT.h b/Source/Services/Achievements/WinRT/AchievementRewardType_WinRT.h new file mode 100644 index 00000000..731dc94e --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementRewardType_WinRT.h @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// Enumeration values that indicate the reward type for an achievement. +public enum class AchievementRewardType +{ + /// The reward type is unknown. + Unknown = xbox::services::achievements::achievement_reward_type::unknown, + + /// A Gamerscore reward. + Gamerscore = xbox::services::achievements::achievement_reward_type::gamerscore, + + /// An in-app reward, defined and delivered by the title. + InApp = xbox::services::achievements::achievement_reward_type::in_app, + + /// A digital art reward. + Art = xbox::services::achievements::achievement_reward_type::art +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END diff --git a/Source/Services/Achievements/WinRT/AchievementService_WinRT.cpp b/Source/Services/Achievements/WinRT/AchievementService_WinRT.cpp new file mode 100644 index 00000000..37413fef --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementService_WinRT.cpp @@ -0,0 +1,121 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "AchievementService_winrt.h" +#include "utils_winrt.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace concurrency; +using namespace xbox::services; +using namespace xbox::services::achievements; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +AchievementService::AchievementService( + _In_ xbox::services::achievements::achievement_service cppObj + ): + m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::IAsyncAction^ +AchievementService::UpdateAchievementAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ achievementId, + _In_ uint32 percentComplete + ) +{ + auto task = m_cppObj.update_achievement( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(achievementId), + percentComplete) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +AchievementService::UpdateAchievementAsync( + _In_ Platform::String^ xboxUserId, + _In_ uint32 titleId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ achievementId, + _In_ uint32 percentComplete + ) +{ + auto task = m_cppObj.update_achievement( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + titleId, + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(achievementId), + percentComplete) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +AchievementService::GetAchievementsForTitleIdAsync( + _In_ Platform::String^ xboxUserId, + _In_ uint32 titleId, + _In_ AchievementType type, + _In_ bool unlockedOnly, + _In_ AchievementOrderBy orderBy, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_achievements_for_title_id( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + titleId, + static_cast(type), + unlockedOnly, + static_cast(orderBy), + skipItems, + maxItems) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new AchievementsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +AchievementService::GetAchievementAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ achievementId + ) +{ + auto task = m_cppObj.get_achievement( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(achievementId)) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new Achievement(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/AchievementService_WinRT.h b/Source/Services/Achievements/WinRT/AchievementService_WinRT.h new file mode 100644 index 00000000..d0228d27 --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementService_WinRT.h @@ -0,0 +1,135 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/achievements.h" +#include "AchievementsResult_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents an endpoint that you can use to access the Achievement service. +/// +public ref class AchievementService sealed +{ +public: + /// + /// Allow achievement progress to be updated and achievements to be unlocked. + /// This API will work even when offline. On PC and Xbox One, updates will be + /// posted by the system when connection is re-established even if the title isn't running. + /// + /// The Xbox User ID of the player. + /// The achievement ID as defined by XDP or Dev Center. + /// The completion percentage of the achievement to indicate progress. + /// Valid values are from 1 to 100. Set to 100 to unlock the achievement. + /// Progress will be set by the server to the highest value sent + /// + /// Returns a task<T> object that represents the state of the asynchronous operation. + /// + /// This method calls V2 POST /users/xuid({xuid})/achievements/{scid}/update + /// + Windows::Foundation::IAsyncAction^ UpdateAchievementAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ achievementId, + _In_ uint32 percentComplete + ); + + /// + /// Allow achievement progress to be updated and achievements to be unlocked. + /// This API will work even when offline. On PC and Xbox One, updates will be + /// posted by the system when connection is re-established even if the title isn't running. + /// + /// The Xbox User ID of the player. + /// The title ID. + /// The service configuration ID (SCID) for the title. + /// The achievement ID as defined by XDP or Dev Center. + /// The completion percentage of the achievement to indicate progress. + /// Valid values are from 1 to 100. Set to 100 to unlock the achievement. + /// Progress will be set by the server to the highest value sent + /// + /// Returns a task<T> object that represents the state of the asynchronous operation. + /// + /// This method calls V2 POST /users/xuid({xuid})/achievements/{scid}/update + /// + Windows::Foundation::IAsyncAction^ UpdateAchievementAsync( + _In_ Platform::String^ xboxUserId, + _In_ uint32 titleId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ achievementId, + _In_ uint32 percentComplete + ); + + /// + /// Returns an AchievementsResult object containing the first page of achievements + /// for a player of the specified title. + /// + /// The Xbox User ID of the player. + /// The title ID. + /// The achievement type to retrieve. + /// Indicates whether to return unlocked achievements only. + /// Controls how the list of achievements is ordered. + /// The number of achievements to skip. + /// The maximum number of achievements the result can contain. Pass 0 to attempt + /// to retrieve all items. + /// An AchievementsResult object that contains a list of Achievement objects. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// See AchievementsResult::GetNextAsync to page in the next set of results. + /// + /// This method calls V2 GET /users/xuid({xuid})/achievements. + /// + Windows::Foundation::IAsyncOperation^ GetAchievementsForTitleIdAsync( + _In_ Platform::String^ xboxUserId, + _In_ uint32 titleId, + _In_ AchievementType type, + _In_ bool unlockedOnly, + _In_ AchievementOrderBy orderBy, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ); + + /// + /// Returns a specific Achievement object for a specified player. + /// + /// The Xbox User ID of the player. + /// The service configuration ID (SCID) for the service. + /// The achievement ID. + /// The requested Achievement object if it exists. + /// If the achievement does not exist, the method throws a Platform::COMException() exception, + /// with hr = INET_E_OBJECT_NOT_FOUND (0x800C0006L). + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// This method calls V2 GET /users/xuid({xuid})/achievements/{scid}/{achievementId}. + /// + Windows::Foundation::IAsyncOperation^ GetAchievementAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ achievementId + ); + +internal: + AchievementService( + _In_ xbox::services::achievements::achievement_service cppObj + ); + +private: + + xbox::services::achievements::achievement_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END diff --git a/Source/Services/Achievements/WinRT/AchievementType_WinRT.h b/Source/Services/Achievements/WinRT/AchievementType_WinRT.h new file mode 100644 index 00000000..0a3695d6 --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementType_WinRT.h @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// Enumeration values that indicate the achievement type. +public enum class AchievementType +{ + /// The achievement type is unknown. + Unknown = xbox::services::achievements::achievement_type::unknown, + + /// Used as a request input parameter. + /// All means to get all achievements regardless of type. + All = xbox::services::achievements::achievement_type::all, + + /// A persistent achievement that may be unlocked at any time. + /// Persistent achievements can give Gamerscore as a reward. + Persistent = xbox::services::achievements::achievement_type::persistent, + + /// A challenge achievement that can only be unlocked within a certain time period. + /// Challenge achievements can't give Gamerscore as a reward. + Challenge = xbox::services::achievements::achievement_type::challenge +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/Achievement_WinRT.cpp b/Source/Services/Achievements/WinRT/Achievement_WinRT.cpp new file mode 100644 index 00000000..3c76c138 --- /dev/null +++ b/Source/Services/Achievements/WinRT/Achievement_WinRT.cpp @@ -0,0 +1,79 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Achievement_winrt.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::achievements; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +Achievement::Achievement( + _In_ xbox::services::achievements::achievement cppObj + ): + m_cppObj(std::move(cppObj)) +{ + m_titleAssociations = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.title_associations()); + m_progression = ref new AchievementProgression(m_cppObj.progression()); + m_mediaAssets = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.media_assets()); + m_platformsAvailableOn = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.platforms_available_on()); + m_available = ref new AchievementTimeWindow(m_cppObj.available()); + m_rewards = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.rewards()); + m_estimatedUnlockTime = UtilsWinRT::ConvertSecondsToTimeSpan(m_cppObj.estimated_unlock_time()); +} + +IVectorView^ +Achievement::TitleAssociations::get() +{ + return m_titleAssociations->GetView(); +} + +AchievementProgression^ +Achievement::Progression::get() +{ + return m_progression; +} + +IVectorView^ +Achievement::MediaAssets::get() +{ + return m_mediaAssets->GetView(); +} + +IVectorView^ +Achievement::PlatformsAvailableOn::get() +{ + return m_platformsAvailableOn->GetView(); +} + +AchievementTimeWindow^ +Achievement::Available::get() +{ + return m_available; +} + +IVectorView^ +Achievement::Rewards::get() +{ + return m_rewards->GetView(); +} + +TimeSpan +Achievement::EstimatedUnlockTime::get() +{ + return m_estimatedUnlockTime; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/Achievement_WinRT.h b/Source/Services/Achievements/WinRT/Achievement_WinRT.h new file mode 100644 index 00000000..7c4ca1dc --- /dev/null +++ b/Source/Services/Achievements/WinRT/Achievement_WinRT.h @@ -0,0 +1,148 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/achievements.h" +#include "AchievementOrderBy_winrt.h" +#include "AchievementProgression_winrt.h" +#include "AchievementType_winrt.h" +#include "MediaAsset_winrt.h" +#include "TimeWindow_winrt.h" +#include "TitleAssociation_winrt.h" +#include "Reward_winrt.h" +#include "ParticipationType_winrt.h" +#include "ProgressState_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents an achievement, a system-wide mechanism for directing and +/// rewarding users' in-game actions consistently across all games. +/// +public ref class Achievement sealed +{ +public: + /// + /// The achievement ID. Can be a uint or a guid. + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// The ID of the service configuration set associated with the achievement. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The localized achievement name. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The game/app titles associated with the achievement. + /// + property Windows::Foundation::Collections::IVectorView^ TitleAssociations { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The state of a user's progress towards the earning of the achievement. + /// + DEFINE_PROP_GET_ENUM_OBJ(ProgressState, progress_state, Microsoft::Xbox::Services::Achievements::AchievementProgressState); + + /// + /// The progression object containing progress details about the achievement, + /// including requirements. + /// + property Microsoft::Xbox::Services::Achievements::AchievementProgression^ Progression { Microsoft::Xbox::Services::Achievements::AchievementProgression^ get(); } + + /// + /// The media assets associated with the achievement, such as image IDs. + /// + property Windows::Foundation::Collections::IVectorView^ MediaAssets { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The collection of platforms that the achievement is available on. + /// + property Windows::Foundation::Collections::IVectorView^ PlatformsAvailableOn { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// Whether or not the achievement is secret. + /// + DEFINE_PROP_GET_OBJ(IsSecret, is_secret, bool); + + /// + /// The description of the unlocked achievement. + /// + DEFINE_PROP_GET_STR_OBJ(UnlockedDescription, unlocked_description); + + /// + /// The description of the locked achievement. + /// + DEFINE_PROP_GET_STR_OBJ(LockedDescription, locked_description); + + /// + /// The ProductId the achievement was released with. This is a globally unique indentifier that + /// may correspond to an application, downloadable content, etc. + /// + DEFINE_PROP_GET_STR_OBJ(ProductId, product_id); + + /// + /// The type of achievement, such as a challenge achievement. + /// + DEFINE_PROP_GET_ENUM_OBJ(AchievementType, type, Microsoft::Xbox::Services::Achievements::AchievementType); + + /// + /// The participation type for the achievement, such as group or individual. + /// + DEFINE_PROP_GET_ENUM_OBJ(ParticipationType, participation_type, Microsoft::Xbox::Services::Achievements::AchievementParticipationType); + + /// + /// The time window during which the achievement is available. Applies to Challenges. + /// + property AchievementTimeWindow^ Available { AchievementTimeWindow^ get(); } + + /// + /// The collection of rewards that the player earns when the achievement is unlocked. + /// + property Windows::Foundation::Collections::IVectorView^ Rewards { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The estimated time that the achievement takes to be earned. + /// + property Windows::Foundation::TimeSpan EstimatedUnlockTime { Windows::Foundation::TimeSpan get(); } + + /// + /// A deeplink for clients that enables the title to lauch at a desired starting point + /// for the achievement. + /// + DEFINE_PROP_GET_STR_OBJ(DeepLink, deep_link); + + /// + /// A value that indicates whether or not the achievement is revoked by enforcement. + /// + DEFINE_PROP_GET_OBJ(IsRevoked, is_revoked, bool); + +internal: + Achievement( + _In_ xbox::services::achievements::achievement cppObj + ); + +private: + xbox::services::achievements::achievement m_cppObj; + Windows::Foundation::Collections::IVector^ m_titleAssociations; + Windows::Foundation::Collections::IVector^ m_mediaAssets; + Windows::Foundation::Collections::IVector^ m_platformsAvailableOn; + Microsoft::Xbox::Services::Achievements::AchievementType m_achievementType; + Microsoft::Xbox::Services::Achievements::AchievementParticipationType m_participationType; + AchievementTimeWindow^ m_available; + Windows::Foundation::Collections::IVector^ m_rewards; + Windows::Foundation::TimeSpan m_estimatedUnlockTime; + AchievementProgression^ m_progression; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/AchievementsResult_WinRT.cpp b/Source/Services/Achievements/WinRT/AchievementsResult_WinRT.cpp new file mode 100644 index 00000000..7d59037f --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementsResult_WinRT.cpp @@ -0,0 +1,55 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "AchievementsResult_winrt.h" +#include "AchievementService_winrt.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services; +using namespace xbox::services::achievements; +using namespace concurrency; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +AchievementsResult::AchievementsResult( + _In_ xbox::services::achievements::achievements_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_items = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.items()); +} + +IVectorView^ +AchievementsResult::Items::get() +{ + return m_items->GetView(); +} + +IAsyncOperation^ +AchievementsResult::GetNextAsync( + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new AchievementsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/AchievementsResult_WinRT.h b/Source/Services/Achievements/WinRT/AchievementsResult_WinRT.h new file mode 100644 index 00000000..23e6de58 --- /dev/null +++ b/Source/Services/Achievements/WinRT/AchievementsResult_WinRT.h @@ -0,0 +1,61 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "Achievement_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents a collection of Achievement class objects returned by a request. +/// +public ref class AchievementsResult sealed +{ +public: + /// + /// The collection of Achievement objects returned by a request. + /// + property Windows::Foundation::Collections::IVectorView^ Items { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// Returns an AchievementsResult object that contains the next page of achievements. + /// + /// The maximum number of items that the result can contain. Pass 0 to attempt + /// to retrieve all items. + /// An AchievementsResult object that contains a list of Achievement objects. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// This method calls V2 GET /users/xuid({xuid})/achievements. + /// + Windows::Foundation::IAsyncOperation^ GetNextAsync( + _In_ uint32 maxItems + ); + + /// + /// Returns a boolean value that indicates if there are more pages of achievements to retrieve. + /// + /// True if there are more pages, otherwise false. + DEFINE_PROP_GET_OBJ(HasNext, has_next, bool); + +internal: + AchievementsResult( + _In_ xbox::services::achievements::achievements_result cppObj + ); + +private: + xbox::services::achievements::achievements_result m_cppObj; + Windows::Foundation::Collections::IVector^ m_items; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/MediaAsset_WinRT.cpp b/Source/Services/Achievements/WinRT/MediaAsset_WinRT.cpp new file mode 100644 index 00000000..663b79b0 --- /dev/null +++ b/Source/Services/Achievements/WinRT/MediaAsset_WinRT.cpp @@ -0,0 +1,31 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MediaAsset_winrt.h" + +using namespace Platform; +using namespace Windows::Foundation; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +AchievementMediaAsset::AchievementMediaAsset( + _In_ xbox::services::achievements::achievement_media_asset cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +String^ +AchievementMediaAsset::Url::get() +{ + return ref new String(m_cppObj.url().to_string().c_str()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/MediaAsset_WinRT.h b/Source/Services/Achievements/WinRT/MediaAsset_WinRT.h new file mode 100644 index 00000000..59947f95 --- /dev/null +++ b/Source/Services/Achievements/WinRT/MediaAsset_WinRT.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/achievements.h" +#include "AchievementMediaAssetType_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents a media asset for an achievement. +/// +public ref class AchievementMediaAsset sealed +{ +public: + /// + /// The name of the media asset, such as "tile01". + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The type of media asset. + /// + DEFINE_PROP_GET_ENUM_OBJ(MediaAssetType, media_asset_type, Microsoft::Xbox::Services::Achievements::AchievementMediaAssetType); + + /// + /// The URL of the media asset. + /// + property Platform::String^ Url { Platform::String^ get(); } + +internal: + AchievementMediaAsset( + _In_ xbox::services::achievements::achievement_media_asset cppObj + ); + +private: + xbox::services::achievements::achievement_media_asset m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/ParticipationType_WinRT.h b/Source/Services/Achievements/WinRT/ParticipationType_WinRT.h new file mode 100644 index 00000000..4836095b --- /dev/null +++ b/Source/Services/Achievements/WinRT/ParticipationType_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// Enumeration values that indicate the participation type for an achievement. +public enum class AchievementParticipationType +{ + /// The participation type is unknown. + Unknown = xbox::services::achievements::achievement_participation_type::unknown, + + /// An achievement that can be earned as an individual participant. + Individual = xbox::services::achievements::achievement_participation_type::individual, + + /// An achievement that can be earned as a group participant. + Group = xbox::services::achievements::achievement_participation_type::group +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/ProgressState_WinRT.h b/Source/Services/Achievements/WinRT/ProgressState_WinRT.h new file mode 100644 index 00000000..2c8bf545 --- /dev/null +++ b/Source/Services/Achievements/WinRT/ProgressState_WinRT.h @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// Enumeration values that indicate the state of a player's progress towards unlocking an achievement. +public enum class AchievementProgressState +{ + /// Achievement progress is unknown. + Unknown = xbox::services::achievements::achievement_progress_state::unknown, + + /// Achievement has been earned. + Achieved = xbox::services::achievements::achievement_progress_state::achieved, + + /// Achievement progress has not been started. + NotStarted = xbox::services::achievements::achievement_progress_state::not_started, + + /// Achievement progress has started. + InProgress = xbox::services::achievements::achievement_progress_state::in_progress +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END diff --git a/Source/Services/Achievements/WinRT/Reward_WinRT.cpp b/Source/Services/Achievements/WinRT/Reward_WinRT.cpp new file mode 100644 index 00000000..f7242ce8 --- /dev/null +++ b/Source/Services/Achievements/WinRT/Reward_WinRT.cpp @@ -0,0 +1,58 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Reward_winrt.h" + +using namespace Microsoft::Xbox::Services::Achievements; +using namespace Microsoft::Xbox::Services; +using namespace Platform; +using namespace Windows::Foundation; + +AchievementReward::AchievementReward( + _In_ xbox::services::achievements::achievement_reward cppObj + ) : + m_cppObj(cppObj) +{ + m_valuePropertyType = ConvertStringToPropertyType(m_cppObj.value_type()); + m_mediaAsset = ref new AchievementMediaAsset(m_cppObj.media_asset()); +} + +PropertyType +AchievementReward::ValuePropertyType::get() +{ + return m_valuePropertyType; +} + +AchievementMediaAsset^ +AchievementReward::MediaAsset::get() +{ + return m_mediaAsset; +} + +PropertyType +AchievementReward::ConvertStringToPropertyType( + _In_ std::wstring value + ) +{ + if( value.empty() ) + { + return PropertyType::String; + } + else if( _wcsicmp(value.c_str(), L"Int") == 0 ) + { + return PropertyType::Int32; + } + else if( _wcsicmp(value.c_str(), L"Guid") == 0 ) + { + return PropertyType::Guid; + } + + return PropertyType::String; +} diff --git a/Source/Services/Achievements/WinRT/Reward_WinRT.h b/Source/Services/Achievements/WinRT/Reward_WinRT.h new file mode 100644 index 00000000..f70e1b3b --- /dev/null +++ b/Source/Services/Achievements/WinRT/Reward_WinRT.h @@ -0,0 +1,75 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/achievements.h" +#include "AchievementRewardType_winrt.h" +#include "MediaAsset_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents a reward that is associated with the achievement. +/// +public ref class AchievementReward sealed +{ +public: + /// + /// The localized reward name. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The description of the reward. + /// + DEFINE_PROP_GET_STR_OBJ(Description, description); + + /// + /// The title-defined reward value (data type and content varies by reward type). + /// + DEFINE_PROP_GET_STR_OBJ(Data, value); + + /// + /// The reward type. + /// + DEFINE_PROP_GET_ENUM_OBJ(RewardType, reward_type, Microsoft::Xbox::Services::Achievements::AchievementRewardType); + + /// + /// The property type of the reward value string. + /// + property Windows::Foundation::PropertyType ValuePropertyType { Windows::Foundation::PropertyType get(); } + + /// + /// The media asset associated with the reward. + /// If the RewardType is Gamerscore, this will be nullptr. + /// If the RewardType is InApp, this will be a media asset. + /// If the RewardType is Art, this may be a media asset or nullptr. + /// + property AchievementMediaAsset^ MediaAsset { AchievementMediaAsset^ get(); } + + +internal: + AchievementReward( + _In_ xbox::services::achievements::achievement_reward cppObj + ); + +private: + + static Windows::Foundation::PropertyType ConvertStringToPropertyType( + _In_ std::wstring value + ); + +private: + xbox::services::achievements::achievement_reward m_cppObj; + Windows::Foundation::PropertyType m_valuePropertyType; + AchievementMediaAsset^ m_mediaAsset; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/TimeWindow_WinRT.cpp b/Source/Services/Achievements/WinRT/TimeWindow_WinRT.cpp new file mode 100644 index 00000000..b8cd03f7 --- /dev/null +++ b/Source/Services/Achievements/WinRT/TimeWindow_WinRT.cpp @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TimeWindow_winrt.h" +#include "Utils_WinRT.h" + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +AchievementTimeWindow::AchievementTimeWindow( + _In_ xbox::services::achievements::achievement_time_window cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/TimeWindow_WinRT.h b/Source/Services/Achievements/WinRT/TimeWindow_WinRT.h new file mode 100644 index 00000000..165a828c --- /dev/null +++ b/Source/Services/Achievements/WinRT/TimeWindow_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/achievements.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents an interval of time during which an achievement can be unlocked. +/// This class is only used when the AchievementType enumeration is set to Challenge. +/// +public ref class AchievementTimeWindow sealed +{ +public: + /// + /// The start date and time of the achievement time window. + /// + DEFINE_PROP_GET_DATETIME_OBJ(StartDate, start_date); + + /// + /// The end date and time of the achievement time window. + /// + DEFINE_PROP_GET_DATETIME_OBJ(EndDate, end_date); + +internal: + AchievementTimeWindow( + _In_ xbox::services::achievements::achievement_time_window cppObj + ); + +private: + xbox::services::achievements::achievement_time_window m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END \ No newline at end of file diff --git a/Source/Services/Achievements/WinRT/TitleAssociation_WinRT.h b/Source/Services/Achievements/WinRT/TitleAssociation_WinRT.h new file mode 100644 index 00000000..f8a4e448 --- /dev/null +++ b/Source/Services/Achievements/WinRT/TitleAssociation_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_BEGIN + +/// +/// Represents the association between a title and achievements. +/// +public ref class AchievementTitleAssociation sealed +{ +public: + /// + /// The localized name of the title. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The title ID. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + +internal: + AchievementTitleAssociation( + _In_ xbox::services::achievements::achievement_title_association cppObj + ) :m_cppObj(std::move(cppObj)) + { + } + +private: + xbox::services::achievements::achievement_title_association m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_END diff --git a/Source/Services/Achievements/achievement.cpp b/Source/Services/Achievements/achievement.cpp new file mode 100644 index 00000000..d0d3d693 --- /dev/null +++ b/Source/Services/Achievements/achievement.cpp @@ -0,0 +1,263 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +static achievement_progress_state convert_string_to_progress_state( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return achievement_progress_state::unknown; + } + else if (utils::str_icmp(value, _T("Achieved")) == 0) + { + return achievement_progress_state::achieved; + } + else if (utils::str_icmp(value, _T("NotStarted")) == 0) + { + return achievement_progress_state::not_started; + } + else if (utils::str_icmp(value, _T("InProgress")) == 0) + { + return achievement_progress_state::in_progress; + } + + return achievement_progress_state::unknown; +} + +static achievement_type convert_string_to_achievement_type( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return achievement_type::unknown; + } + else if (utils::str_icmp(value, _T("Persistent")) == 0) + { + return achievement_type::persistent; + } + else if (utils::str_icmp(value, _T("Challenge")) == 0) + { + return achievement_type::challenge; + } + + return achievement_type::unknown; +} + +static achievement_participation_type convert_string_to_participation_type( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return achievement_participation_type::unknown; + } + else if (utils::str_icmp(value, _T("Individual")) == 0) + { + return achievement_participation_type::individual; + } + else if (utils::str_icmp(value, _T("Group")) == 0) + { + return achievement_participation_type::group; + } + + return achievement_participation_type::unknown; +} + +achievement::achievement() : + m_progressState(achievement_progress_state::unknown), + m_achievementType(achievement_type::unknown), + m_participationType(achievement_participation_type::unknown), + m_estimatedUnlockTime(0) +{ +} + +achievement::achievement( + _In_ string_t id, + _In_ string_t serviceConfigurationId, + _In_ string_t name, + _In_ std::vector titleAssociations, + _In_ achievement_progress_state progressState, + _In_ std::vector mediaAssets, + _In_ std::vector platformsAvailableOn, + _In_ bool isSecret, + _In_ string_t unlockedDescription, + _In_ string_t lockedDescription, + _In_ string_t productId, + _In_ achievement_type achievementType, + _In_ achievement_participation_type participationType, + _In_ achievement_time_window available, + _In_ std::vector rewards, + _In_ std::chrono::seconds estimatedUnlockTime, + _In_ string_t deepLink, + _In_ bool isRevoked, + _In_ achievement_progression progression + ) : + m_id(std::move(id)), + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_name(std::move(name)), + m_titleAssociations(std::move(titleAssociations)), + m_progressState(progressState), + m_mediaAssets(std::move(mediaAssets)), + m_platformsAvailableOn(std::move(platformsAvailableOn)), + m_isSecret(isSecret), + m_unlockedDescription(std::move(unlockedDescription)), + m_lockedDescription(std::move(lockedDescription)), + m_productId(std::move(productId)), + m_achievementType(achievementType), + m_participationType(participationType), + m_available(std::move(available)), + m_rewards(std::move(rewards)), + m_estimatedUnlockTime(std::move(estimatedUnlockTime)), + m_deepLink(std::move(deepLink)), + m_isRevoked(isRevoked), + m_progression(std::move(progression)) +{ +} + +const string_t& achievement::id() const +{ + return m_id; +} + +const string_t& achievement::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const string_t& achievement::name() const +{ + return m_name; +} + +const std::vector& achievement::title_associations() const +{ + return m_titleAssociations; +} + +achievement_progress_state achievement::progress_state() const +{ + return m_progressState; +} + +const achievement_progression& achievement::progression() const +{ + return m_progression; +} + +const std::vector& achievement::media_assets() const +{ + return m_mediaAssets; +} + +const std::vector& achievement::platforms_available_on() const +{ + return m_platformsAvailableOn; +} + +bool achievement::is_secret() const +{ + return m_isSecret; +} + +const string_t& achievement::unlocked_description() const +{ + return m_unlockedDescription; +} + +const string_t& achievement::locked_description() const +{ + return m_lockedDescription; +} + +const string_t& achievement::product_id() const +{ + return m_productId; +} + +achievement_type achievement::type() const +{ + return m_achievementType; +} + +achievement_participation_type achievement::participation_type() const +{ + return m_participationType; +} + +const achievement_time_window& achievement::available() const +{ + return m_available; +} + +const std::vector& achievement::rewards() const +{ + return m_rewards; +} + +const std::chrono::seconds& achievement::estimated_unlock_time() const +{ + return m_estimatedUnlockTime; +} + +const string_t& achievement::deep_link() const +{ + return m_deepLink; +} + +bool achievement::is_revoked() const +{ + return m_isRevoked; +} + +xbox_live_result +achievement::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errCode = xbox_live_error_code::no_error; + + achievement returnAchievement( + utils::extract_json_string(json, _T("id"), errCode, true), + utils::extract_json_string(json, _T("serviceConfigId"), errCode, true), + utils::extract_json_string(json, _T("name"), errCode, true), + utils::extract_json_vector(achievement_title_association::_Deserialize, json, _T("titleAssociations"), errCode, true), + convert_string_to_progress_state(utils::extract_json_string(json, _T("progressState"), true)), + utils::extract_json_vector(achievement_media_asset::_Deserialize, json, _T("mediaAssets"), errCode, true), + utils::extract_json_vector(utils::json_string_extractor, json, _T("platforms"), errCode, true), + utils::extract_json_bool(json, _T("isSecret")), + utils::extract_json_string(json, _T("description"), errCode, true), + utils::extract_json_string(json, _T("lockedDescription"), errCode, true), + utils::extract_json_string(json, _T("productId"), errCode, true), + convert_string_to_achievement_type(utils::extract_json_string(json, _T("achievementType"), errCode, true)), + convert_string_to_participation_type(utils::extract_json_string(json, _T("participationType"), errCode, true)), + utils::extract_json_object(achievement_time_window::_Deserialize, json, _T("timeWindow"), errCode, true), + utils::extract_json_vector(achievement_reward::_Deserialize, json, _T("rewards"), errCode, true), + utils::extract_json_string_timespan_in_seconds(json, _T("estimatedTime"), true), + utils::extract_json_string(json, _T("deeplink"), errCode, true), + utils::extract_json_bool(json, _T("isRevoked"), true, false), + utils::extract_json_object(achievement_progression::_Deserialize, json, _T("progression"), errCode, true) + ); + + return xbox_live_result(returnAchievement, errCode); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_media_asset.cpp b/Source/Services/Achievements/achievement_media_asset.cpp new file mode 100644 index 00000000..c55c2f28 --- /dev/null +++ b/Source/Services/Achievements/achievement_media_asset.cpp @@ -0,0 +1,87 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievement_media_asset::achievement_media_asset() +{ +} + +achievement_media_asset::achievement_media_asset( + _In_ string_t name, + _In_ achievement_media_asset_type type, + _In_ web::uri url + ) : + m_name(std::move(name)), + m_type(type), + m_url(std::move(url)) +{ +} + +const string_t& +achievement_media_asset::name() const +{ + return m_name; +} + +achievement_media_asset_type +achievement_media_asset::media_asset_type() const +{ + return m_type; +} + +const web::uri& +achievement_media_asset::url() const +{ + return m_url; +} + +achievement_media_asset_type +achievement_media_asset::_Convert_string_to_media_asset_type( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("Icon")) == 0) + { + return achievement_media_asset_type::icon; + } + else if (utils::str_icmp(value, _T("Art")) == 0) + { + return achievement_media_asset_type::art; + } + + return achievement_media_asset_type::unknown; +} + +xbox_live_result +achievement_media_asset::_Deserialize( +_In_ const web::json::value& json +) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto achievementMediaAsset = achievement_media_asset( + utils::extract_json_string(json, _T("name"), errc, true), + _Convert_string_to_media_asset_type(utils::extract_json_string(json, _T("type"), errc, true)), + utils::extract_json_string(json, _T("url"), errc, true) + ); + + return xbox_live_result(achievementMediaAsset, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_progression.cpp b/Source/Services/Achievements/achievement_progression.cpp new file mode 100644 index 00000000..1cdc43a1 --- /dev/null +++ b/Source/Services/Achievements/achievement_progression.cpp @@ -0,0 +1,59 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievement_progression::achievement_progression() +{ +} + +achievement_progression::achievement_progression( + _In_ std::vector requirements, + _In_ utility::datetime timeUnlocked + ): + m_requirements(std::move(requirements)), + m_timeUnlocked(std::move(timeUnlocked)) +{ +} + +const std::vector& +achievement_progression::requirements() const +{ + return m_requirements; +} + +const utility::datetime& +achievement_progression::time_unlocked() const +{ + return m_timeUnlocked; +} + +xbox_live_result +achievement_progression::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto achievementProgression = achievement_progression( + utils::extract_json_vector(achievement_requirement::_Deserialize, json, _T("requirements"), errc, true), + utils::extract_json_time(json, _T("timeUnlocked"), errc, true) + ); + + return xbox_live_result(achievementProgression, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_requirement.cpp b/Source/Services/Achievements/achievement_requirement.cpp new file mode 100644 index 00000000..7c6a7640 --- /dev/null +++ b/Source/Services/Achievements/achievement_requirement.cpp @@ -0,0 +1,71 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievement_requirement::achievement_requirement() +{ +} + +achievement_requirement::achievement_requirement( + _In_ string_t id, + _In_ string_t currentProgressValue, + _In_ string_t targetProgressValue + ) : + m_id(std::move(id)), + m_currentProgressValue(std::move(currentProgressValue)), + m_targetProgressValue(std::move(targetProgressValue)) +{ +} + +const string_t& +achievement_requirement::id() const +{ + return m_id; +} + +const string_t& +achievement_requirement::current_progress_value() const +{ + return m_currentProgressValue; +} + +const string_t& +achievement_requirement::target_progress_value() const +{ + return m_targetProgressValue; +} + +xbox_live_result +achievement_requirement::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto achievementRequirement = achievement_requirement( + utils::extract_json_string(json, _T("id"), errc, true), + utils::extract_json_string(json, _T("current"), errc, true), + utils::extract_json_string(json, _T("target"), errc, true) + ); + + return xbox_live_result(achievementRequirement, errc); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_reward.cpp b/Source/Services/Achievements/achievement_reward.cpp new file mode 100644 index 00000000..dce02790 --- /dev/null +++ b/Source/Services/Achievements/achievement_reward.cpp @@ -0,0 +1,115 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievement_reward::achievement_reward() +{ +} + +achievement_reward::achievement_reward( + _In_ string_t name, + _In_ string_t description, + _In_ string_t value, + _In_ achievement_reward_type rewardType, + _In_ string_t valuePropertyType, + _In_ achievement_media_asset mediaAsset + ) : + m_name(std::move(name)), + m_description(std::move(description)), + m_value(std::move(value)), + m_rewardType(std::move(rewardType)), + m_valuePropertyType(std::move(valuePropertyType)), + m_mediaAsset(std::move(mediaAsset)) +{ +} + +const string_t& achievement_reward::name() const +{ + return m_name; +} + +const string_t& achievement_reward::description() const +{ + return m_description; +} + +const string_t& achievement_reward::value() const +{ + return m_value; +} + +achievement_reward_type achievement_reward::reward_type() const +{ + return m_rewardType; +} + +const string_t& achievement_reward::value_type() const +{ + return m_valuePropertyType; +} + +const achievement_media_asset& achievement_reward::media_asset() const +{ + return m_mediaAsset; +} + +xbox_live_result +achievement_reward::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto achievementReward = achievement_reward( + utils::extract_json_string(json, _T("name"), errc, true), + utils::extract_json_string(json, _T("description"), errc, true), + utils::extract_json_string(json, _T("value"), errc, true), + convert_string_to_reward_type(utils::extract_json_string(json, _T("type"), errc, true)), + utils::extract_json_string(json, _T("valueType"), errc, true), + utils::extract_json_object(achievement_media_asset::_Deserialize, json, _T("mediaAsset"), errc, true) + ); + + return xbox_live_result(achievementReward, errc); +} + +achievement_reward_type achievement_reward::convert_string_to_reward_type( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return achievement_reward_type::unknown; + } + else if (utils::str_icmp(value, _T("Gamerscore")) == 0) + { + return achievement_reward_type::gamerscore; + } + else if (utils::str_icmp(value, _T("InApp")) == 0) + { + return achievement_reward_type::in_app; + } + else if (utils::str_icmp(value, _T("Art")) == 0) + { + return achievement_reward_type::art; + } + + return achievement_reward_type::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_service.cpp b/Source/Services/Achievements/achievement_service.cpp new file mode 100644 index 00000000..425dcb52 --- /dev/null +++ b/Source/Services/Achievements/achievement_service.cpp @@ -0,0 +1,586 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Utils.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xsapi/achievements.h" +#include "xsapi/services.h" +#include "xbox_live_context_impl.h" + +#if TV_API +#pragma pack(push, 16) +#include "EtwPlus.h" +#endif + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +#if TV_API +bool achievement_service::s_bHasInitialized = false; +GUID achievement_service::s_eventPlayerSessionId = {0}; +std::string achievement_service::s_eventProviderName; +std::mutex achievement_service::m_initLock; + +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR XSAPI_Update_Achievement_Fields[5] = +{ + {EtxFieldType_UnicodeString,0}, + {EtxFieldType_UnicodeString,0}, + {EtxFieldType_GUID,0}, + {EtxFieldType_UnicodeString,0}, + {EtxFieldType_UInt32,0} +}; + +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR XSAPI_Update_Achievement_Events[1] = +{ + { + { 1, 1, 0, 0, 0, 0, 0x0 }, + "AchievementUpdate", + "0.7.IGAU-1.0", + XSAPI_Update_Achievement_Fields, + 5, + 0, + EtxEventEnabledState_Undefined, + EtxEventEnabledState_ProviderDefault, + EtxPopulationSample_Undefined, + EtxPopulationSample_UseProviderPopulationSample, + EtxEventLatency_Undefined, + EtxEventLatency_ProviderDefault, + EtxEventPriority_Undefined, + EtxEventPriority_ProviderDefault + } +}; + +EXTERN_C __declspec(selectany) REGHANDLE XSAPI_Update_Achievement_Handle = (REGHANDLE)0; + +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR XSAPI_Update_Achievement_Provider = +{ + "", + {0}, + 1, + (ETX_EVENT_DESCRIPTOR*)&XSAPI_Update_Achievement_Events, + 0, + EtxProviderEnabledState_Undefined, + EtxProviderEnabledState_OnByDefault, + 0, + 100, + EtxProviderLatency_Undefined, + EtxProviderLatency_RealTime, + EtxProviderPriority_Undefined, + EtxProviderPriority_Critical +}; +#endif + +achievement_service::achievement_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::weak_ptr xboxLiveContextImpl + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_xboxLiveContextImpl(std::move(xboxLiveContextImpl)) +{ +} + +pplx::task> +achievement_service::update_achievement( + _In_ const string_t& xboxUserId, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ) +{ + uint32_t titleId = m_appConfig->title_id(); + const string_t& serviceConfigurationId = m_appConfig->scid(); + + return update_achievement(xboxUserId, titleId, serviceConfigurationId, achievementId, percentComplete); +} + + +pplx::task> +achievement_service::update_achievement( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserId.empty(), void, "xbox user id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(serviceConfigurationId.empty(), void, "serviceConfigurationId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(achievementId.empty(), void, "achievementId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(percentComplete > 100, void, "percentComplete is greater than 100"); + +#if TV_API + { + std::lock_guard lock(m_initLock); + if (!s_bHasInitialized) + { + HRESULT hr = CoCreateGuid(&s_eventPlayerSessionId); + if (FAILED(hr)) + { + return pplx::task_from_result(xbox::services::xbox_live_result(static_cast(hr))); + } + + std::error_code errC = utils::guid_from_string(serviceConfigurationId, const_cast(&XSAPI_Update_Achievement_Provider.Guid), false); + if (errC) + { + return pplx::task_from_result(xbox::services::xbox_live_result(errC)); + } + + CHAR strTitleId[16] = ""; + sprintf_s( strTitleId, "%0.8X", titleId ); + + std::stringstream ss; + ss << "XSAPI_"; + ss << strTitleId; + s_eventProviderName = ss.str(); + XSAPI_Update_Achievement_Provider.Name = s_eventProviderName.c_str(); + + ULONG errorCode = EtxRegister(&XSAPI_Update_Achievement_Provider, &XSAPI_Update_Achievement_Handle); + hr = HRESULT_FROM_WIN32(errorCode); + if (FAILED(hr)) + { + return pplx::task_from_result(xbox::services::xbox_live_result(static_cast(hr))); + } + + s_bHasInitialized = true; + } + } +#endif + + auto subPath = update_achievement_sub_path( + xboxUserId, + serviceConfigurationId + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("achievements"), m_appConfig), + subPath, + xbox_live_api::update_achievement + ); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + web::json::value achievementJson; + achievementJson[_T("id")] = web::json::value::string(achievementId); + achievementJson[_T("percentComplete")] = web::json::value::number(static_cast(percentComplete)); + + web::json::value achievementsJson = web::json::value::array(); + achievementsJson[0] = achievementJson; + + web::json::value request; + request[_T("action")] = web::json::value::string(_T("progressUpdate")); + request[_T("serviceConfigId")] = web::json::value::string(serviceConfigurationId); + request[_T("titleId")] = web::json::value::number(titleId); + request[_T("userId")] = web::json::value::string(xboxUserId); + request[_T("achievements")] = achievementsJson; + + httpCall->set_request_body(request.serialize()); + + auto userContext = m_userContext; + auto xboxLiveContextImpl = m_xboxLiveContextImpl.lock(); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([userContext, xboxUserId, titleId, serviceConfigurationId, achievementId, percentComplete, xboxLiveContextImpl](std::shared_ptr response) + { + if (response->err_code() == xbox_live_error_condition::network || + response->err_code() == xbox_live_error_code::http_status_429_too_many_requests || + (response->err_code().value() >= 500 && response->err_code().value() < 600)) + { +#if TV_API | UWP_API + if( xboxLiveContextImpl ) + { + return write_offline_update_achievement( + xboxLiveContextImpl, + achievementId, + percentComplete + ); + } +#endif + + return xbox_live_result(response->err_code(), response->err_message()); + } + else + { + return xbox_live_result(response->err_code(), response->err_message()); + } + }); + + return utils::create_exception_free_task( + task + ); + +} + +#if TV_API + +ULONG +achievement_service::event_write_achievement_update( + _In_ PCWSTR userId, + _In_ PCWSTR achievementId, + _In_ const uint32_t percentComplete + ) +{ + if( achievementId == nullptr) return ERROR_BAD_ARGUMENTS; + if( userId == nullptr ) return ERROR_BAD_ARGUMENTS; + + static const uint32_t EventWriteAchievementUpdate_ArgCount = 5; + static const uint32_t EventWriteAchievementUpdate_ScratchSize = 64; + EVENT_DATA_DESCRIPTOR eventData[EventWriteAchievementUpdate_ArgCount] = {0}; + UINT8 scratch[EventWriteAchievementUpdate_ScratchSize] = {0}; + + EtxFillCommonFields_v7(&eventData[0], scratch, EventWriteAchievementUpdate_ScratchSize); + + EventDataDescCreate(&eventData[1], userId, (ULONG)((wcslen(userId) + 1) * sizeof(WCHAR))); + EventDataDescCreate(&eventData[2], &s_eventPlayerSessionId, sizeof(GUID)); + EventDataDescCreate(&eventData[3], achievementId, (ULONG)((wcslen(achievementId) + 1) * sizeof(WCHAR))); + EventDataDescCreate(&eventData[4], &percentComplete, sizeof(percentComplete)); + + return EtxEventWrite( + &XSAPI_Update_Achievement_Events[0], + &XSAPI_Update_Achievement_Provider, + XSAPI_Update_Achievement_Handle, + EventWriteAchievementUpdate_ArgCount, + eventData + ); +} + +xbox::services::xbox_live_result +achievement_service::write_offline_update_achievement( + _In_ std::shared_ptr xboxLiveContextImpl, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ) +{ + ULONG errorCode = event_write_achievement_update( + xboxLiveContextImpl->xbox_live_user_id().c_str(), + achievementId.c_str(), + percentComplete + ); + HRESULT hr = HRESULT_FROM_WIN32(errorCode); + std::error_code errc = static_cast(hr); + return xbox_live_result(errc); +} +#endif + +#if UWP_API +xbox::services::xbox_live_result +achievement_service::write_offline_update_achievement( + _In_ std::shared_ptr xboxLiveContextImpl, + _In_ const string_t& achievementId, + _In_ uint32_t percentComplete + ) +{ + web::json::value properties = web::json::value::object(); + properties[_T("AchievementId")] = web::json::value(achievementId); + properties[_T("PercentComplete")] = percentComplete; + web::json::value measurements = web::json::value::object(); + return xboxLiveContextImpl->events_service().write_in_game_event(_T("AchievementUpdate"), properties, measurements); +} +#endif + +pplx::task> +achievement_service::get_achievements_for_title_id( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId, + _In_ achievement_type type, + _In_ bool unlockedOnly, + _In_ achievement_order_by orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserId.empty(), achievements_result, "xbox user id is empty"); + + std::vector titles; + titles.push_back(titleId); + + return get_achievements( + xboxUserId, + titles, + type, + unlockedOnly, + orderBy, + skipItems, + maxItems, + string_t() + ); +} + +pplx::task> +achievement_service::get_achievement( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& achievementId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserId.empty(), achievement, "xbox user id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(serviceConfigurationId.empty(), achievement, "service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(achievementId.empty(), achievement, "achievement id is empty"); + + auto subPath = achievement_by_id_sub_path( + xboxUserId, + serviceConfigurationId, + achievementId + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("achievements"), m_appConfig), + subPath, + xbox_live_api::get_achievement + ); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto achievementResult = achievements_result::_Deserialize(response->response_body_json()); + auto results = utils::generate_xbox_live_result( + achievementResult, + response + ); + + if (!results.err()) + { + if (results.payload().items().size() == 1) + { + const auto& achievementResult2 = results.payload().items()[0]; + return xbox_live_result(achievementResult2, results.err(), results.err_message()); + } + else if (results.payload().items().size() > 1) + { + return xbox_live_result(xbox_live_error_code::runtime_error, "Return payload was larger than expected"); + } + else + { + return xbox_live_result(xbox_live_error_code::runtime_error, "The achievement is not found"); + } + } + + return xbox_live_result(results.err(), results.err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +achievement_service::get_achievements( + _In_ const string_t& xboxUserId, + _In_ const std::vector& titleIds, + _In_ achievement_type type, + _In_ bool unlockedOnly, + _In_ achievement_order_by orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ) +{ + xbox_live_result stringType = convert_type_to_string(type); + RETURN_TASK_CPP_IF_ERR(stringType, achievements_result); + xbox_live_result orderType = convert_order_by_to_string(orderBy); + RETURN_TASK_CPP_IF_ERR(orderType, achievements_result); + + auto subPath = achievements_sub_path( + xboxUserId, + titleIds, + stringType.payload(), + unlockedOnly, + orderType.payload(), + skipItems, + maxItems, + continuationToken + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("achievements"), m_appConfig), + subPath, + xbox_live_api::get_achievements + ); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + auto xboxLiveContextImpl = m_xboxLiveContextImpl; + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([userContext, xboxLiveContextSettings, appConfig, xboxLiveContextImpl, xboxUserId, titleIds, type, unlockedOnly, orderBy](std::shared_ptr response) + { + if (response->response_body_json().size() > 0) + { + auto jsonResult = xbox::services::achievements::achievements_result::_Deserialize(response->response_body_json()); + auto achievementsResult = utils::generate_xbox_live_result( + jsonResult, + response + ); + + auto& achievement = achievementsResult.payload(); + achievement._Init_next_page_info( + userContext, + xboxLiveContextSettings, + appConfig, + xboxLiveContextImpl, + xboxUserId, + titleIds, + type, + unlockedOnly, + orderBy + ); + + return achievementsResult; + } + else + { + return xbox_live_result(response->err_code(), response->err_message()); + } + }); + + return utils::create_exception_free_task( + task + ); +} + +xbox_live_result +achievement_service::convert_type_to_string( + _In_ achievement_type type + ) +{ + switch (type) + { + case achievement_type::persistent: + return xbox_live_result(_T("persistent")); + + case achievement_type::challenge: + return xbox_live_result(_T("challenge")); + + case achievement_type::all: + return xbox_live_result(string_t()); + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Unsupported achievement type"); + } +} + +xbox_live_result +achievement_service::convert_order_by_to_string( + _In_ achievement_order_by orderBy + ) +{ + switch (orderBy) + { + case achievement_order_by::default_order: + return xbox_live_result(string_t()); + + case achievement_order_by::title_id: + return xbox_live_result(_T("title")); + + case achievement_order_by::unlock_time: + return xbox_live_result(_T("unlocktime")); + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Unsupported achievement order"); + } +} + +const string_t +achievement_service::achievements_sub_path( + _In_ const string_t& xboxUserId, + _In_ const std::vector& titleIds, + _In_ const string_t& type, + _In_ bool unlockedOnly, + _In_ const string_t& orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ) +{ + web::uri_builder subPathBuilder; + stringstream_t path; + path << _T("/users/xuid("); + path << xboxUserId; + path << _T(")/achievements"); + + subPathBuilder.append_path(path.str()); + + stringstream_t titleQuery; + auto &last = titleIds.back(); + for (const uint32_t& titleId : titleIds) + { + titleQuery << titleId; + if (&titleId != &last) + { + titleQuery << _T(","); + } + } + subPathBuilder.append_query(_T("titleId"), titleQuery.str()); + + if (!type.empty()) + { + subPathBuilder.append_query(_T("types"), type); + } + + if (unlockedOnly) + { + subPathBuilder.append_query(_T("unlockedOnly=true")); + } + + if (!orderBy.empty()) + { + subPathBuilder.append_query(_T("orderBy"), orderBy); + } + + utils::append_paging_info( + subPathBuilder, + skipItems, + maxItems, + continuationToken + ); + + return subPathBuilder.to_string(); +} + +const string_t +achievement_service::update_achievement_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId + ) +{ + stringstream_t ss; + ss << _T("/users/xuid(") << xboxUserId << _T(")/achievements/") << serviceConfigurationId << _T("/update"); + return ss.str(); +} + +const string_t +achievement_service::achievement_by_id_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& achievementId + ) +{ + stringstream_t ss; + ss << _T("/users/xuid(") << xboxUserId << _T(")/achievements/") << serviceConfigurationId << _T("/") << achievementId; + return ss.str(); +} + +#if TV_API +#pragma pack(pop) +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_time_window.cpp b/Source/Services/Achievements/achievement_time_window.cpp new file mode 100644 index 00000000..66be27e6 --- /dev/null +++ b/Source/Services/Achievements/achievement_time_window.cpp @@ -0,0 +1,59 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievement_time_window::achievement_time_window() +{ +} + +achievement_time_window::achievement_time_window( + _In_ utility::datetime startDate, + _In_ utility::datetime endDate + ): + m_startDate(std::move(startDate)), + m_endDate(std::move(endDate)) +{ +} + +const utility::datetime& achievement_time_window::start_date() const +{ + return m_startDate; +} + +const utility::datetime& achievement_time_window::end_date() const +{ + return m_endDate; +} + +xbox_live_result +achievement_time_window::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto achievementTimeWindow = achievement_time_window( + utils::extract_json_time(json, _T("startDate"), errc, true), + utils::extract_json_time(json, _T("endDate"), errc, true) + ); + + return xbox_live_result(achievementTimeWindow, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievement_title_association.cpp b/Source/Services/Achievements/achievement_title_association.cpp new file mode 100644 index 00000000..2f6b7df7 --- /dev/null +++ b/Source/Services/Achievements/achievement_title_association.cpp @@ -0,0 +1,59 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "utils.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievement_title_association::achievement_title_association() +{ +} + +achievement_title_association::achievement_title_association( + _In_ string_t name, + _In_ uint32_t id + ) : + m_name(std::move(name)), + m_id(id) +{ +} + +const string_t& +achievement_title_association::name() const +{ + return m_name; +} + +uint32_t +achievement_title_association::title_id() const +{ + return m_id; +} + +xbox_live_result +achievement_title_association::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto achievementTitleAssoication = achievement_title_association( + utils::extract_json_string(json, _T("name"), errc, true), + utils::extract_json_int(json, _T("id"), errc, true) + ); + + return xbox_live_result(achievementTitleAssoication, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Achievements/achievements_result.cpp b/Source/Services/Achievements/achievements_result.cpp new file mode 100644 index 00000000..479075dc --- /dev/null +++ b/Source/Services/Achievements/achievements_result.cpp @@ -0,0 +1,109 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/achievements.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_BEGIN + +achievements_result::achievements_result() +{ +} + +void achievements_result::_Init_next_page_info( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::weak_ptr xboxLiveContextImpl, + _In_ string_t xboxUserId, + _In_ std::vector titleIds, + _In_ achievement_type type, + _In_ bool unlockedOnly, + _In_ achievement_order_by orderBy + ) +{ + m_userContext = std::move(userContext); + m_xboxLiveContextSettings = std::move(xboxLiveContextSettings); + m_appConfig = std::move(appConfig); + m_xboxLiveContextImpl = std::move(xboxLiveContextImpl); + m_xboxUserId = std::move(xboxUserId); + m_titleIds = std::move(titleIds); + m_achievementType = type; + m_unlockedOnly = unlockedOnly; + m_orderBy = orderBy; +} + +const std::vector& +achievements_result::items() const +{ + return m_items; +} + +bool +achievements_result::has_next() +{ + return !m_continuationToken.empty(); +} + +pplx::task> +achievements_result::get_next( + _In_ uint32_t maxItems + ) +{ + if (m_continuationToken.empty()) + { + xbox_live_result results(xbox_live_error_code::out_of_range, "achievements_result doesn't have next page"); + return pplx::task_from_result>(results); + } + + return achievement_service( + m_userContext, + m_xboxLiveContextSettings, + m_appConfig, + m_xboxLiveContextImpl).get_achievements( + m_xboxUserId, + m_titleIds, + m_achievementType, + m_unlockedOnly, + m_orderBy, + 0, // use continuationToken, ignore skipItems. + maxItems, + m_continuationToken + ); +} + +xbox_live_result +achievements_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + achievements_result result; + + std::error_code errCode = xbox_live_error_code::no_error; + + result.m_items = utils::extract_json_vector(achievement::_Deserialize, json, _T("achievements"), errCode, true); + auto pageInfoJson = utils::extract_json_field(json, _T("pagingInfo"), errCode, false); + if (!pageInfoJson.is_null()) + { + result.m_continuationToken = utils::extract_json_string(pageInfoJson, _T("continuationToken"), errCode, true); + } + + return xbox_live_result(result, errCode); +} + + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ACHIEVEMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Common/Desktop/XboxLiveContext_Desktop.cpp b/Source/Services/Common/Desktop/XboxLiveContext_Desktop.cpp new file mode 100644 index 00000000..3f8e04b6 --- /dev/null +++ b/Source/Services/Common/Desktop/XboxLiveContext_Desktop.cpp @@ -0,0 +1,206 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/services.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xbox_live_context_impl.h" +#if !TV_API && !UNIT_TEST_SERVICES && !XSAPI_SERVER && !XSAPI_U +#include "Misc/notification_service.h" +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +#if TV_API | XBOX_UWP + +xbox_live_context::xbox_live_context( + _In_ Windows::Xbox::System::User^ user + ) +{ + m_xboxLiveContextImpl = std::make_shared(user); + m_xboxLiveContextImpl->init(); +} + +Windows::Xbox::System::User^ +xbox_live_context::user() +{ + return m_xboxLiveContextImpl->user(); +} + +#elif XSAPI_CPP + +xbox_live_context::xbox_live_context( + _In_ std::shared_ptr user + ) +{ + user->_User_impl()->set_user_pointer(user); + m_xboxLiveContextImpl = std::make_shared(user); + m_xboxLiveContextImpl->init(); +} + +std::shared_ptr +xbox_live_context::user() +{ + return m_xboxLiveContextImpl->user(); +} + +#else +xbox_live_context::xbox_live_context( + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user + ) +{ + m_xboxLiveContextImpl = std::make_shared(user); + m_xboxLiveContextImpl->init(); +} + +Microsoft::Xbox::Services::System::XboxLiveUser^ +xbox_live_context::user() +{ + return m_xboxLiveContextImpl->user(); +} +#endif + +const string_t& xbox_live_context::xbox_live_user_id() +{ + return m_xboxLiveContextImpl->xbox_live_user_id(); +} + +social::profile_service& +xbox_live_context::profile_service() +{ + return m_xboxLiveContextImpl->profile_service(); +} + +social::social_service& +xbox_live_context::social_service() +{ + return m_xboxLiveContextImpl->social_service(); +} + +social::reputation_service& +xbox_live_context::reputation_service() +{ + return m_xboxLiveContextImpl->reputation_service(); +} + +leaderboard::leaderboard_service& +xbox_live_context::leaderboard_service() +{ + return m_xboxLiveContextImpl->leaderboard_service(); +} + +achievements::achievement_service& +xbox_live_context::achievement_service() +{ + return m_xboxLiveContextImpl->achievement_service(); +} + +multiplayer::multiplayer_service& +xbox_live_context::multiplayer_service() +{ + return m_xboxLiveContextImpl->multiplayer_service(); +} + +matchmaking::matchmaking_service& +xbox_live_context::matchmaking_service() +{ + return m_xboxLiveContextImpl->matchmaking_service(); +} + +user_statistics::user_statistics_service& +xbox_live_context::user_statistics_service() +{ + return m_xboxLiveContextImpl->user_statistics_service(); +} + +const std::shared_ptr& +xbox_live_context::real_time_activity_service() +{ + return m_xboxLiveContextImpl->real_time_activity_service(); +} + +presence::presence_service& +xbox_live_context::presence_service() +{ + return m_xboxLiveContextImpl->presence_service(); +} + +game_server_platform::game_server_platform_service& +xbox_live_context::game_server_platform_service() +{ + return m_xboxLiveContextImpl->game_server_platform_service(); +} + +title_storage::title_storage_service& +xbox_live_context::title_storage_service() +{ + return m_xboxLiveContextImpl->title_storage_service(); +} + +privacy::privacy_service& +xbox_live_context::privacy_service() +{ + return m_xboxLiveContextImpl->privacy_service(); +} + +system::string_service& +xbox_live_context::string_service() +{ + return m_xboxLiveContextImpl->string_service(); +} + +contextual_search::contextual_search_service& +xbox_live_context::contextual_search_service() +{ + return m_xboxLiveContextImpl->contextual_search_service(); +} + +#if UWP_API || XSAPI_U +events::events_service& +xbox_live_context::events_service() +{ + return m_xboxLiveContextImpl->events_service(); +} +#endif + +#if TV_API || UNIT_TEST_SERVICES +marketplace::catalog_service& +xbox_live_context::catalog_service() +{ + return m_xboxLiveContextImpl->catalog_service(); +} + +marketplace::inventory_service& + xbox_live_context::inventory_service() +{ + return m_xboxLiveContextImpl->inventory_service(); +} + +entertainment_profile::entertainment_profile_list_service& +xbox_live_context::entertainment_profile_list_service() +{ + return m_xboxLiveContextImpl->entertainment_profile_list_service(); +} +#endif + +std::shared_ptr +xbox_live_context::settings() +{ + return m_xboxLiveContextImpl->settings(); +} + +std::shared_ptr +xbox_live_context::application_config() +{ + return m_xboxLiveContextImpl->application_config(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END \ No newline at end of file diff --git a/Source/Services/Common/Desktop/dllmain.cpp b/Source/Services/Common/Desktop/dllmain.cpp new file mode 100644 index 00000000..01f5b0a8 --- /dev/null +++ b/Source/Services/Common/Desktop/dllmain.cpp @@ -0,0 +1,19 @@ +#include "pch.h" + +BOOL APIENTRY DllMain( + HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/Source/Services/Common/Desktop/pch.cpp b/Source/Services/Common/Desktop/pch.cpp new file mode 100644 index 00000000..1d9f38c5 --- /dev/null +++ b/Source/Services/Common/Desktop/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/Source/Services/Common/Desktop/pch.h b/Source/Services/Common/Desktop/pch.h new file mode 100644 index 00000000..205ca751 --- /dev/null +++ b/Source/Services/Common/Desktop/pch.h @@ -0,0 +1,8 @@ +#pragma once + +#include "pch_common.h" + +#ifdef XSAPI_CPP +#undef XSAPI_CPP +#endif +#define XSAPI_CPP 1 diff --git a/Source/Services/Common/Server/xbox_live_context_server.cpp b/Source/Services/Common/Server/xbox_live_context_server.cpp new file mode 100644 index 00000000..3fa6abd2 --- /dev/null +++ b/Source/Services/Common/Server/xbox_live_context_server.cpp @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/services.h" +#include "xbox_system_factory.h" +#include "xbox_live_context_server_impl.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +xbox_live_server_context::xbox_live_server_context( + _In_ std::shared_ptr server + ) +{ + m_xboxLiveContextImpl = std::make_shared(server); + m_xboxLiveContextImpl->init(); +} + +/// +/// Returns the associated system User. +/// +std::shared_ptr +xbox_live_server_context::server() +{ + return m_xboxLiveContextImpl->server(); +} + +std::shared_ptr +xbox_live_server_context::settings() +{ + return m_xboxLiveContextImpl->settings(); +} + +std::shared_ptr +xbox_live_server_context::application_config() +{ + return m_xboxLiveContextImpl->application_config(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END \ No newline at end of file diff --git a/Source/Services/Common/Server/xbox_live_context_server_impl.cpp b/Source/Services/Common/Server/xbox_live_context_server_impl.cpp new file mode 100644 index 00000000..94f53e3a --- /dev/null +++ b/Source/Services/Common/Server/xbox_live_context_server_impl.cpp @@ -0,0 +1,60 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/services.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xbox_live_context_server_impl.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +xbox_live_context_server_impl::xbox_live_context_server_impl( + _In_ std::shared_ptr server + ) +{ + m_userContext = std::make_shared(server); +} + +std::shared_ptr +xbox_live_context_server_impl::server() +{ + return m_userContext->server(); +} + + +void xbox_live_context_server_impl::init() +{ + xbox_live_result servicesConfigFileReadResult; + + m_appConfig = xbox_live_app_config::get_app_config_singleton(); + + m_xboxLiveContextSettings = std::make_shared(); + +} + +std::shared_ptr xbox_live_context_server_impl::user_context() +{ + return m_userContext; +} + +std::shared_ptr +xbox_live_context_server_impl::settings() +{ + return m_xboxLiveContextSettings; +} + +std::shared_ptr +xbox_live_context_server_impl::application_config() +{ + return m_appConfig; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END \ No newline at end of file diff --git a/Source/Services/Common/Server/xbox_live_context_server_impl.h b/Source/Services/Common/Server/xbox_live_context_server_impl.h new file mode 100644 index 00000000..92dcc315 --- /dev/null +++ b/Source/Services/Common/Server/xbox_live_context_server_impl.h @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include + +#if !XSAPI_CPP +#include "User_WinRT.h" +#else +#include "xsapi/system.h" +#endif + +namespace xbox { namespace services { + +class xbox_live_context_server_impl : public std::enable_shared_from_this < xbox_live_context_server_impl > +{ +public: + + xbox_live_context_server_impl( + _In_ std::shared_ptr server + ); + + std::shared_ptr server(); + + /// + /// Returns an object containing settings that apply to all REST calls made such as retry and diagnostic settings. + /// + std::shared_ptr settings(); + + /// + /// Returns an object containing Xbox Live app config such as title ID + /// + std::shared_ptr application_config(); + + /// + /// Returns the current user context. + /// + std::shared_ptr user_context(); + + void init(); + +private: + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; +}; + +}} + + diff --git a/Source/Services/Common/Unix/pch.cpp b/Source/Services/Common/Unix/pch.cpp new file mode 100644 index 00000000..17305716 --- /dev/null +++ b/Source/Services/Common/Unix/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" \ No newline at end of file diff --git a/Source/Services/Common/Unix/pch.h b/Source/Services/Common/Unix/pch.h new file mode 100644 index 00000000..2772581d --- /dev/null +++ b/Source/Services/Common/Unix/pch.h @@ -0,0 +1,11 @@ +#pragma once + +#include "pch_common.h" + +#ifdef XSAPI_CPP +#undef XSAPI_CPP +#endif +#define XSAPI_CPP 1 +#define XSAPI_SERVER 0 + +#define LOG_U 1 \ No newline at end of file diff --git a/Source/Services/Common/Unix/pch_unix.cpp b/Source/Services/Common/Unix/pch_unix.cpp new file mode 100644 index 00000000..a949770d --- /dev/null +++ b/Source/Services/Common/Unix/pch_unix.cpp @@ -0,0 +1 @@ +#include "pch_unix.h" \ No newline at end of file diff --git a/Source/Services/Common/Unix/pch_unix.h b/Source/Services/Common/Unix/pch_unix.h new file mode 100644 index 00000000..719a588e --- /dev/null +++ b/Source/Services/Common/Unix/pch_unix.h @@ -0,0 +1,11 @@ +#pragma once + +#include "pch_common.h" + +#ifdef XSAPI_CPP +#undef XSAPI_CPP +#endif +#define XSAPI_CPP 1 +#define XSAPI_U 1 +#define XSAPI_SERVER 0 + diff --git a/Source/Services/Common/WinRT/XboxLiveContext_WinRT.cpp b/Source/Services/Common/WinRT/XboxLiveContext_WinRT.cpp new file mode 100644 index 00000000..f920244d --- /dev/null +++ b/Source/Services/Common/WinRT/XboxLiveContext_WinRT.cpp @@ -0,0 +1,291 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/services.h" +#include "../Common/xbox_live_context_impl.h" +#include "XboxLiveContext_WinRT.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#if !(TV_API | XBOX_UWP) +#include "User_WinRT.h" +#endif +#include "xsapi/profile.h" +#include "xsapi/contextual_search_service.h" +#include "xsapi/xbox_live_app_config.h" +#if !TV_API +#include "notification_service.h" +#endif +#include "presence_internal.h" + +using namespace Platform; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_BEGIN + +#if TV_API | XBOX_UWP +XboxLiveContext::XboxLiveContext( + _In_ Windows::Xbox::System::User^ user + ) +{ + m_cppObj = std::make_shared(user); + + Initialize(); +} + + +Windows::Xbox::System::User^ +XboxLiveContext::User::get() +{ + return m_cppObj->user(); +} + +#else +XboxLiveContext::XboxLiveContext( + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user + ) +{ + m_cppObj = std::make_shared(user); + + Initialize(); +} + +Microsoft::Xbox::Services::System::XboxLiveUser^ +XboxLiveContext::User::get() +{ + return m_cppObj->user(); +} +#endif + +void +XboxLiveContext::Initialize() +{ + m_xboxLiveContextSettings = ref new Microsoft::Xbox::Services::XboxLiveContextSettings(m_cppObj->settings()); + + auto appConfig = xbox::services::xbox_live_app_config::get_app_config_singleton(); + + m_appConfig = ref new Microsoft::Xbox::Services::XboxLiveAppConfiguration(appConfig); + + m_profileService = ref new Microsoft::Xbox::Services::Social::ProfileService( + m_cppObj->profile_service() + ); + + m_reputationService = ref new Microsoft::Xbox::Services::Social::ReputationService( + m_cppObj->reputation_service() + ); + + m_achievementService = ref new Microsoft::Xbox::Services::Achievements::AchievementService( + m_cppObj->achievement_service() + ); + + m_leaderboardService = ref new Leaderboard::LeaderboardService( + m_cppObj->leaderboard_service() + ); + + m_realTimeActivityService = ref new RealTimeActivity::RealTimeActivityService( + m_cppObj->real_time_activity_service() + ); + + m_multiplayerService = ref new Multiplayer::MultiplayerService( + m_cppObj->multiplayer_service() + ); + + m_userStatisticsService = ref new UserStatistics::UserStatisticsService( + m_cppObj->user_statistics_service() + ); + + m_matchmakingService = ref new Matchmaking::MatchmakingService( + m_cppObj->matchmaking_service() + ); + + m_presenceService = ref new Presence::PresenceService( + m_cppObj->presence_service() + ); + + m_gameServerPlatformService = ref new GameServerPlatform::GameServerPlatformService( + m_cppObj->game_server_platform_service() + ); + + m_titleStorageService = ref new TitleStorage::TitleStorageService( + m_cppObj->title_storage_service() + ); + + m_privacyService = ref new Privacy::PrivacyService( + m_cppObj->privacy_service() + ); + + m_socialService = ref new Microsoft::Xbox::Services::Social::SocialService( + m_cppObj->social_service() + ); + +#if UWP_API + m_eventsService = ref new Events::EventsService( + m_cppObj->events_service() + ); +#endif + +#if TV_API || UNIT_TEST_SERVICES + m_catalogService = ref new Marketplace::CatalogService( + m_cppObj->catalog_service() + ); + + m_inventoryService = ref new Marketplace::InventoryService( + m_cppObj->inventory_service() + ); + + m_entertainmentProfileListService = ref new Microsoft::Xbox::Services::EntertainmentProfile::EntertainmentProfileListService( + m_cppObj->entertainment_profile_list_service() + ); +#endif + m_stringService = ref new System::StringService( + m_cppObj->string_service() + ); + + m_contextualSearchService = ref new ContextualSearch::ContextualSearchService( + m_cppObj->contextual_search_service() + ); +} + +Social::ProfileService^ +XboxLiveContext::ProfileService::get() +{ + return m_profileService; +} + +Social::SocialService^ +XboxLiveContext::SocialService::get() +{ + return m_socialService; +} + +Social::ReputationService^ +XboxLiveContext::ReputationService::get() +{ + return m_reputationService; +} + +Achievements::AchievementService^ +XboxLiveContext::AchievementService::get() +{ + return m_achievementService; +} + +Leaderboard::LeaderboardService^ +XboxLiveContext::LeaderboardService::get() +{ + return m_leaderboardService; +} + +UserStatistics::UserStatisticsService^ +XboxLiveContext::UserStatisticsService::get() +{ + return m_userStatisticsService; +} + +Multiplayer::MultiplayerService^ +XboxLiveContext::MultiplayerService::get() +{ + return m_multiplayerService; +} + +Matchmaking::MatchmakingService^ +XboxLiveContext::MatchmakingService::get() +{ + return m_matchmakingService; +} + +RealTimeActivity::RealTimeActivityService^ +XboxLiveContext::RealTimeActivityService::get() +{ + return m_realTimeActivityService; +} + +Presence::PresenceService^ +XboxLiveContext::PresenceService::get() +{ + return m_presenceService; +} + +GameServerPlatform::GameServerPlatformService^ +XboxLiveContext::GameServerPlatformService::get() +{ + return m_gameServerPlatformService; +} + +TitleStorage::TitleStorageService^ +XboxLiveContext::TitleStorageService::get() +{ + return m_titleStorageService; +} + +Privacy::PrivacyService^ +XboxLiveContext::PrivacyService::get() +{ + return m_privacyService; +} + +System::StringService^ +XboxLiveContext::StringService::get() +{ + return m_stringService; +} + +ContextualSearch::ContextualSearchService^ +XboxLiveContext::ContextualSearchService::get() +{ + return m_contextualSearchService; +} + +#if UWP_API +Events::EventsService^ +XboxLiveContext::EventsService::get() +{ + return m_eventsService; +} +#endif + +#if TV_API || UNIT_TEST_SERVICES +Marketplace::CatalogService^ +XboxLiveContext::CatalogService::get() +{ + return m_catalogService; +} + +Marketplace::InventoryService^ +XboxLiveContext::InventoryService::get() +{ + return m_inventoryService; +} + +EntertainmentProfile::EntertainmentProfileListService^ +XboxLiveContext::EntertainmentProfileListService::get() +{ + return m_entertainmentProfileListService; +} +#endif + +Microsoft::Xbox::Services::XboxLiveContextSettings^ +XboxLiveContext::Settings::get() +{ + return m_xboxLiveContextSettings; +} + +Microsoft::Xbox::Services::XboxLiveAppConfiguration^ +XboxLiveContext::AppConfig::get() +{ + return m_appConfig; +} + +std::shared_ptr +XboxLiveContext::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_END \ No newline at end of file diff --git a/Source/Services/Common/WinRT/XboxLiveContext_WinRT.h b/Source/Services/Common/WinRT/XboxLiveContext_WinRT.h new file mode 100644 index 00000000..8f89528e --- /dev/null +++ b/Source/Services/Common/WinRT/XboxLiveContext_WinRT.h @@ -0,0 +1,216 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#if !TV_API +#include "User_WinRT.h" +#endif +#include "ProfileService_WinRT.h" +#include "SocialService_WinRT.h" +#include "ReputationService_WinRT.h" +#include "AppConfiguration_WinRT.h" +#include "Achievementservice_WinRT.h" +#include "LeaderboardService.h" +#include "UserStatisticsService_WinRT.h" +#include "MultiplayerService_WinRT.h" +#include "MatchmakingService_WinRT.h" +#include "XboxLiveContextSettings_WinRT.h" +#include "RealTimeActivityService_WinRT.h" +#include "PresenceService_WinRT.h" +#include "TitleStorageService_WinRT.h" +#include "GameServerPlatformService_WinRT.h" +#include "PrivacyService_WinRT.h" +#include "StringService_WinRT.h" +#include "EventsService_WinRT.h" +#include "ContextualSearchService_WinRT.h" +#if TV_API || UNIT_TEST_SERVICES +#include "CatalogService_WinRT.h" +#include "InventoryService_WinRT.h" +#include "EntertainmentProfileListService_WinRT.h" +#endif +#include "local_config.h" + +namespace xbox { namespace services { class xbox_live_context; } } + +NAMESPACE_MICROSOFT_XBOX_SERVICES_BEGIN + +/// +/// Defines methods used to retrieve objects that in turn provide access to different Xbox Live service components. +/// +/// Note: the XboxLiveContext is unique per instance. Changing state on one instance for a user does not affect a second instance of the context for the same user. Using multiple instances can therefore result in unexpected behavior. Titles should ensure to only use one instance of the XboxLiveContext per user. +/// +public ref class XboxLiveContext sealed +{ +public: + +#if TV_API | XBOX_UWP + XboxLiveContext(_In_ Windows::Xbox::System::User^ user); + + /// + /// Returns the associated system user. + /// + property Windows::Xbox::System::User^ User { Windows::Xbox::System::User^ get(); } + +#else + XboxLiveContext(_In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user); + + /// + /// Returns the associated system user. + /// + property Microsoft::Xbox::Services::System::XboxLiveUser^ User { Microsoft::Xbox::Services::System::XboxLiveUser^ get(); } + +#endif + + /// + /// Returns object containing access methods to the Xbox Profile service. + /// + property Social::ProfileService^ ProfileService { Social::ProfileService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Social service. + /// + property Social::SocialService^ SocialService { Social::SocialService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Reputation service. + /// + property Social::ReputationService^ ReputationService { Social::ReputationService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Achievement service. + /// + property Achievements::AchievementService^ AchievementService { Achievements::AchievementService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Leaderboard service. + /// + property Leaderboard::LeaderboardService^ LeaderboardService { Leaderboard::LeaderboardService^ get(); } + + /// + /// Returns object containing access methods to the Xbox User Stats service. + /// + property UserStatistics::UserStatisticsService^ UserStatisticsService { UserStatistics::UserStatisticsService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Matchmaking service. + /// + property Matchmaking::MatchmakingService^ MatchmakingService { Matchmaking::MatchmakingService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Multiplayer service. + /// + property Multiplayer::MultiplayerService^ MultiplayerService { Multiplayer::MultiplayerService^ get(); } + + /// + /// Returns object containing access methods to the Xbox Real Time Activity service. + /// + property RealTimeActivity::RealTimeActivityService^ RealTimeActivityService { RealTimeActivity::RealTimeActivityService^ get(); } + + /// + /// Returns object containing access methods to the Presence service. + /// + property Presence::PresenceService^ PresenceService { Presence::PresenceService^ get(); } + + /// + /// Returns object containing access methods to the GameServerPlatform service. + /// + property GameServerPlatform::GameServerPlatformService^ GameServerPlatformService { GameServerPlatform::GameServerPlatformService^ get(); } + + /// + /// Returns object containing access methods to the TitleStorage service. + /// + property TitleStorage::TitleStorageService^ TitleStorageService{ TitleStorage::TitleStorageService^ get(); } + + /// + /// Returns object containing access methods to the Privacy service. + /// + property Privacy::PrivacyService^ PrivacyService { Privacy::PrivacyService^ get(); } + + /// + /// Returns object containing access methods to the Xbox String service. + /// + property System::StringService^ StringService { System::StringService^ get(); } + + /// + /// Returns object containing access methods to the contextual search service. + /// + property ContextualSearch::ContextualSearchService^ ContextualSearchService { ContextualSearch::ContextualSearchService^ get(); } + +#if UWP_API + /// + /// Returns object containing access methods to the events service. + /// + property Events::EventsService^ EventsService { Events::EventsService^ get(); } +#endif + +#if TV_API || UNIT_TEST_SERVICES + /// + /// Returns object containing access methods to the Catalog service. + /// + property Marketplace::CatalogService^ CatalogService { Marketplace::CatalogService^ get(); } + + /// + /// Returns object containing access methods to the Inventory service. + /// + property Marketplace::InventoryService^ InventoryService { Marketplace::InventoryService^ get(); } + + /// + /// Returns object containing access methods to the Xbox String service. + /// + property EntertainmentProfile::EntertainmentProfileListService^ EntertainmentProfileListService { EntertainmentProfile::EntertainmentProfileListService^ get(); } +#endif // #if TV_API || UNIT_TEST_SERVICES + + /// + /// Returns an object containing settings that apply to all REST calls made such as retry and diagnostic settings. + /// + property Microsoft::Xbox::Services::XboxLiveContextSettings^ Settings { Microsoft::Xbox::Services::XboxLiveContextSettings^ get(); } + + /// + /// Returns an object containing Xbox Live app config such as title ID + /// + property Microsoft::Xbox::Services::XboxLiveAppConfiguration^ AppConfig { Microsoft::Xbox::Services::XboxLiveAppConfiguration^ get(); } + +internal: + std::shared_ptr GetCppObj() const; + +private: + void Initialize(); + + std::shared_ptr m_cppObj; + Microsoft::Xbox::Services::XboxLiveContextSettings^ m_xboxLiveContextSettings; + Microsoft::Xbox::Services::XboxLiveAppConfiguration^ m_appConfig; + Social::ProfileService^ m_profileService; + Social::SocialService^ m_socialService; + Social::ReputationService^ m_reputationService; + Achievements::AchievementService^ m_achievementService; + Leaderboard::LeaderboardService^ m_leaderboardService; + UserStatistics::UserStatisticsService^ m_userStatisticsService; + Multiplayer::MultiplayerService^ m_multiplayerService; + Matchmaking::MatchmakingService^ m_matchmakingService; + RealTimeActivity::RealTimeActivityService^ m_realTimeActivityService; + Presence::PresenceService^ m_presenceService; + GameServerPlatform::GameServerPlatformService^ m_gameServerPlatformService; + TitleStorage::TitleStorageService^ m_titleStorageService; + Privacy::PrivacyService^ m_privacyService; + ContextualSearch::ContextualSearchService^ m_contextualSearchService; + System::StringService^ m_stringService; +#if UWP_API + Events::EventsService^ m_eventsService; +#endif +#if TV_API || UNIT_TEST_SERVICES + Marketplace::CatalogService^ m_catalogService; + Marketplace::InventoryService^ m_inventoryService; + EntertainmentProfile::EntertainmentProfileListService^ m_entertainmentProfileListService; +#endif + + function_context m_signInContext; + function_context m_signOutContext; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_END diff --git a/Source/Services/Common/WinRT/pch.cpp b/Source/Services/Common/WinRT/pch.cpp new file mode 100644 index 00000000..b59bcecf --- /dev/null +++ b/Source/Services/Common/WinRT/pch.cpp @@ -0,0 +1,10 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" diff --git a/Source/Services/Common/WinRT/pch.h b/Source/Services/Common/WinRT/pch.h new file mode 100644 index 00000000..7547fefc --- /dev/null +++ b/Source/Services/Common/WinRT/pch.h @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch_common.h" + +#ifdef XSAPI_CPP +#undef XSAPI_CPP +#endif +#define XSAPI_CPP 0 + +#include +#include "Macros_WinRT.h" +#include "xsapi/errors.h" +#include "Utils_WinRT.h" \ No newline at end of file diff --git a/Source/Services/Common/iOS/pch.cpp b/Source/Services/Common/iOS/pch.cpp new file mode 100644 index 00000000..17305716 --- /dev/null +++ b/Source/Services/Common/iOS/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" \ No newline at end of file diff --git a/Source/Services/Common/iOS/pch.h b/Source/Services/Common/iOS/pch.h new file mode 100644 index 00000000..909ce9a4 --- /dev/null +++ b/Source/Services/Common/iOS/pch.h @@ -0,0 +1,5 @@ +#pragma once + +#include "pch_unix.h" + +#define XSAPI_I 1 \ No newline at end of file diff --git a/Source/Services/Common/pch_common.h b/Source/Services/Common/pch_common.h new file mode 100644 index 00000000..4b3142ef --- /dev/null +++ b/Source/Services/Common/pch_common.h @@ -0,0 +1,75 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#pragma warning(disable: 4503) // C4503: decorated name length exceeded, name was truncated +#pragma warning(disable: 4242) + +#ifdef _WIN32 +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. +#include + +// Windows +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#endif +#include +//#include +#else +#define __STDC_LIMIT_MACROS +#include + +#include +#endif +#if XSAPI_A +#define _NOEXCEPT noexcept +#endif + +// STL includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xsapi/types.h" + +#include +#include +#include // HTTP server +#include // JSON library +#include // URI library + +#include "shared_macros.h" +#if UWP_API +#include +#endif + +#include "xsapi/errors.h" +#include "utils.h" +#include "Logger/Log.h" + + +#ifndef _WIN32 +#define UNREFERENCED_PARAMETER(args) +#endif + +#ifndef max +#define max(x,y) std::max(x,y) +#endif + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) sizeof(x) / sizeof(x[0]) +#endif \ No newline at end of file diff --git a/Source/Services/Common/xbox_live_context_impl.cpp b/Source/Services/Common/xbox_live_context_impl.cpp new file mode 100644 index 00000000..25eda4c6 --- /dev/null +++ b/Source/Services/Common/xbox_live_context_impl.cpp @@ -0,0 +1,386 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/services.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xsapi/system.h" +#include "xbox_live_context_impl.h" +#if !TV_API && !UNIT_TEST_SERVICES && !XSAPI_SERVER +#include "notification_service.h" +#endif +#include "presence_internal.h" +#include "real_time_activity_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +#if TV_API | XBOX_UWP + +xbox_live_context_impl::xbox_live_context_impl( + _In_ Windows::Xbox::System::User^ user + ) : + m_signInContext(0), + m_signOutContext(0) +{ + m_userContext = std::make_shared(user); +} + +Windows::Xbox::System::User^ +xbox_live_context_impl::user() +{ + return m_userContext->user(); +} + +#else + +xbox_live_context_impl::xbox_live_context_impl( + _In_ std::shared_ptr user + ) : + m_signInContext(0), + m_signOutContext(0) +{ + user->_User_impl()->set_user_pointer(user); + m_userContext = std::make_shared(user); +} + +#if XSAPI_CPP +std::shared_ptr +xbox_live_context_impl::user() +{ + return m_userContext->user(); +} + +#else +xbox_live_context_impl::xbox_live_context_impl( + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user + ) : + m_signInContext(0), + m_signOutContext(0) +{ + m_userContext = std::make_shared(user); +} + +Microsoft::Xbox::Services::System::XboxLiveUser^ +xbox_live_context_impl::user() +{ + return m_userContext->user(); +} +#endif +#endif + +xbox_live_context_impl::~xbox_live_context_impl() +{ + if (m_userContext->user() != nullptr) + { +#if !TV_API && !UNIT_TEST_SERVICES && !XSAPI_SERVER +#if XSAPI_CPP + m_userContext->user()->_User_impl()->remove_sign_in_completed_handler( + m_signInContext + ); + + m_userContext->user()->_User_impl()->remove_sign_out_completed_handler( + m_signOutContext + ); +#else + m_userContext->user()->GetUserImpl()->remove_sign_in_completed_handler( + m_signInContext + ); + + m_userContext->user()->GetUserImpl()->remove_sign_out_completed_handler( + m_signOutContext + ); +#endif +#endif + } + + real_time_activity::real_time_activity_service_factory::get_singleton_instance()->remove_user_from_rta_map(m_userContext); +} + + +void xbox_live_context_impl::init() +{ + xbox_live_result servicesConfigFileReadResult; + + m_appConfig = xbox_live_app_config::get_app_config_singleton(); + m_xboxLiveContextSettings = std::make_shared(); + init_real_time_activity_service_instance(); + +#if TV_API || UWP_API + auto mainView = Windows::ApplicationModel::Core::CoreApplication::MainView; + if (mainView != nullptr) + { + auto coreWindow = mainView->CoreWindow; + if (coreWindow != nullptr) + { + auto dispatcher = coreWindow->Dispatcher; + if (dispatcher != nullptr) + { + dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([]() + { + xbox::services::service_call_logging_config::get_singleton_instance()->_Register_for_protocol_activation(); + })); + } + } + } + + xbox::services::service_call_logging_config::get_singleton_instance()->_ReadLocalConfig(); + +#endif + + std::weak_ptr thisWeakPtr = shared_from_this(); + + m_profileService = xbox::services::social::profile_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_reputationService = xbox::services::social::reputation_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_leaderboardService = xbox::services::leaderboard::leaderboard_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_achievementService = xbox::services::achievements::achievement_service(m_userContext, m_xboxLiveContextSettings, m_appConfig, thisWeakPtr); + m_matchmakingService = xbox::services::matchmaking::matchmaking_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_gameServerPlatformService = xbox::services::game_server_platform::game_server_platform_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_titleStorageService = xbox::services::title_storage::title_storage_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_privacyService = xbox::services::privacy::privacy_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_presenceService = xbox::services::presence::presence_service(m_userContext, m_xboxLiveContextSettings, m_appConfig, m_realTimeActivityService); + m_userStatisticsService = xbox::services::user_statistics::user_statistics_service(m_userContext, m_xboxLiveContextSettings, m_appConfig, m_realTimeActivityService); + m_multiplayerService = xbox::services::multiplayer::multiplayer_service(m_userContext, m_xboxLiveContextSettings, m_appConfig, m_realTimeActivityService); + m_socialService = xbox::services::social::social_service(m_userContext, m_xboxLiveContextSettings, m_appConfig, m_realTimeActivityService); + m_stringService = xbox::services::system::string_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_contextualSearchService = xbox::services::contextual_search::contextual_search_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + +#if !XSAPI_SERVER + +#if UWP_API || XSAPI_U + m_eventsService = events::events_service(m_userContext, m_appConfig); +#endif + +#if TV_API || UNIT_TEST_SERVICES + // These services are only on XDK + m_catalogService = marketplace::catalog_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_inventoryService = marketplace::inventory_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + m_entertainmentProfileService = entertainment_profile::entertainment_profile_list_service(m_userContext, m_xboxLiveContextSettings, m_appConfig); +#else + +#if !XBOX_UWP + + // Only start the presence writer on UAP + presence::presence_writer::get_presence_writer_singleton()->start_writer(m_presenceService._Impl()); + + auto notificationService = notification::notification_service::get_notification_service_singleton(); + notificationService->subscribe_to_notifications( + m_userContext, + m_xboxLiveContextSettings, + m_appConfig + ); + + if (m_userContext->user() != nullptr) + { +#if !TV_API && XSAPI_CPP + m_signInContext = m_userContext->user()->_User_impl()->add_sign_in_completed_handler( + [thisWeakPtr](const string_t& xboxUserId) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr && utils::str_icmp(pThis->xbox_live_user_id(), xboxUserId) == 0) + { + presence::presence_writer::get_presence_writer_singleton()->start_writer(pThis->m_presenceService._Impl()); + } + }); + + m_signOutContext = m_userContext->user()->_User_impl()->add_sign_out_completed_handler( + [thisWeakPtr](const system::sign_out_completed_event_args& args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->real_time_activity_service()->_Close_websocket(); + presence::presence_writer::get_presence_writer_singleton()->stop_writer(pThis->xbox_live_user_id()); + } + }); + +#elif !TV_API + m_signInContext = m_userContext->user()->GetUserImpl()->add_sign_in_completed_handler( + [thisWeakPtr](const string_t& xboxUserId) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr && utils::str_icmp(pThis->xbox_live_user_id(), xboxUserId) == 0) + { + presence::presence_writer::get_presence_writer_singleton()->start_writer(pThis->m_presenceService._Impl()); + } + }); + + m_signOutContext = m_userContext->user()->GetUserImpl()->add_sign_out_completed_handler( + [thisWeakPtr](const system::sign_out_completed_event_args& args) + { + UNREFERENCED_PARAMETER(args); + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->real_time_activity_service()->_Close_websocket(); + presence::presence_writer::get_presence_writer_singleton()->stop_writer(pThis->xbox_live_user_id()); + } + }); +#endif + } +#endif +#endif +#endif +} + +std::shared_ptr xbox_live_context_impl::user_context() +{ + return m_userContext; +} + +const string_t& xbox_live_context_impl::xbox_live_user_id() +{ + return m_userContext->xbox_user_id(); +} + +social::profile_service& +xbox_live_context_impl::profile_service() +{ + return m_profileService; +} + +social::social_service& +xbox_live_context_impl::social_service() +{ + return m_socialService; +} + +social::reputation_service& +xbox_live_context_impl::reputation_service() +{ + return m_reputationService; +} + +leaderboard::leaderboard_service& +xbox_live_context_impl::leaderboard_service() +{ + return m_leaderboardService; +} + +achievements::achievement_service& +xbox_live_context_impl::achievement_service() +{ + return m_achievementService; +} + +multiplayer::multiplayer_service& +xbox_live_context_impl::multiplayer_service() +{ + return m_multiplayerService; +} + +matchmaking::matchmaking_service& +xbox_live_context_impl::matchmaking_service() +{ + return m_matchmakingService; +} + +user_statistics::user_statistics_service& +xbox_live_context_impl::user_statistics_service() +{ + return m_userStatisticsService; +} + +void +xbox_live_context_impl::init_real_time_activity_service_instance() +{ + if (m_userContext->caller_context_type() == caller_context_type::title) + { + m_realTimeActivityService = std::shared_ptr(new xbox::services::real_time_activity::real_time_activity_service(m_userContext, m_xboxLiveContextSettings, m_appConfig)); + } + else + { + m_realTimeActivityService = real_time_activity::real_time_activity_service_factory::get_singleton_instance()->get_rta_instance(m_userContext, m_xboxLiveContextSettings, m_appConfig); + } +} + +const std::shared_ptr& +xbox_live_context_impl::real_time_activity_service() +{ + return m_realTimeActivityService; +} + +presence::presence_service& +xbox_live_context_impl::presence_service() +{ + return m_presenceService; +} + +game_server_platform::game_server_platform_service& +xbox_live_context_impl::game_server_platform_service() +{ + return m_gameServerPlatformService; +} + +title_storage::title_storage_service& +xbox_live_context_impl::title_storage_service() +{ + return m_titleStorageService; +} + +privacy::privacy_service& +xbox_live_context_impl::privacy_service() +{ + return m_privacyService; +} + +system::string_service& +xbox_live_context_impl::string_service() +{ + return m_stringService; +} + +contextual_search::contextual_search_service& +xbox_live_context_impl::contextual_search_service() +{ + return m_contextualSearchService; +} + +#if UWP_API || XSAPI_U +events::events_service& +xbox_live_context_impl::events_service() +{ + return m_eventsService; +} +#endif + +#if TV_API || UNIT_TEST_SERVICES +marketplace::catalog_service& +xbox_live_context_impl::catalog_service() +{ + return m_catalogService; +} + +marketplace::inventory_service& + xbox_live_context_impl::inventory_service() +{ + return m_inventoryService; +} +entertainment_profile::entertainment_profile_list_service& +xbox_live_context_impl::entertainment_profile_list_service() +{ + return m_entertainmentProfileService; +} +#endif + +std::shared_ptr +xbox_live_context_impl::settings() +{ + return m_xboxLiveContextSettings; +} + +std::shared_ptr +xbox_live_context_impl::application_config() +{ + return m_appConfig; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END \ No newline at end of file diff --git a/Source/Services/Common/xbox_live_context_impl.h b/Source/Services/Common/xbox_live_context_impl.h new file mode 100644 index 00000000..de116981 --- /dev/null +++ b/Source/Services/Common/xbox_live_context_impl.h @@ -0,0 +1,222 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#if !TV_API + +#if !XSAPI_CPP +#include "User_WinRT.h" +#else +#include "xsapi/system.h" +#endif + +#endif + +namespace xbox { namespace services { + +class xbox_live_context_impl : public std::enable_shared_from_this < xbox_live_context_impl > +{ +public: + +#if TV_API | XBOX_UWP + xbox_live_context_impl( + _In_ Windows::Xbox::System::User^ user + ); + + /// + /// Returns the associated system User + /// + Windows::Xbox::System::User^ user(); + +#else + xbox_live_context_impl( + _In_ std::shared_ptr user + ); +#if XSAPI_CPP + /// + /// Returns the associated system User. + /// + std::shared_ptr user(); + +#else + xbox_live_context_impl( + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user + ); + + /// + /// Returns the associated system XboxLiveUser. + /// + Microsoft::Xbox::Services::System::XboxLiveUser^ user(); +#endif +#endif + + ~xbox_live_context_impl(); + + /// + /// Returns the current user context. + /// + std::shared_ptr user_context(); + + /// + /// Returns the current user's Xbox Live User ID. + /// + const string_t& xbox_live_user_id(); + + /// + /// A service for managing user profiles. + /// + social::profile_service& profile_service(); + + /// + /// A service for managing social networking links. + /// + social::social_service& social_service(); + + /// + /// A service for managing reputation reports. + /// + social::reputation_service& reputation_service(); + + /// + /// A service for managing leaderboards. + /// + leaderboard::leaderboard_service& leaderboard_service(); + + /// + /// A service for managing achievements. + /// + achievements::achievement_service& achievement_service(); + + /// + /// A service for managing user statistics. + /// + user_statistics::user_statistics_service& user_statistics_service(); + + /// + /// A service for managing multiplayer games. + /// + multiplayer::multiplayer_service& multiplayer_service(); + + /// + /// A service for managing matchmaking sessions. + /// + matchmaking::matchmaking_service& matchmaking_service(); + + /// + /// Returns an object containing settings that apply to all REST calls made such as retry and diagnostic settings. + /// + std::shared_ptr settings(); + + /// + /// Returns an object containing Xbox Live app config such as title ID + /// + std::shared_ptr application_config(); + + /// + /// A service for managing real-time activity. + /// + const std::shared_ptr& real_time_activity_service(); + + /// + /// A service for using the Game Server Platform. + /// + game_server_platform::game_server_platform_service& game_server_platform_service(); + + /// + /// A service for managing Rich Presence. + /// + presence::presence_service& presence_service(); + + /// + /// A service for storing data in the cloud. + /// + title_storage::title_storage_service& title_storage_service(); + + /// + /// A service for managing privacy settings. + /// + privacy::privacy_service& privacy_service(); + + /// + /// A service used to check for offensive strings. + /// + system::string_service& string_service(); + + /// + /// A service for contextual search. + /// + contextual_search::contextual_search_service& contextual_search_service(); + +#if UWP_API || XSAPI_U + /// + /// A service used to write in game events. + /// + events::events_service& events_service(); +#endif + +#if TV_API || UNIT_TEST_SERVICES + /// + /// A service for managing catalogs. + /// + marketplace::catalog_service& catalog_service(); + + /// + /// A service for managing inventory. + /// + marketplace::inventory_service& inventory_service(); + + /// + /// A service for the entertainment profile. + /// + _XSAPIIMP entertainment_profile::entertainment_profile_list_service& entertainment_profile_list_service(); +#endif + + void init(); + void init_real_time_activity_service_instance(); + +private: + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + social::profile_service m_profileService; + social::social_service m_socialService; + social::reputation_service m_reputationService; + leaderboard::leaderboard_service m_leaderboardService; + achievements::achievement_service m_achievementService; + user_statistics::user_statistics_service m_userStatisticsService; + multiplayer::multiplayer_service m_multiplayerService; + matchmaking::matchmaking_service m_matchmakingService; + std::shared_ptr m_realTimeActivityService; + presence::presence_service m_presenceService; + game_server_platform::game_server_platform_service m_gameServerPlatformService; + title_storage::title_storage_service m_titleStorageService; + privacy::privacy_service m_privacyService; + system::string_service m_stringService; + contextual_search::contextual_search_service m_contextualSearchService; + +#if UWP_API || XSAPI_U + events::events_service m_eventsService; +#endif +#if TV_API || UNIT_TEST_SERVICES + marketplace::catalog_service m_catalogService; + marketplace::inventory_service m_inventoryService; + entertainment_profile::entertainment_profile_list_service m_entertainmentProfileService; +#endif + + function_context m_signInContext; + function_context m_signOutContext; + + friend class xbox_live_context; +}; + +}} + + diff --git a/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.cpp b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.cpp new file mode 100644 index 00000000..ba14b1b7 --- /dev/null +++ b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.cpp @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if TV_API || UNIT_TEST_SERVICES +#include "EntertainmentProfileListContainsItemResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_BEGIN + +EntertainmentProfileListContainsItemResult::EntertainmentProfileListContainsItemResult( + xbox::services::entertainment_profile::entertainment_profile_list_contains_item_result cppObj + ) : + m_cppObj(cppObj) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_END +#endif diff --git a/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.h b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.h new file mode 100644 index 00000000..8e97f42c --- /dev/null +++ b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListContainsItemResult_WinRT.h @@ -0,0 +1,42 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#if TV_API|| UNIT_TEST_SERVICES +#pragma once +#include "xsapi/entertainment_profile.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_BEGIN + +public ref class EntertainmentProfileListContainsItemResult sealed +{ +public: + /// + /// Specifies if the item is contained in the queue + /// + DEFINE_PROP_GET_OBJ(IsContained, is_contained, bool); + + /// + /// The Id that a provider (3rd party app) uses to identify a piece of content + /// + DEFINE_PROP_GET_STR_OBJ(ProviderId, provider_id); + + /// + /// The string used to identify the provider of the content + /// + DEFINE_PROP_GET_STR_OBJ(Provider, provider); + +internal: + EntertainmentProfileListContainsItemResult(xbox::services::entertainment_profile::entertainment_profile_list_contains_item_result cppObj); + +private: + xbox::services::entertainment_profile::entertainment_profile_list_contains_item_result m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_END +#endif diff --git a/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.cpp b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.cpp new file mode 100644 index 00000000..1061d566 --- /dev/null +++ b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.cpp @@ -0,0 +1,29 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if TV_API || UNIT_TEST_SERVICES +#include "EntertainmentProfileListService_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_BEGIN + +EntertainmentProfileListService::EntertainmentProfileListService( + _In_ xbox::services::entertainment_profile::entertainment_profile_list_service cppObj + ) : + m_cppObj(cppObj) +{ +} + +EntertainmentProfileListXboxOnePins^ +EntertainmentProfileListService::XboxOnePins::get() +{ + return ref new EntertainmentProfileListXboxOnePins(m_cppObj.xbox_one_pins()); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_END +#endif diff --git a/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.h b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.h new file mode 100644 index 00000000..157aca20 --- /dev/null +++ b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListService_WinRT.h @@ -0,0 +1,36 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#if TV_API || UNIT_TEST_SERVICES + +#include "EntertainmentProfileListVideoQueue_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_BEGIN + +public ref class EntertainmentProfileListService sealed +{ +public: + /// + /// Returns the XboxOne Pins + /// + property Microsoft::Xbox::Services::EntertainmentProfile::EntertainmentProfileListXboxOnePins^ + XboxOnePins { Microsoft::Xbox::Services::EntertainmentProfile::EntertainmentProfileListXboxOnePins^ get(); } + +internal: + EntertainmentProfileListService( + _In_ xbox::services::entertainment_profile::entertainment_profile_list_service cppObj + ); + +private: + xbox::services::entertainment_profile::entertainment_profile_list_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_END +#endif diff --git a/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.cpp b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.cpp new file mode 100644 index 00000000..ced910ec --- /dev/null +++ b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.cpp @@ -0,0 +1,93 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if TV_API || UNIT_TEST_SERVICES +#include "EntertainmentProfileListVideoQueue_WinRT.h" + +using namespace xbox::services; +using namespace xbox::services::entertainment_profile; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_BEGIN + +EntertainmentProfileListXboxOnePins::EntertainmentProfileListXboxOnePins( + _In_ xbox::services::entertainment_profile::entertainment_profile_list_xbox_one_pins cppObj + ) : + m_cppObj(cppObj) +{ +} + +Windows::Foundation::IAsyncAction^ +EntertainmentProfileListXboxOnePins::AddItemAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType itemType, + _In_ Platform::String^ providerId, + _In_ Platform::String^ provider, + _In_opt_ Windows::Foundation::Uri^ imageUrl, + _In_opt_ Windows::Foundation::Uri^ providerLogoImageUrl, + _In_opt_ Platform::String^ title, + _In_opt_ Platform::String^ subTitle, + _In_ Platform::String^ locale + ) +{ + auto task = m_cppObj.add_item( + static_cast(itemType), + STRING_T_FROM_PLATFORM_STRING(providerId), + STRING_T_FROM_PLATFORM_STRING(provider), + web::uri(STRING_T_FROM_PLATFORM_STRING(imageUrl->AbsoluteUri)), + web::uri(STRING_T_FROM_PLATFORM_STRING(providerLogoImageUrl->AbsoluteUri)), + STRING_T_FROM_PLATFORM_STRING(title), + STRING_T_FROM_PLATFORM_STRING(subTitle), + STRING_T_FROM_PLATFORM_STRING(locale)) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + }); + + return ASYNC_FROM_TASK(task); +} + + +Windows::Foundation::IAsyncAction^ +EntertainmentProfileListXboxOnePins::RemoveItemAsync( + _In_ Platform::String^ providerId, + _In_ Platform::String^ provider + ) +{ + auto task = m_cppObj.remove_item( + STRING_T_FROM_PLATFORM_STRING(providerId), + STRING_T_FROM_PLATFORM_STRING(provider)) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + }); + + return ASYNC_FROM_TASK(task); +} + + +Windows::Foundation::IAsyncOperation^ +EntertainmentProfileListXboxOnePins::ContainsItemAsync( + _In_ Platform::String^ providerId, + _In_ Platform::String^ provider + ) +{ + auto task = m_cppObj.contains_item( + STRING_T_FROM_PLATFORM_STRING(providerId), + STRING_T_FROM_PLATFORM_STRING(provider)) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new EntertainmentProfileListContainsItemResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_END +#endif diff --git a/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.h b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.h new file mode 100644 index 00000000..d16667c9 --- /dev/null +++ b/Source/Services/EntertainmentProfile/WinRT/EntertainmentProfileListVideoQueue_WinRT.h @@ -0,0 +1,76 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#if TV_API || UNIT_TEST_SERVICES +#include "xsapi/entertainment_profile.h" +#include "MediaItemType_WinRT.h" +#include "EntertainmentProfileListContainsItemResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_BEGIN + +public ref class EntertainmentProfileListXboxOnePins sealed +{ +public: + /// + /// Adds an item to the end of the video queue. + /// + /// The type of item being added to the video queue (Movie, TelevisionShow, TelevisionSeries, or TelevisionSeason). + /// The Id that a provider (3rd party app) uses to identify a piece of content. + /// The string used to identify the provider of the content. + /// A Url pointing to a box shot, cover art, etc that is representative of the content. (Optional) + /// A Url for the provider's logo image. (Optional) + /// The title of the item. (Optional) + /// The subtitle of the item. (Optional) + /// The locale of the item. + /// Calls V2 POST /users/xuid({xuid})/lists/PINS/XBLPins + Windows::Foundation::IAsyncAction^ AddItemAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType itemType, + _In_ Platform::String^ providerId, + _In_ Platform::String^ provider, + _In_opt_ Windows::Foundation::Uri^ imageUrl, + _In_opt_ Windows::Foundation::Uri^ providerLogoImageUrl, + _In_opt_ Platform::String^ title, + _In_opt_ Platform::String^ subTitle, + _In_ Platform::String^ locale + ); + + /// + /// Removes an item from the video queue. + /// + /// The Id that a provider (3rd party app) uses to identify a piece of content. + /// The string used to identify the provider of the content. + /// Calls V2 POST /users/xuid({xuid})/lists/PINS/XBLPins/RemoveItems + Windows::Foundation::IAsyncAction^ RemoveItemAsync( + _In_ Platform::String^ providerId, + _In_ Platform::String^ provider + ); + + /// + /// Determines if an item exists in the video queue. + /// + /// The Id that a provider (3rd party app) uses to identify a piece of content. + /// The string used to identify the provider of the content. + /// Calls V2 POST /users/xuid({xuid})/lists/PINS/XBLPins/ContainsItems + Windows::Foundation::IAsyncOperation^ ContainsItemAsync( + _In_ Platform::String^ providerId, + _In_ Platform::String^ provider + ); + +internal: + EntertainmentProfileListXboxOnePins( + _In_ xbox::services::entertainment_profile::entertainment_profile_list_xbox_one_pins cppObj + ); + +private: + xbox::services::entertainment_profile::entertainment_profile_list_xbox_one_pins m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_END +#endif diff --git a/Source/Services/EntertainmentProfile/entertainment_profile.cpp b/Source/Services/EntertainmentProfile/entertainment_profile.cpp new file mode 100644 index 00000000..8a7a44ec --- /dev/null +++ b/Source/Services/EntertainmentProfile/entertainment_profile.cpp @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "user_context.h" +#include "xsapi/entertainment_profile.h" +#if TV_API || UNIT_TEST_SERVICES + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_CPP_BEGIN + +entertainment_profile_list_service::entertainment_profile_list_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_xboxOnePins(m_userContext, m_xboxLiveContextSettings, m_appConfig) +{ +} + +entertainment_profile_list_xbox_one_pins& entertainment_profile_list_service::xbox_one_pins() +{ + return m_xboxOnePins; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_CPP_END +#endif diff --git a/Source/Services/EntertainmentProfile/entertainment_profile_list_contains_item_result.cpp b/Source/Services/EntertainmentProfile/entertainment_profile_list_contains_item_result.cpp new file mode 100644 index 00000000..480cb178 --- /dev/null +++ b/Source/Services/EntertainmentProfile/entertainment_profile_list_contains_item_result.cpp @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "user_context.h" +#include "xsapi/entertainment_profile.h" +#if TV_API || UNIT_TEST_SERVICES + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_CPP_BEGIN + +bool entertainment_profile_list_contains_item_result::is_contained() const +{ + return m_isContained; +} + +const string_t& entertainment_profile_list_contains_item_result::provider_id() const +{ + return m_providerId; +} + +const string_t& entertainment_profile_list_contains_item_result::provider() const +{ + return m_provider; +} + +xbox_live_result entertainment_profile_list_contains_item_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + std::error_code errCode; + + entertainment_profile_list_contains_item_result item; + + web::json::value itemJson = utils::extract_json_field(json, _T("ContainedItems"), errCode, true)[0]; + if(!itemJson.is_null()) + { + item.m_isContained = utils::extract_json_bool(itemJson, _T("Contained"), errCode, true); + web::json::value innerItemJson = utils::extract_json_field(itemJson, _T("Item"), errCode, false); + if(!innerItemJson.is_null()) + { + item.m_provider = utils::extract_json_string(innerItemJson, _T("Provider"), errCode, true); + item.m_providerId = utils::extract_json_string(innerItemJson, _T("ProviderId"), errCode, true); + } + } + + return xbox_live_result(item, errCode); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_CPP_END +#endif \ No newline at end of file diff --git a/Source/Services/EntertainmentProfile/entertainment_profile_list_xbox_one_pins.cpp b/Source/Services/EntertainmentProfile/entertainment_profile_list_xbox_one_pins.cpp new file mode 100644 index 00000000..0e91f7fa --- /dev/null +++ b/Source/Services/EntertainmentProfile/entertainment_profile_list_xbox_one_pins.cpp @@ -0,0 +1,230 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Utils.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xsapi/entertainment_profile.h" + +#if TV_API || UNIT_TEST_SERVICES +string_t c_entertainmentProfileListContractVersionHeaderValue = _T("2"); + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_CPP_BEGIN + +entertainment_profile_list_xbox_one_pins::entertainment_profile_list_xbox_one_pins( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> entertainment_profile_list_xbox_one_pins::add_item( + _In_ xbox::services::marketplace::media_item_type itemType, + _In_ const string_t& providerId, + _In_ const string_t& provider, + _In_ const web::uri& imageUrl, + _In_ const web::uri& providerLogoImageUrl, + _In_ const string_t& title, + _In_ const string_t& subTitle, + _In_ const string_t& locale + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(locale.empty(), void, "locale is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(provider.empty(), void, "provider is empty"); + + auto subPath = entertainment_profile_list_xbox_one_pins_add_item_sub_path(m_userContext->xbox_user_id()); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("eplists"), m_appConfig), + subPath, + xbox_live_api::xbox_one_pins_add_item + ); + + httpCall->set_xbox_contract_version_header_value(c_entertainmentProfileListContractVersionHeaderValue); + + web::json::value request; + web::json::value item; + item[_T("ContentType")] = web::json::value::string(xbox::services::marketplace::catalog_service::_Convert_media_item_type_to_string(itemType)); + if(providerId.empty()) + { + item[_T("ProviderId")] = web::json::value::null(); + } + else + { + item[_T("ProviderId")] = web::json::value::string(providerId); + } + item[_T("Provider")] = web::json::value::string(provider); + item[_T("Locale")] = web::json::value::string(locale); + if(!imageUrl.is_empty()) + { + item[_T("ImageUrl")] = web::json::value::string(imageUrl.to_string()); + } + if(!providerLogoImageUrl.is_empty()) + { + item[_T("AltImageUrl")] = web::json::value::string(providerLogoImageUrl.to_string()); + } + if(!title.empty()) + { + item[_T("Title")] = web::json::value::string(title); + } + if(!subTitle.empty()) + { + item[_T("SubTitle")] = web::json::value::string(subTitle); + } + std::vector items; + items.push_back(item); + request[_T("Items")] = web::json::value::array(items); + + httpCall->set_request_body(request); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> entertainment_profile_list_xbox_one_pins::remove_item( + _In_ const string_t& providerId, + _In_ const string_t& provider + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(provider.empty(), void, "provider is empty"); + + auto subPath = entertainment_profile_list_xbox_one_pins_remove_item_sub_path(m_userContext->xbox_user_id()); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("eplists"), m_appConfig), + subPath, + xbox_live_api::xbox_one_pins_remove_item + ); + + httpCall->set_xbox_contract_version_header_value(c_entertainmentProfileListContractVersionHeaderValue); + + web::json::value request; + web::json::value item; + if(providerId.empty()) + { + item[_T("ProviderId")] = web::json::value::Null; + } + else + { + item[_T("ProviderId")] = web::json::value::string(providerId); + } + item[_T("Provider")] = web::json::value::string(provider); + + std::vector items; + items.push_back(item); + request[_T("Items")] = web::json::value::array(items); + + httpCall->set_request_body(request); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + return utils::create_exception_free_task( + task + ); +} + +pplx::task> entertainment_profile_list_xbox_one_pins::contains_item( + _In_ const string_t& providerId, + _In_ const string_t& provider + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(provider.empty(), entertainment_profile_list_contains_item_result, "provider is empty"); + + auto subPath = entertainment_profile_list_xbox_one_pins_contains_item_sub_path(m_userContext->xbox_user_id()); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("eplists"), m_appConfig), + subPath, + xbox_live_api::xbox_one_pins_contains_item + ); + + httpCall->set_xbox_contract_version_header_value(c_entertainmentProfileListContractVersionHeaderValue); + + web::json::value request; + web::json::value item; + if(providerId.empty()) + { + item[_T("ProviderId")] = web::json::value::Null; + } + else + { + item[_T("ProviderId")] = web::json::value::string(providerId); + } + item[_T("Provider")] = web::json::value::string(provider); + + std::vector items; + items.push_back(item); + request[_T("Items")] = web::json::value::array(items); + + httpCall->set_request_body(request); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto itemResult = entertainment_profile_list_contains_item_result::_Deserialize(response->response_body_json()); + return utils::generate_xbox_live_result( + itemResult, + response + ); + }); + return utils::create_exception_free_task( + task + ); +} + +string_t entertainment_profile_list_xbox_one_pins::entertainment_profile_list_xbox_one_pins_add_item_sub_path( + _In_ const string_t& xboxUserId + ) +{ + stringstream_t ss; + ss << _T("/users/xuid(") << xboxUserId << _T(")/lists/PINS/XBLPins"); + return ss.str(); +} + +string_t entertainment_profile_list_xbox_one_pins::entertainment_profile_list_xbox_one_pins_remove_item_sub_path( + _In_ const string_t& xboxUserId + ) +{ + stringstream_t ss; + ss << _T("/users/xuid(") << xboxUserId << _T(")/lists/PINS/XBLPins/RemoveItems"); + return ss.str(); +} + +string_t entertainment_profile_list_xbox_one_pins::entertainment_profile_list_xbox_one_pins_contains_item_sub_path( + _In_ const string_t& xboxUserId + ) +{ + stringstream_t ss; + ss << _T("/users/xuid(") << xboxUserId << _T(")/lists/PINS/XBLPins/ContainsItems"); + return ss.str(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_ENTERTAINMENT_PROFILE_CPP_END +#endif \ No newline at end of file diff --git a/Source/Services/Events/WinRT/EventsService_WinRT.cpp b/Source/Services/Events/WinRT/EventsService_WinRT.cpp new file mode 100644 index 00000000..70ab87aa --- /dev/null +++ b/Source/Services/Events/WinRT/EventsService_WinRT.cpp @@ -0,0 +1,54 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !UNIT_TEST_SERVICES +#include "EventsService_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Concurrency; +using namespace xbox::services::events; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_EVENTS_BEGIN + +EventsService::EventsService( + _In_ xbox::services::events::events_service cppObj + ): + m_cppObj(std::move(cppObj)) +{ +} + +void +EventsService::WriteInGameEvent(_In_ Platform::String^ eventName) +{ + xbox_live_result result = m_cppObj.write_in_game_event(STRING_T_FROM_PLATFORM_STRING(eventName)); + THROW_IF_ERR(result); +} + +void EventsService::WriteInGameEvent( + _In_ Platform::String^ eventName, + _In_ Windows::Foundation::Collections::PropertySet^ dimensions, + _In_ Windows::Foundation::Collections::PropertySet^ measurements + ) +{ + xbox_live_result result = m_cppObj.write_in_game_event( + STRING_T_FROM_PLATFORM_STRING(eventName), + UtilsWinRT::JsonValueFromPropertySet(dimensions), + UtilsWinRT::JsonValueFromPropertySet(measurements) + ); + THROW_IF_ERR(result); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_EVENTS_END +#endif \ No newline at end of file diff --git a/Source/Services/Events/WinRT/EventsService_WinRT.h b/Source/Services/Events/WinRT/EventsService_WinRT.h new file mode 100644 index 00000000..cdd01718 --- /dev/null +++ b/Source/Services/Events/WinRT/EventsService_WinRT.h @@ -0,0 +1,75 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#if UWP_API + +#include "xsapi/events.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_EVENTS_BEGIN + +/// +/// Represents a service class that provides APIs that you can use to write in-game events +/// +public ref class EventsService sealed +{ +public: + /// + /// Write a simple in-game event without providing any data fields. + /// + /// Event name + /// + /// The name of the event must match the event name declared in the title's service configuration. + /// The names are case insensitive. + /// If the API writes an event with a name that does not match a name in the service configuration, the + /// service drops the event with no notification. + /// + void WriteInGameEvent(_In_ Platform::String^ eventName); + + /// + /// Write an in-game event that includes "dimension" and "measurement" data fields. + /// + /// Dimensions include event fields with a finite number of defined numeric or string values. + /// Examples of dimensions: map id, difficulty level, character or weapon class, game mode, boolean settings, etc. + /// + /// Measurements include event fields that represent scalar numeric metrics. + /// Examples of measurements: score, time, counters, position, etc. + /// + /// Example: for an in-game event that tracks the highest match score for a particular difficulty level: + /// The difficulty level should be included in dimensions, and the score should be included in measurements. + /// + /// Event name + /// Dimension data fields + /// Measurement data fields + /// + /// The name of the event, and the names of the event fields (both dimensions and measurements), must match + /// the names declared in the title's service configuration. The names are case insensitive. + /// If the API writes an event with a name that does not match a name in the service configuration, the + /// service drops the event with no notification. + /// + void WriteInGameEvent( + _In_ Platform::String^ eventName, + _In_ Windows::Foundation::Collections::PropertySet^ dimensions, + _In_ Windows::Foundation::Collections::PropertySet^ measurements + ); + +internal: + EventsService( + _In_ xbox::services::events::events_service cppObj + ); + +private: + xbox::services::events::events_service m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_EVENTS_END + +#endif //#if UWP_API \ No newline at end of file diff --git a/Source/Services/Events/events_service.cpp b/Source/Services/Events/events_service.cpp new file mode 100644 index 00000000..7cf0bc75 --- /dev/null +++ b/Source/Services/Events/events_service.cpp @@ -0,0 +1,346 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !UNIT_TEST_SERVICES +#include "xsapi/events.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" +#if XSAPI_A +#include "a/user_impl_a.h" +#include "a/java_interop.h" +#elif XSAPI_I +#include "xbox_cll.h" +#endif + +#if UWP_API +#include +#include +#include +#include "service_call_logger_data.h" +#include "service_call_logger.h" + +using namespace Windows::Foundation::Diagnostics; +using namespace Platform; + + +DEFINE_GUID(XSAPI_TELEMETRY_GROUP, + 0x53b78fc6, 0xe359, 0x453e, 0x89, 0xfe, 0xa5, 0xf4, 0xe5, 0xff, 0x4a, 0xf3); + +// {5E9EDC93-F04F-47EC-8DCB-0CF8F3442BDC} +DEFINE_GUID(GUID_LOGGING_CHANNEL, + 0x5e9edc93, 0xf04f, 0x47ec, 0x8d, 0xcb, 0xc, 0xf8, 0xf3, 0x44, 0x2b, 0xdc); + +#define XBOX_LIVE_LOGGING_OPTIONS 0x0000800000000000 +#define XBOX_LIVE_LOGGING_TAGS 0x00B00000 +#endif + +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_EVENTS_CPP_BEGIN + +// Events service +events_service::events_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr appConfig +) : + m_userContext(std::move(userContext)), + m_appConfig(std::move(appConfig)) +{ + m_playSession = utils::create_guid(true).c_str(); +#if UWP_API + m_loggingOptions = ref new LoggingOptions(XBOX_LIVE_LOGGING_OPTIONS); + m_loggingOptions->Tags = XBOX_LIVE_LOGGING_TAGS; + + + stringstream_t channelId; + channelId << L"Microsoft.XboxLive.T" << m_appConfig->title_id(); + + m_loggingChannel = ref new LoggingChannel( + ref new String(channelId.str().c_str()), + ref new LoggingChannelOptions(Guid(XSAPI_TELEMETRY_GROUP)), + Guid(GUID_LOGGING_CHANNEL)); + + m_appInsightsKey = load_app_insights_key(); +#endif +} + +xbox_live_result +events_service::write_in_game_event(_In_ const string_t& eventName) +{ + return write_in_game_event(eventName, web::json::value::null(), web::json::value::null()); +} + +xbox_live_result +events_service::write_in_game_event( + _In_ const string_t& eventName, + _In_ const web::json::value& dimensions, + _In_ const web::json::value& measurements +) +{ + try + { +#if XSAPI_CPP + if (!m_userContext->user() || !m_userContext->user()->is_signed_in()) +#else + if (!m_userContext->user() || !m_userContext->user()->IsSignedIn) +#endif + { + return xbox_live_result(xbox_live_error_code::auth_user_not_signed_in, "User must be signed in to call this API"); + } + + // Check event name + regex_t regex(_T("[A-Za-z]+[A-Za-z0-9_]*")); + bool matchFound = std::regex_match(eventName, regex); + if (!matchFound) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid event name"); + } + +#ifdef _WIN32 + //Log service call + if (xbox::services::service_call_logger::get_singleton_instance()->is_enabled()) + { + std::shared_ptr tracker = service_call_logger::get_singleton_instance(); + + service_call_logger_data logData( + m_userContext->xbox_user_id(), + eventName, + m_playSession, + dimensions.serialize(), + measurements.serialize(), + chrono_clock_t::now() + ); + + tracker->log(logData.to_string()); + } +#endif +#if UWP_API + + auto fields = create_logging_field(eventName, dimensions, measurements); + + m_loggingChannel->LogEvent(ref new String(eventName.c_str()), fields, LoggingLevel::Critical, m_loggingOptions); +#elif XSAPI_U + stringstream_t ss; + ss << m_appConfig->title_id(); + web::json::value eventData; + eventData[_T("baseType")] = web::json::value::string(_T("Microsoft.XboxLive.InGame")); + + web::json::value baseData; + baseData[_T("name")] = web::json::value::string(eventName.c_str()); + baseData[_T("serviceConfigId")] = web::json::value::string(m_appConfig->scid().c_str()); + baseData[_T("playerSessionId")] = web::json::value::string(m_playSession.c_str()); + baseData[_T("titleId")] = web::json::value::string(ss.str()); + baseData[_T("userId")] = web::json::value::string(m_userContext->xbox_user_id().c_str()); + baseData[_T("ver")] = web::json::value::number(1); + baseData[_T("properties")] = dimensions; + baseData[_T("measurements")] = measurements; + + eventData[_T("baseData")] = baseData; + + stringstream_t eventNameStream; + eventNameStream << "Microsoft.XboxLive.T" << ss.str() << "." << eventName; +#if XSAPI_A + std::shared_ptr interop = java_interop::get_java_interop_singleton(); + if (interop) + { + interop->log_cll(m_userContext->xbox_user_id(), eventNameStream.str(), eventData.serialize()); + } +#elif XSAPI_I + std::shared_ptr cll = xbox_cll::get_xbox_cll_singleton(); + std::vector ids = { m_userContext->xbox_user_id() }; + iOSCll* iCll = static_cast(cll->raw_cll().get()); + if (iCll) + { + iCll->log(eventNameStream.str(), + eventData.serialize(), + cll::Latency::LatencyRealtime, + cll::Persistence::PersistenceCritical, + cll::Sensitivity::SensitivityNone, + cll::SampleRate_NoSampling, + ids); + } +#endif +#endif + + } + catch (const std::exception& e) + { + xbox_live_error_code err = utils::convert_exception_to_xbox_live_error_code(); + return xbox_live_result(err, e.what()); + } +#if UWP_API + catch (Platform::Exception^ e) + { + xbox_live_error_code errc = static_cast(e->HResult); + return xbox_live_result(errc, utility::conversions::to_utf8string(e->Message->Data())); + } +#endif + return xbox_live_result(); +} + +#if UWP_API +void events_service::add_common_logging_field(_In_ Windows::Foundation::Diagnostics::LoggingFields^ fields) +{ + fields->AddString("serviceConfigId", ref new String(m_appConfig->scid().c_str())); + fields->AddString("playerSessionId", ref new String(m_playSession.c_str())); + fields->AddString("titleId", m_appConfig->title_id().ToString()); + fields->AddString("userId", ref new String(m_userContext->xbox_user_id().c_str())); + fields->AddUInt16("ver", 1); +} + +Windows::Foundation::Diagnostics::LoggingFields^ +events_service::create_logging_field( + _In_ const string_t& eventName, + _In_ const web::json::value& dimensions, + _In_ const web::json::value& measurements + ) +{ + THROW_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(eventName); + THROW_CPP_INVALIDARGUMENT_IF(!(dimensions.is_object() || dimensions.is_null())); + THROW_CPP_INVALIDARGUMENT_IF(!(measurements.is_object() || measurements.is_null())); + + auto fields = ref new Windows::Foundation::Diagnostics::LoggingFields(); + if (!m_appInsightsKey.empty()) + { + fields->AddString("PartA_iKey", "AIX-" + ref new String(m_appInsightsKey.c_str())); + } + + fields->BeginStruct("PartB_Microsoft.XboxLive.InGame"); + fields->AddString("name", ref new String(eventName.c_str())); + add_common_logging_field(fields); + + if (dimensions.is_object()) + { + // Add properties + fields->BeginStruct("properties"); + for (const auto& pair : dimensions.as_object()) + { + add_value_pair(fields, pair); + } + fields->EndStruct(); + } + + if (measurements.is_object()) + { + // Add measurements + fields->BeginStruct("measurements"); + for (const auto& pair : measurements.as_object()) + { + add_value_pair(fields, pair); + } + fields->EndStruct(); + } + + fields->EndStruct(); + + return fields; +} + +void +events_service::add_value_pair( + _In_ LoggingFields^ fields, + _In_ const std::pair& pair + ) +{ + // check property name. + const auto& name = pair.first; + THROW_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(name); + + regex_t regex(_T("[A-Za-z]+[A-Za-z0-9]*")); + bool matchFound = std::regex_match(name, regex); + if (!matchFound) + { + throw std::invalid_argument("Invalid properties or measurements name"); + } + + String^ propertyName = ref new String(name.c_str()); + + const auto& value = pair.second; + switch (value.type()) + { + case web::json::value::value_type::Number: + // if value can fit into int64, add as int64 + if (value.as_number().is_int64()) + { + fields->AddInt64(propertyName, value.as_number().to_int64()); + } + else if (value.as_number().is_uint64()) + { + fields->AddUInt64(propertyName, value.as_number().to_uint64()); + } + else + { + fields->AddDouble(propertyName, value.as_number().to_double()); + } + break; + + case web::json::value::value_type::Boolean: + fields->AddBoolean(propertyName, value.as_bool()); + break; + + case web::json::value::value_type::Null: + fields->AddEmpty(propertyName); + break; + + case web::json::value::value_type::String: + fields->AddString(propertyName, ref new String(value.as_string().c_str())); + break; + + default: + throw std::invalid_argument("Logging property type not supported"); + } +} + +string_t events_service::load_app_insights_key() +{ + string_t result; + try + { + auto localConfig = xbox_system_factory::get_factory()->create_local_config(); + + // 1. Check if app insight is disabled. + if (localConfig->get_value_from_config(_T("SendXboxEventsToAppInsights"), false, _T("1")) != _T("0")) + { + // 2. check if an alternate app insight key is provided + result = localConfig->get_value_from_config(_T("AlternateAppInsightsInstrumentationKey"), false, string_t()); + + // 3. Load app insight key from ApplicationInsights.config + if (result.empty()) + { + Windows::ApplicationModel::Package^ package = Windows::ApplicationModel::Package::Current; + Windows::Storage::StorageFolder^ installedLocation = package->InstalledLocation; + string_t configPath = string_t(installedLocation->Path->Data()) + _T("\\ApplicationInsights.config"); + string_t fileData = utils::read_file_to_string(configPath); + + if(!fileData.empty()) + { + auto xml = ref new Windows::Data::Xml::Dom::XmlDocument(); + xml->LoadXml(ref new String(fileData.c_str())); + + auto node = xml->SelectSingleNodeNS("//ns:InstrumentationKey", "xmlns:ns='http://schemas.microsoft.com/ApplicationInsights/2013/Settings'"); + if (node != nullptr) + { + result = node->InnerText->Data(); + } + } + } + } + } + catch (...) + { + LOG_ERROR("Xbox Services API couldn't load ApplicationInsights.config"); + } + + return result; +} +#endif +NAMESPACE_MICROSOFT_XBOX_SERVICES_EVENTS_CPP_END +#endif \ No newline at end of file diff --git a/Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.cpp new file mode 100644 index 00000000..2107df3a --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.cpp @@ -0,0 +1,36 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "AllocationResult_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +AllocationResult::AllocationResult( + _In_ allocation_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_portMappings = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.port_mappings()); +} + +IVectorView^ +AllocationResult::PortMappings::get() +{ + return m_portMappings->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.h b/Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.h new file mode 100644 index 00000000..8e6d5b67 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/AllocationResult_WinRT.h @@ -0,0 +1,64 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "GameServerFulfillmentState_WinRT.h" +#include "GameServerPortMapping_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents a game server cluster result. +/// + +public ref class AllocationResult sealed +{ +public: + /// + /// Indicates if the allocation is available if or the caller should wait or if the request was aborted. + /// + DEFINE_PROP_GET_ENUM_OBJ(FulfillmentState, fulfillment_state, GameServerFulfillmentState); + + /// + /// The host name of the session host. + /// + DEFINE_PROP_GET_STR_OBJ(HostName, host_name); + + /// + /// The ID of the session host. It is responsible for hosting the session. + /// A session host can only host one session at a time, but over its life time, will host several sessions. + /// + DEFINE_PROP_GET_STR_OBJ(SessionHostId, session_host_id); + + /// + /// The region of the session host. + /// + DEFINE_PROP_GET_STR_OBJ(Region, region); + + /// + /// The port mappings of the session host. + /// + property Windows::Foundation::Collections::IVectorView^ PortMappings { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The secure device address of the session host. + /// + DEFINE_PROP_GET_STR_OBJ(SecureDeviceAddress, secure_device_address); + +internal: + AllocationResult( + _In_ xbox::services::game_server_platform::allocation_result cppObj + ); + +private: + xbox::services::game_server_platform::allocation_result m_cppObj; + Windows::Foundation::Collections::IVector^ m_portMappings; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.cpp new file mode 100644 index 00000000..bad0e5d3 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ClusterResult_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +ClusterResult::ClusterResult( + _In_ cluster_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_portMappings = ref new Vector(); + for (const auto& i : m_cppObj.port_mappings()) + { + m_portMappings->Append(ref new GameServerPortMapping(i)); + } +} + +IVectorView^ +ClusterResult::PortMappings::get() +{ + return m_portMappings->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.h b/Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.h new file mode 100644 index 00000000..3a6f45c0 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/ClusterResult_WinRT.h @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "GameServerFulfillmentState_WinRT.h" +#include "GameServerPortMapping_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents a game server cluster result. +/// + +public ref class ClusterResult sealed +{ +public: + /// + /// Recommended interval to poll for completion. Note that this is not an estimate of when + /// the cluster will be ready, but rather a recommendation for how frequently the caller should + /// poll for a session status update. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(PollInterval, poll_interval) + + /// + /// Indicates if the cluster is available if or the caller should wait or if the request was aborted. + /// + DEFINE_PROP_GET_ENUM_OBJ(FulfillmentState, fulfillment_state, GameServerFulfillmentState); + + /// + /// The host name of the cluster. + /// + DEFINE_PROP_GET_STR_OBJ(HostName, host_name); + + /// + /// The region of the cluster. + /// + DEFINE_PROP_GET_STR_OBJ(Region, region); + + /// + /// The port mappings of the cluster. + /// + property Windows::Foundation::Collections::IVectorView^ PortMappings { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The secure context which is the secure device address of the cluster. + /// + DEFINE_PROP_GET_STR_OBJ(SecureDeviceAddress, secure_device_address); + +internal: + ClusterResult( + _In_ xbox::services::game_server_platform::cluster_result cppObj + ); + +private: + xbox::services::game_server_platform::cluster_result m_cppObj; + Windows::Foundation::Collections::IVector^ m_portMappings; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerFulfillmentState_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerFulfillmentState_WinRT.h new file mode 100644 index 00000000..07c8105a --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerFulfillmentState_WinRT.h @@ -0,0 +1,31 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +/// Defines values that indicate the the fulfillment state. +public enum class GameServerFulfillmentState +{ + /// The fulfillment state is unknown. + Unknown = xbox::services::game_server_platform::game_server_fulfillment_state::unknown, + + /// Indicates that the allocate cluster request is fulfilled and the cluster is available. + Fulfilled = xbox::services::game_server_platform::game_server_fulfillment_state::fulfilled, + + /// Indicates that the allocate cluster request is queued. + Queued = xbox::services::game_server_platform::game_server_fulfillment_state::queued, + + /// Indicates that the cluster request was aborted. This will only be returned if "abortIfQueued" is set to true. + Aborted = xbox::services::game_server_platform::game_server_fulfillment_state::aborted +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerHostStatus_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerHostStatus_WinRT.h new file mode 100644 index 00000000..b0c54d76 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerHostStatus_WinRT.h @@ -0,0 +1,34 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +/// Defines values that indicate the host state. +public enum class GameServerHostStatus +{ + /// The fulfillment state is unknown. + Unknown = xbox::services::game_server_platform::game_server_host_status::unknown, + + /// Indicates that the cluster request is active. + Active = xbox::services::game_server_platform::game_server_host_status::active, + + /// Indicates that the cluster request is queued. + Queued = xbox::services::game_server_platform::game_server_host_status::queued, + + /// Indicates that the cluster request was aborted. This will only be returned if "abortIfQueued" is set to true. + Aborted = xbox::services::game_server_platform::game_server_host_status::aborted, + + /// Indicates that the cluster request had an error. + Error = xbox::services::game_server_platform::game_server_host_status::error +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.cpp new file mode 100644 index 00000000..9105e452 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.cpp @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameServerImageSet_WinRT.h" + +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameServerImageSet::GameServerImageSet( + _In_ game_server_image_set cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_tagsMap = ref new Platform::Collections::Map(); + for (const auto& tag : m_cppObj.tags()) + { + m_tagsMap->Insert(ref new Platform::String(tag.first.c_str()), ref new Platform::String(tag.second.c_str())); + } +} + +Windows::Foundation::Collections::IMapView^ +GameServerImageSet::Tags::get() +{ + return m_tagsMap->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.h new file mode 100644 index 00000000..1d228505 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerImageSet_WinRT.h @@ -0,0 +1,89 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "GameVariantSchema_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents a set of game server images. +/// + +public ref class GameServerImageSet sealed +{ + // Example: + // { + // "gsiSetId":"7efdf3a7-9ce4-4d28-b889-4aeea98727c1", + // "minRequiredPlayers":"2", + // "maxAllowedPlayers":"50", + // "selectionOrder":"1", + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806" + // } + +public: + /// + /// The minimum number of players for the variant. + /// + DEFINE_PROP_GET_OBJ(MinPlayers, min_players, uint64); + + /// + /// The maximum number of players for the variant. + /// + DEFINE_PROP_GET_OBJ(MaxPlayers, max_players, uint64); + + /// + /// The set ID of the variant. + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// The set Name of the variant. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// Selection order for this set. + /// + DEFINE_PROP_GET_OBJ(SelectionOrder, selection_order, uint64); + + /// + /// Content of this set's schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaContent, schema_content); + + /// + /// Name of this set's schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaName, schema_name); + + /// + /// ID of this set's schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaId, schema_id); + + /// + /// Tags are key value metadata on game variant that can be set at the time of ingestion and then use them as filters or additional metadata. + /// + property Windows::Foundation::Collections::IMapView^ Tags + { + Windows::Foundation::Collections::IMapView^ get(); + } + +internal: + GameServerImageSet( + _In_ xbox::services::game_server_platform::game_server_image_set cppObj + ); + +private: + xbox::services::game_server_platform::game_server_image_set m_cppObj; + Platform::Collections::Map^ m_tagsMap; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.cpp new file mode 100644 index 00000000..4094a3dd --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.cpp @@ -0,0 +1,49 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameServerMetadataResult_WinRT.h" + +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameServerMetadataResult::GameServerMetadataResult( + _In_ xbox::services::game_server_platform::game_server_metadata_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_gameVariants = ref new Vector(); + for (const auto& i : m_cppObj.game_variants()) + { + m_gameVariants->Append(ref new GameVariant(i)); + } + + m_gameServerImageSets = ref new Vector(); + for (const auto& i : m_cppObj.game_server_image_sets()) + { + m_gameServerImageSets->Append(ref new GameServerImageSet(i)); + } +} + +Windows::Foundation::Collections::IVectorView^ +GameServerMetadataResult::GameVariants::get() +{ + return m_gameVariants->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +GameServerMetadataResult::GameServerImageSets::get() +{ + return m_gameServerImageSets->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.h new file mode 100644 index 00000000..756e2177 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerMetadataResult_WinRT.h @@ -0,0 +1,85 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "GameVariant_WinRT.h" +#include "GameVariantSchema_WinRT.h" +#include "GameServerImageSet_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents information on game server image sets and game variants. +/// + +public ref class GameServerMetadataResult sealed +{ + // Example: + //{ + // "variants" : + // [ + // { + // "gamevariantId":"041aae97-d359-4244-9b93-2d23ba27cd19", + // "name":"Example Variant", + // "rank":"100", + // "isPublisher":"False" + // "gameVariantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // } + // ], + // + // "variantSchemas" : + // [ + // { + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // "schemaContent":"\r\n \r\n\r\n \r\n ", + // "name":"Example Variant" + // } + // ], + // + // "gsiSets" : + // [ + // { + // "gsiSetId":"7efdf3a7-9ce4-4d28-b889-4aeea98727c1", + // "minRequiredPlayers":"2", + // "maxAllowedPlayers":"50", + // "selectionOrder":"1", + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806" + // } + // ] + //} + +public: + /// + /// The collection of game variants. + /// + property Windows::Foundation::Collections::IVectorView^ GameVariants + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The collection of game server image sets. + /// + property Windows::Foundation::Collections::IVectorView^ GameServerImageSets + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + GameServerMetadataResult( + _In_ xbox::services::game_server_platform::game_server_metadata_result cppObj + ); + +private: + xbox::services::game_server_platform::game_server_metadata_result m_cppObj; + Windows::Foundation::Collections::IVector^ m_gameVariants; + Windows::Foundation::Collections::IVector^ m_gameServerImageSets; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.cpp new file mode 100644 index 00000000..9aae8ca1 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.cpp @@ -0,0 +1,205 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameServerPlatformService_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::game_server_platform; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameServerPlatformService::GameServerPlatformService( + _In_ game_server_platform_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +IAsyncOperation^ +GameServerPlatformService::AllocateClusterAsync( + _In_ uint32 gameServerTitleId, + _In_ String^ serviceConfigurationId, + _In_ String^ sessionTemplateName, + _In_ String^ sessionName, + _In_ bool abortIfQueued + ) +{ + auto task = m_cppObj.allocate_cluster( + gameServerTitleId, + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(sessionTemplateName), + STRING_T_FROM_PLATFORM_STRING(sessionName), + abortIfQueued) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new ClusterResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +GameServerPlatformService::AllocateClusterInlineAsync( + _In_ uint32 gameServerTitleId, + _In_ String^ serviceConfigurationId, + _In_ String^ sandboxId, + _In_ String^ ticketId, + _In_ String^ gsiSetId, + _In_ String^ gameVariantId, + _In_ uint64 maxAllowedPlayers, + _In_ String^ location, + _In_ bool abortIfQueued + ) +{ + auto task = m_cppObj.allocate_cluster_inline( + gameServerTitleId, + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(sandboxId), + STRING_T_FROM_PLATFORM_STRING(ticketId), + STRING_T_FROM_PLATFORM_STRING(gsiSetId), + STRING_T_FROM_PLATFORM_STRING(gameVariantId), + maxAllowedPlayers, + STRING_T_FROM_PLATFORM_STRING(location), + abortIfQueued) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new ClusterResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +GameServerPlatformService::GetTicketStatusAsync( + _In_ uint32 gameServerTitleId, + _In_ String^ ticketId + ) +{ + auto task = m_cppObj.get_ticket_status( + gameServerTitleId, + STRING_T_FROM_PLATFORM_STRING(ticketId) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new GameServerTicketStatus(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +GameServerPlatformService::GetGameServerMetadataAsync( + _In_ uint32 titleId, + _In_ uint32 maxAllowedPlayers, + _In_ bool publisherOnly, + _In_ uint32 maxVariants, + _In_opt_ Platform::String^ locale + ) +{ + return GetGameServerMetadataAsync(titleId, maxAllowedPlayers, publisherOnly, maxVariants, locale, nullptr); +} + +IAsyncOperation^ +GameServerPlatformService::GetGameServerMetadataAsync( + _In_ uint32 titleId, + _In_ uint32 maxAllowedPlayers, + _In_ bool publisherOnly, + _In_ uint32 maxVariants, + _In_opt_ Platform::String^ locale, + _In_opt_ Windows::Foundation::Collections::IMapView^ filterTags + ) +{ + std::map filterMap = UtilsWinRT::CreateStdMapStringFromMapObj(filterTags); + auto task = m_cppObj.get_game_server_metadata( + titleId, + maxAllowedPlayers, + publisherOnly, + maxVariants, + filterMap + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new GameServerMetadataResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +GameServerPlatformService::GetQualityOfServiceServersAsync() +{ + auto task = m_cppObj.get_quality_of_service_servers() + .then([](xbox_live_result> servers) + { + THROW_IF_ERR(servers); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(servers.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +GameServerPlatformService::AllocateSessionHost( + _In_ uint32 gameServerTitleId, + _In_ Windows::Foundation::Collections::IVectorView^ locations, + _In_ Platform::String^ sessionId, + _In_ Platform::String^ cloudGameId, + _In_ Platform::String^ gameModeId, + _In_ Platform::String^ sessionCookie + ) +{ + auto task = m_cppObj.allocate_session_host( + gameServerTitleId, + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(locations), + STRING_T_FROM_PLATFORM_STRING(sessionId), + STRING_T_FROM_PLATFORM_STRING(cloudGameId), + STRING_T_FROM_PLATFORM_STRING(gameModeId), + STRING_T_FROM_PLATFORM_STRING(sessionCookie) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new AllocationResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + + +Windows::Foundation::IAsyncOperation^ +GameServerPlatformService::GetSessionHostAllocationStatus( + _In_ uint32 gameServerTitleId, + _In_ Platform::String^ sessionId + ) +{ + auto task = m_cppObj.get_session_host_allocation_status( + gameServerTitleId, + STRING_T_FROM_PLATFORM_STRING(sessionId) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new AllocationResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.h new file mode 100644 index 00000000..504c199b --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerPlatformService_WinRT.h @@ -0,0 +1,170 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "ClusterResult_WinRT.h" +#include "AllocationResult_WinRT.h" +#include "GameServerTicketStatus_WinRT.h" +#include "GameServerMetadataResult_WinRT.h" +#include "QualityOfServiceServer_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents the game server platform service for allocating game server clusters and retrieving game server metadata. +/// + +public ref class GameServerPlatformService sealed +{ +public: + + /// + /// Allocates a new Game Server Cluster using an existing Game Server Image. + /// + /// Title ID of the game server. + /// Service configuration ID (SCID). This can come from the MatchTicket. + /// Session template name. This can come from the MatchTicket. + /// Session name. This can come from the MatchTicket. + /// Indicates if the allocate should aborted if the operation is queued. + /// ClusterResult object + /// Calls V1 POST /titles/{gameServerTitleId}/clusters + Windows::Foundation::IAsyncOperation^ AllocateClusterAsync( + _In_ uint32 gameServerTitleId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName, + _In_ Platform::String^ sessionName, + _In_ bool abortIfQueued + ); + + /// + /// Allocates a new Game Server Cluster using an existing Game Server Image, without interacting with MPSD. + /// + /// Title ID of the game server. + /// Service configuration ID (SCID). + /// Unique id for this request. The ticket id should be the same for all members of the group. + /// The GSI Set id to use for this request. Comes from GetGameServerMetadataAsync. + /// Which game variant to use. Comes from GetGameServerMetadataAsync. + /// The maximum players allowed by this variant. + /// Which datacenter to use for allocation. This information should come from QoS probes. + /// Indicates if the allocate should aborted if the operation is queued. + /// ClusterResult object + /// Calls V2 POST /titles/{gameServerTitleId}/inlineclusters + Windows::Foundation::IAsyncOperation^ AllocateClusterInlineAsync( + _In_ uint32 gameServerTitleId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sandboxId, + _In_ Platform::String^ ticketId, + _In_ Platform::String^ gsiSetId, + _In_ Platform::String^ gameVariantId, + _In_ uint64 maxAllowedPlayers, + _In_ Platform::String^ location, + _In_ bool abortIfQueued + ); + + /// + /// Allocates a new Game Server Cluster using an existing Game Server Image, without interacting with MPSD. + /// + /// Title ID of the game server. + /// Unique id for this request. The ticket id should be the same for all members of the group. + /// GameServerTicketStatus object + /// Calls V6 GET titles/{titleId}/tickets/{ticketId}/status + Windows::Foundation::IAsyncOperation^ GetTicketStatusAsync( + _In_ uint32 gameServerTitleId, + _In_ Platform::String^ ticketId + ); + + /// + /// Retrieves a list of game variants for the specified title Id. + /// + /// The title ID. + /// The maximum players the variant allows. + /// Indicates whether to filter on publisher-created variants; otherwise user-created variants. + /// The maximum number of variants to return. + /// Deprecated. This value is ignored and no longer required. (Optional) + /// GameServerMetadataResult object + /// Calls V1 POST /titles/{titleId}/variants + Windows::Foundation::IAsyncOperation^ GetGameServerMetadataAsync( + _In_ uint32 titleId, + _In_ uint32 maxAllowedPlayers, + _In_ bool publisherOnly, + _In_ uint32 maxVariants, + _In_opt_ Platform::String^ locale + ); + + /// + /// Retrieves a list of game variants for the specified title Id. + /// + /// The title ID. + /// The maximum players the variant allows. + /// Indicates whether to filter on publisher-created variants; otherwise user-created variants. + /// The maximum number of variants to return. + /// Deprecated. This value is ignored and no longer required. (Optional) + /// Tags are key value metadata on game variant, that a game developer sets at the time of ingestion and then use it as filters or + /// additional metadata. The developer can use this value to filter which game variants they want to see. (Optional) + /// GameServerMetadataResult object + /// Calls V1 POST /titles/{titleId}/variants + Windows::Foundation::IAsyncOperation^ GetGameServerMetadataAsync( + _In_ uint32 titleId, + _In_ uint32 maxAllowedPlayers, + _In_ bool publisherOnly, + _In_ uint32 maxVariants, + _In_opt_ Platform::String^ locale, + _In_opt_ Windows::Foundation::Collections::IMapView^ filterTags + ); + + /// + /// Retrieves a collection of Quality of Service (QoS) servers. + /// + /// A collection of QualityOfServiceServer objects. + /// Calls V1 GET /qosservers/ + Windows::Foundation::IAsyncOperation^>^ GetQualityOfServiceServersAsync(); + + /// + /// Allocates a new session host + /// + /// The title ID of the game server. + /// The ordered list of preferred location you wish the session host to be allocated from. + /// This is the caller specified identifier. It is assigned to the session host that is allocated and returned. Later on you can reference the specific sessionhost by this identifier. It must be globally unique(i.e.GUID). + /// The cloud game identifier (GUID), otherwise known as the GSI Set ID. + /// The game mode identifier otherwise known as game variant IDs. + /// This is a caller specified opaque string. It too is assign to the sessionhost and can be referenced in your game code. Use this to pass a small amount of information from the client to the server. Max size is 32KB. + /// AllocationResult object + /// Calls V8 POST /titles/{gameServerTitleId}/allocationStatus + Windows::Foundation::IAsyncOperation^ AllocateSessionHost( + _In_ uint32 gameServerTitleId, + _In_ Windows::Foundation::Collections::IVectorView^ locations, + _In_ Platform::String^ sessionId, + _In_ Platform::String^ cloudGameId, + _In_ Platform::String^ gameModeId, + _In_ Platform::String^ sessionCookie + ); + + /// + /// Get allocation status for a previous allocate session host request + /// + /// Title ID of the game server + /// This is the caller specified identifier. It is assigned to the session host that is allocated and returned. Later on you can reference the specific sessionhost by this identifier. It must be globally unique(i.e.GUID). + /// AllocationResult object + /// Calls V8 POST /titles/{gameServerTitleId}/sessionhosts + Windows::Foundation::IAsyncOperation^ GetSessionHostAllocationStatus( + _In_ uint32 gameServerTitleId, + _In_ Platform::String^ sessionId + ); + +internal: + GameServerPlatformService( + _In_ xbox::services::game_server_platform::game_server_platform_service cppObj + ); + +private: + xbox::services::game_server_platform::game_server_platform_service m_cppObj; +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.cpp new file mode 100644 index 00000000..3026fbc7 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.cpp @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameServerPortMapping_WinRT.h" + +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameServerPortMapping::GameServerPortMapping( + _In_ game_server_port_mapping cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.h new file mode 100644 index 00000000..c5608319 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerPortMapping_WinRT.h @@ -0,0 +1,63 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +/// +/// Represents a mapping between the port numbers requested for the server to use, and the port numbers exposed via load balancing hardware. +/// +public ref class GameServerPortMapping sealed +{ + // Example: + // "portMappings": { + // "GameData1": { + // "internal": 8347, + // "external": 30002 + // }, + // "GameData2": { + // "internal": 8348, + // "external": 31002 + // }, + // "Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp": { + // "internal": 3389, + // "external": 3389 + // }, + // "Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput": { + // "internal": 20000, + // "external": 3389 + // } + // } + +public: + /// + /// The name of the port, which is specified in your Azure project cscfg. + /// + DEFINE_PROP_GET_STR_OBJ(PortName, port_name); + + /// + /// The internal port number for the named port. This is the port that the server will open using the socket API. + /// + DEFINE_PROP_GET_OBJ(InternalPortNumber, internal_port_number, uint32); + + /// + /// The external port number clients should use when connecting. This port is mapped by networking hardware to the internal port number. + /// + DEFINE_PROP_GET_OBJ(ExternalPortNumber, external_port_number, uint32); + +internal: + GameServerPortMapping(_In_ xbox::services::game_server_platform::game_server_port_mapping cppObj); + +private: + xbox::services::game_server_platform::game_server_port_mapping m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.cpp new file mode 100644 index 00000000..035f5f6d --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.cpp @@ -0,0 +1,37 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameServerTicketStatus_WinRT.h" + +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameServerTicketStatus::GameServerTicketStatus( + _In_ game_server_ticket_status cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_portMappings = ref new Vector(); + for (const auto& i : m_cppObj.port_mappings()) + { + m_portMappings->Append(ref new GameServerPortMapping(i)); + } +} + +IVectorView^ +GameServerTicketStatus::PortMappings::get() +{ + return m_portMappings->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.h new file mode 100644 index 00000000..264c3982 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameServerTicketStatus_WinRT.h @@ -0,0 +1,98 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "GameServerHostStatus_WinRT.h" +#include "GameServerPortMapping_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +/// +/// Represents status information for the Allocation request previously sent to the service. +/// +public ref class GameServerTicketStatus sealed +{ + // Example: + // { + // "ticketId": "12341234-1234-1234-1234-123412341234", + // "clusterId": "12341234-1234-1234-1234-123412341234", + // "titleId": "1234", + // "hostName": "cloudapp.net", + // "status": "Active", + // "description": "", + // "secureContext": "", + // "portMappings": {}, + // "gameHostId": "abc.Cloud.Gaming.Bootstrap_IN_0.0" + // "region": "Central US" + // } + +public: + /// + /// The ID of the ticket whose status is being checked. + /// + DEFINE_PROP_GET_STR_OBJ(TicketId, ticket_id); + + /// + /// The cluster ID of the server allocated for this ticket. + /// + DEFINE_PROP_GET_STR_OBJ(ClusterId, cluster_id); + + /// + /// The title ID of the requesting title. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The host name of the server which was allocated to support this request. + /// + DEFINE_PROP_GET_STR_OBJ(HostName, host_name); + + /// + /// The status of the server. + /// + DEFINE_PROP_GET_ENUM_OBJ(Status, status, GameServerHostStatus); + + /// + /// Description of the allocation request. + /// + DEFINE_PROP_GET_STR_OBJ(Description, description); + + /// + /// The secure device address information for the assigned server. + /// + DEFINE_PROP_GET_STR_OBJ(SecureContext, secure_context); + + /// + /// The list of GameServerPortMapping for this server. + /// + property Windows::Foundation::Collections::IVectorView^ PortMappings { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The ID of the game host. + /// + DEFINE_PROP_GET_STR_OBJ(GameHostId, game_host_id); + + /// + /// The region of the game host. + /// + DEFINE_PROP_GET_STR_OBJ(Region, region); + +internal: + GameServerTicketStatus( + _In_ xbox::services::game_server_platform::game_server_ticket_status cppObj + ); + +private: + xbox::services::game_server_platform::game_server_ticket_status m_cppObj; + Windows::Foundation::Collections::IVector^ m_portMappings; +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.cpp new file mode 100644 index 00000000..a513e1c8 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.cpp @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameVariantSchema_WinRT.h" + +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameVariantSchema::GameVariantSchema( + _In_ game_variant_schema cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.h new file mode 100644 index 00000000..a82362f2 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameVariantSchema_WinRT.h @@ -0,0 +1,52 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents a game variant schema. +/// + +ref class GameVariantSchema sealed +{ + // Example: + // { + // "variantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // "schemaContent":"\r\n \r\n\r\n \r\n ", + // "name":"Example Variant" + // } + +public: + /// + /// The ID of the schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaId, schema_id); + + /// + /// The content of the schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaContent, schema_content); + + /// + /// The name of the schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaName, schema_name); + +internal: + GameVariantSchema( + _In_ xbox::services::game_server_platform::game_variant_schema cppObj + ); + +private: + xbox::services::game_server_platform::game_variant_schema m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.cpp new file mode 100644 index 00000000..7fd33347 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.cpp @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "GameVariant_WinRT.h" + +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +GameVariant::GameVariant( + _In_ game_variant cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.h b/Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.h new file mode 100644 index 00000000..1d868c35 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/GameVariant_WinRT.h @@ -0,0 +1,75 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" +#include "GameVariantSchema_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents a game variant. +/// + +public ref class GameVariant sealed +{ + // Example: + // { + // "gamevariantId":"041aae97-d359-4244-9b93-2d23ba27cd19", + // "name":"Example Variant", + // "rank":"100", + // "isPublisher":"False" + // "gameVariantSchemaId":"e96582b8-d78d-49e4-afe8-8b7ea3d10806", + // } + +public: + /// + /// ID of a variant. + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// Name of variant. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// A boolean field to indicate whether the variant was user-created or publisher-created. + /// + DEFINE_PROP_GET_OBJ(IsPublisher, is_publisher, bool); + + /// + /// A boolean field to indicate whether the variant was user-created or publisher-created. + /// + DEFINE_PROP_GET_OBJ(Rank, rank, uint64); + + /// + /// Content of the variant's schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaContent, schema_content); + + /// + /// Name of the variant's schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaName, schema_name); + + /// + /// ID of the variant's schema. + /// + DEFINE_PROP_GET_STR_OBJ(SchemaId, schema_id); + +internal: + GameVariant( + _In_ xbox::services::game_server_platform::game_variant cppObj + ); + +private: + xbox::services::game_server_platform::game_variant m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.cpp b/Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.cpp new file mode 100644 index 00000000..f8a53bb7 --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "QualityOfServiceServer_WinRT.h" + +using namespace xbox::services::game_server_platform; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN + +QualityOfServiceServer::QualityOfServiceServer( + _In_ quality_of_service_server cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +const xbox::services::game_server_platform::quality_of_service_server& +QualityOfServiceServer::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.h b/Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.h new file mode 100644 index 00000000..3e132e0f --- /dev/null +++ b/Source/Services/GameServerPlatform/WinRT/QualityOfServiceServer_WinRT.h @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/game_server_platform.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_BEGIN +/// +/// Represents the server used to measure network quality of service (QoS) for the session. +/// + +public ref class QualityOfServiceServer sealed +{ + // Example: + // + // { + // "qosServers" : + // [ + // { + // "serverFqdn":"microsoft.com", + // "serverSecureDeviceAddress":"r5Y=", + // "targetLocation":"North Central US" + // }, + // { + // "serverFqdn":"microsoft.com", + // "serverSecureDeviceAddress":"r5Y=", + // "targetLocation":"West US" + // } + // ] + // } + +public: + /// + /// The full qualified domain name of the server. + /// + DEFINE_PROP_GET_STR_OBJ(ServerFullQualifiedDomainName, server_full_qualified_domain_name); + + /// + /// The secure device address in base64 of the server. + /// + DEFINE_PROP_GET_STR_OBJ(SecureDeviceAddressBase64, secure_device_address_base64); + + /// + /// The target location. + /// + DEFINE_PROP_GET_STR_OBJ(TargetLocation, target_location); + +internal: + QualityOfServiceServer( + _In_ xbox::services::game_server_platform::quality_of_service_server cppObj + ); + + const xbox::services::game_server_platform::quality_of_service_server& GetCppObj() const; +internal: + xbox::services::game_server_platform::quality_of_service_server m_cppObj; +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_END diff --git a/Source/Services/GameServerPlatform/allocation_result.cpp b/Source/Services/GameServerPlatform/allocation_result.cpp new file mode 100644 index 00000000..c3fcb28c --- /dev/null +++ b/Source/Services/GameServerPlatform/allocation_result.cpp @@ -0,0 +1,143 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +allocation_result::allocation_result() +{ +} + +allocation_result::allocation_result( + _In_ game_server_fulfillment_state fulfillmentState, + _In_ string_t hostName, + _In_ string_t sessionHostId, + _In_ string_t region, + _In_ std::vector< game_server_port_mapping > portMappings, + _In_ string_t secureDeviceAddress + ) : + m_fulfillmentState(std::move(fulfillmentState)), + m_hostName(std::move(hostName)), + m_sessionHostId(std::move(sessionHostId)), + m_region(std::move(region)), + m_portMappings(std::move(portMappings)), + m_secureDeviceAddress(std::move(secureDeviceAddress)) +{ +} + +game_server_fulfillment_state +allocation_result::fulfillment_state() const +{ + return m_fulfillmentState; +} + +const string_t& +allocation_result::host_name() const +{ + return m_hostName; +} + +const string_t& +allocation_result::session_host_id() const +{ + return m_sessionHostId; +} + +const string_t& +allocation_result::region() const +{ + return m_region; +} + +const std::vector< game_server_port_mapping >& +allocation_result::port_mappings() const +{ + return m_portMappings; +} + +/// +/// The secure context which is the secure device address of the cluster +/// +const string_t& +allocation_result::secure_device_address() const +{ + return m_secureDeviceAddress; +} + +xbox_live_result +allocation_result::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + //{ + // "hostName": "1234", + // "portMappings": + // [ + // { + // "Key": "1234", + // "Value": + // { + // "internal": 10100, + // "external": 10103 + // } + // } + // ], + // "region": "WestUS", + // "secureContext": "1234" + // "sessionHostId": "345789", + // "status": "2345" + //} + + auto clusterResult = allocation_result( + convert_string_to_fulfillment_state(utils::extract_json_string(json, _T("fulfillmentState"), errc)), + utils::extract_json_string(json, _T("hostName"), errc), + utils::extract_json_string(json, _T("sessionHostId"), errc), + utils::extract_json_string(json, _T("region"), errc), + utils::extract_json_vector(game_server_port_mapping::_Deserialize, json, _T("portMappings"), errc, false), + utils::extract_json_string(json, _T("secureContext"), errc) + ); + + return xbox_live_result(clusterResult, errc); +} + +game_server_fulfillment_state +allocation_result::convert_string_to_fulfillment_state( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("fulfilled")) == 0) + { + return game_server_fulfillment_state::fulfilled; + } + else if (utils::str_icmp(value, _T("queued")) == 0) + { + return game_server_fulfillment_state::queued; + } + else if (utils::str_icmp(value, _T("aborted")) == 0) + { + return game_server_fulfillment_state::aborted; + } + else if (value.empty()) + { + return game_server_fulfillment_state::fulfilled; + } + + return game_server_fulfillment_state::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/cluster_result.cpp b/Source/Services/GameServerPlatform/cluster_result.cpp new file mode 100644 index 00000000..c2559f07 --- /dev/null +++ b/Source/Services/GameServerPlatform/cluster_result.cpp @@ -0,0 +1,125 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +cluster_result::cluster_result() : + m_fulfillmentState(game_server_fulfillment_state::unknown) +{ +} + +cluster_result::cluster_result( + _In_ std::chrono::milliseconds pollInterval, + _In_ game_server_fulfillment_state fulfillmentState, + _In_ string_t hostName, + _In_ string_t region, + _In_ std::vector< game_server_port_mapping > portMappings, + _In_ string_t secureDeviceAddress + ) : + m_pollInterval(std::move(pollInterval)), + m_fulfillmentState(fulfillmentState), + m_hostName(std::move(hostName)), + m_region(std::move(region)), + m_portMappings(std::move(portMappings)), + m_secureDeviceAddress(std::move(secureDeviceAddress)) +{ +} + +const std::chrono::milliseconds& +cluster_result::poll_interval() const +{ + return m_pollInterval; +} + +game_server_fulfillment_state +cluster_result::fulfillment_state() const +{ + return m_fulfillmentState; +} + +const string_t& +cluster_result::host_name() const +{ + return m_hostName; +} + +const string_t& +cluster_result::region() const +{ + return m_region; +} + +const std::vector< game_server_port_mapping >& +cluster_result::port_mappings() const +{ + return m_portMappings; +} + +/// +/// The secure context which is the secure device address of the cluster +/// +const string_t& +cluster_result::secure_device_address() const +{ + return m_secureDeviceAddress; +} + +xbox_live_result +cluster_result::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + string_t pollIntervalMillisecondsStr = utils::extract_json_string(json, _T("pollIntervalMilliseconds"), errc, false, _T("1000")); + + uint32_t pollIntervalMilliseconds = utils::string_t_to_uint32(pollIntervalMillisecondsStr); + + auto clusterResult = cluster_result( + std::chrono::milliseconds(pollIntervalMilliseconds), + convert_string_to_fulfillment_state(utils::extract_json_string(json, _T("fulfillmentState"), errc)), + utils::extract_json_string(json, _T("hostName"), errc), + utils::extract_json_string(json, _T("region"), errc), + utils::extract_json_vector(game_server_port_mapping::_Deserialize, json, _T("portMappings"), errc, false), + utils::extract_json_string(json, _T("secureContext"), errc, false, _T("")) + ); + + return xbox_live_result(clusterResult, errc); +} + +game_server_fulfillment_state +cluster_result::convert_string_to_fulfillment_state( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("fulfilled")) == 0) + { + return game_server_fulfillment_state::fulfilled; + } + else if (utils::str_icmp(value, _T("queued")) == 0) + { + return game_server_fulfillment_state::queued; + } + else if (utils::str_icmp(value, _T("aborted")) == 0) + { + return game_server_fulfillment_state::aborted; + } + + return game_server_fulfillment_state::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_server_image_set.cpp b/Source/Services/GameServerPlatform/game_server_image_set.cpp new file mode 100644 index 00000000..ab139576 --- /dev/null +++ b/Source/Services/GameServerPlatform/game_server_image_set.cpp @@ -0,0 +1,131 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_server_image_set::game_server_image_set() : + m_minPlayers(0), + m_maxPlayers(0), + m_selectionOrder(0) +{ +} + +game_server_image_set::game_server_image_set( + _In_ uint64_t minPlayers, + _In_ uint64_t maxPlayers, + _In_ string_t id, + _In_ string_t name, + _In_ uint64_t selectionOrder, + _In_ string_t schemaId, + _In_ std::map tags + ) : + m_minPlayers(minPlayers), + m_maxPlayers(maxPlayers), + m_id(std::move(id)), + m_name(std::move(name)), + m_selectionOrder(selectionOrder), + m_schemaId(std::move(schemaId)), + m_tags(std::move(tags)) +{ +} + +const uint64_t game_server_image_set::min_players() const +{ + return m_minPlayers; +} + +uint64_t game_server_image_set::max_players() const +{ + return m_maxPlayers; +} + +const string_t& game_server_image_set::id() const +{ + return m_id; +} + +const string_t& game_server_image_set::name() const +{ + return m_name; +} + +uint64_t game_server_image_set::selection_order() const +{ + return m_selectionOrder; +} + +const string_t& game_server_image_set::schema_content() const +{ + return m_schema.schema_content(); +} + +const string_t& game_server_image_set::schema_name() const +{ + return m_schema.schema_name(); +} + +const string_t& game_server_image_set::schema_id() const +{ + return m_schemaId; +} + +const std::map& game_server_image_set::tags() const +{ + return m_tags; +} + +xbox_live_result +game_server_image_set::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + std::map tags; + web::json::value tagField(utils::extract_json_field(json, _T("tags"), errc, false)); + if (tagField.is_array()) + { + const web::json::array& arr(tagField.as_array()); + for (const auto& element : arr) + { + string_t name = utils::extract_json_string(element, _T("name"), errc); + string_t value = utils::extract_json_string(element, _T("value"), errc); + tags[name] = value; + } + } + + auto result = game_server_image_set( + utils::extract_json_string_to_uint64(json, _T("minRequiredPlayers"), errc), + utils::extract_json_string_to_uint64(json, _T("maxAllowedPlayers"), errc), + utils::extract_json_string(json, _T("gsiSetId"), errc), + utils::extract_json_string(json, _T("gsiSetName"), errc), + utils::extract_json_string_to_uint64(json, _T("selectionOrder"), errc), + utils::extract_json_string(json, _T("variantSchemaId"), errc), + tags + ); + + return xbox_live_result(result, errc); +} + +void game_server_image_set::_Set_schema(_In_ game_variant_schema schema) +{ + m_schema = std::move(schema); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_server_metadata_result.cpp b/Source/Services/GameServerPlatform/game_server_metadata_result.cpp new file mode 100644 index 00000000..26b5f665 --- /dev/null +++ b/Source/Services/GameServerPlatform/game_server_metadata_result.cpp @@ -0,0 +1,92 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_server_metadata_result::game_server_metadata_result() +{ +} + +game_server_metadata_result::game_server_metadata_result( + _In_ std::vector< game_variant > gameVariants, + _In_ std::vector< game_variant_schema > gameVariantSchemas, + _In_ std::vector< game_server_image_set > gameServerImageSets + ) : + m_gameVariants(std::move(gameVariants)), + m_gameVariantSchemas(std::move(gameVariantSchemas)), + m_gameServerImageSets(std::move(gameServerImageSets)) +{ +} + +const std::vector< game_variant >& +game_server_metadata_result::game_variants() +{ + return m_gameVariants; +} + +const std::vector< game_server_image_set >& +game_server_metadata_result::game_server_image_sets() const +{ + return m_gameServerImageSets; +} + +xbox_live_result +game_server_metadata_result::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto variantSchemas = utils::extract_json_vector(game_variant_schema::_Deserialize, json, _T("variantSchemas"), errc, false); + auto variants = utils::extract_json_vector(game_variant::_Deserialize, json, _T("variants"), errc, false); + auto gameServerImageSets = utils::extract_json_vector(game_server_image_set::_Deserialize, json, _T("gsiSets"), errc, false); + + // Build a map of schemaIds -> schema + std::map schemaMap; + for (const auto& schema : variantSchemas) + { + schemaMap[schema.schema_id()] = schema; + } + + // For each variant and set, find its schema and set it. + for (auto& variant : variants) + { + auto it = schemaMap.find(variant.schema_id()); + if (it != schemaMap.end()) + { + variant._Set_schema(it->second); + } + } + + for (auto& imageSet : gameServerImageSets) + { + auto it = schemaMap.find(imageSet.schema_id()); + if (it != schemaMap.end()) + { + imageSet._Set_schema(it->second); + } + } + + auto result = game_server_metadata_result( + variants, + variantSchemas, + gameServerImageSets + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_server_platform_service.cpp b/Source/Services/GameServerPlatform/game_server_platform_service.cpp new file mode 100644 index 00000000..f7e6f647 --- /dev/null +++ b/Source/Services/GameServerPlatform/game_server_platform_service.cpp @@ -0,0 +1,501 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_server_platform_service::game_server_platform_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +game_server_platform_service::allocate_cluster( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& sessionName, + _In_ bool abortIfQueued + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, cluster_result, "serviceConfigurationId is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(sessionTemplateName, cluster_result, "sessionTemplateName is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(sessionName, cluster_result, "sessionName is required"); + + auto pathAndQuery = pathandquery_game_server_create_cluster_subpath( + gameServerTitleId, + false + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("gameserverms"), m_appConfig), + pathAndQuery, + xbox_live_api::allocate_cluster + ); + + httpCall->set_retry_allowed(false); + + // Set request body to something like: + // { + // "sessionId" : "/serviceconfigs/{scid}/sessionTemplates/{sessionTemplateName}/sessions/{sessionName}" + // "abortIfQueued" : false + // } + web::json::value request; + request[_T("sessionId")] = web::json::value::string(game_server_session_id_path(serviceConfigurationId, sessionTemplateName, sessionName)); + if (abortIfQueued) + { + request[_T("abortIfQueued")] = web::json::value::boolean(abortIfQueued); + } + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + cluster_result::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +game_server_platform_service::allocate_cluster_inline( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sandboxId, + _In_ const string_t& ticketId, + _In_ const string_t& gsiSetId, + _In_ const string_t& gameVariantId, + _In_ uint64_t maxAllowedPlayers, + _In_ const string_t& location, + _In_ bool abortIfQueued + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, cluster_result, "serviceConfigurationId is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(sandboxId, cluster_result, "sandboxId is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(ticketId, cluster_result, "ticketId is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(gsiSetId, cluster_result, "gsiSetId is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(gameVariantId, cluster_result, "gameVariantId is required"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(location, cluster_result, "location is required"); + + string_t pathAndQuery = pathandquery_game_server_create_cluster_subpath( + gameServerTitleId, + true + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("gameserverms"), m_appConfig), + pathAndQuery, + xbox_live_api::allocate_cluster_inline + ); + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + // Set request body to something like: + // { + // "serviceConfigId": "88222fc5-b30c-43f2-ab0f-834e9b2266c4", + // "sandboxId": "MSCP.0", + // "ticketId": "6057ff49-28ff-4156-95dc-a733e9bfa8ef", + // "gsiSetId": "a0aaa8e0-0866-45ca-908b-0274b889b099", + // "gameVariantId": "905b665a-fe2f-4170-acd5-fd44118c15a0", + // "maxAllowedPlayers": 8, + // "location": "west us", + // "abortIfQueued": true + // } + + web::json::value request; + request[_T("serviceConfigId")] = web::json::value::string(serviceConfigurationId); + request[_T("sandboxId")] = web::json::value::string(sandboxId); + request[_T("ticketId")] = web::json::value::string(ticketId); + request[_T("gsiSetId")] = web::json::value::string(gsiSetId); + request[_T("gameVariantId")] = web::json::value::string(gameVariantId); + request[_T("maxAllowedPlayers")] = web::json::value::number(static_cast(maxAllowedPlayers)); + request[_T("location")] = web::json::value::string(location); + if (abortIfQueued) + { + request[_T("abortIfQueued")] = web::json::value::boolean(abortIfQueued); + } + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + cluster_result::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} +pplx::task> +game_server_platform_service::get_ticket_status( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& ticketId + ) +{ + if (ticketId.empty()) { return pplx::task_from_result(xbox_live_result(xbox_live_error_code::invalid_argument, "ticketId is required")); } + + string_t pathAndQuery = pathandquery_game_server_ticket_status_subpath( + gameServerTitleId, + ticketId + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("gameserverms"), m_appConfig), + pathAndQuery, + xbox_live_api::get_ticket_status + ); + httpCall->set_xbox_contract_version_header_value(_T("6")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + game_server_ticket_status::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +game_server_platform_service::get_game_server_metadata( + _In_ uint32_t titleId, + _In_ uint32_t maxAllowedPlayers, + _In_ bool publisherOnly, + _In_ uint32_t maxVariants, + _In_ const std::map& filterTags + ) +{ + string_t pathAndQuery = pathandquery_game_server_gamevariant_list_subpath( + titleId + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("gameserverds"), m_appConfig), + pathAndQuery, + xbox_live_api::get_game_server_metadata + ); + + // Set request body to something like: + // { + // "maxAllowedPlayers": 12, + // "publisherOnly" : false, + // "maxVariants" : 100, + // "locale" : "en-us", + // "tags": [ { "name": "tagName1", "value": "tagValue1" }, { "name": "tagName2", "value": "tagValue2" } ] + // } + + web::json::value tagsJson; + int i = 0; + for(const auto& tag : filterTags) + { + web::json::value tagJson; + tagJson[_T("name")] = web::json::value::string(tag.first); + tagJson[_T("value")] = web::json::value::string(tag.second); + + tagsJson[i++] = tagJson; + } + + web::json::value request; + request[_T("maxAllowedPlayers")] = web::json::value::number(static_cast(maxAllowedPlayers)); + request[_T("publisherOnly")] = web::json::value::boolean(publisherOnly); + request[_T("maxVariants")] = web::json::value::number(static_cast(maxVariants)); + request[_T("locale")] = web::json::value::string(_T("en-us")); + request[_T("tags")] = tagsJson; + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + game_server_metadata_result::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task>> +game_server_platform_service::get_quality_of_service_servers() +{ + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("gameserverds"), m_appConfig), +#if TV_API + _T("/qosservers"), +#else + _T("/xplatqosservers"), +#endif + xbox_live_api::get_quality_of_service_servers + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + + auto qosServer = utils::extract_xbox_live_result_json_vector( + quality_of_service_server::_Deserialize, + response->response_body_json(), + _T("qosServers"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + qosServer, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task> +game_server_platform_service::allocate_session_host( + _In_ uint32_t gameServerTitleId, + _In_ const std::vector& locations, + _In_ const string_t& sessionId, + _In_ const string_t& cloudGameId, + _In_opt_ const string_t& gameModeId, + _In_opt_ const string_t& sessionCookie + ) +{ + string_t pathAndQuery = pathandquery_game_server_allocate_session_host_subpath( + gameServerTitleId + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("gameserverds"), m_appConfig), + pathAndQuery, + xbox_live_api::allocate_session_host + ); + + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(_T("8")); + + //// Set request body to something like: + //{ + // "sessionId": "3536d3e6-e85d-4f47-b898-9617d19dabcd", + // "cloudGameId" : "1b7f9925-369c-4301-b1f7-1125dce25776", + // "locations" : + // [ + // "West US", + // "East US", + // "West Europe" + // ], + // "sessionCookie" : "Caller provided opaque string", + // "gameModeId" : "2162d32c-7ac8-40e9-9b1f-56676b8b2513" + //} + + web::json::value request; + request[_T("sessionId")] = web::json::value::string(sessionId); + request[_T("cloudGameId")] = web::json::value::string(cloudGameId); + request[_T("locations")] = utils::serialize_vector(utils::json_string_serializer, locations); + if (!sessionCookie.empty()) + { + request[_T("sessionCookie")] = web::json::value::string(sessionCookie); + } + if (!gameModeId.empty()) + { + request[_T("gameModeId")] = web::json::value::string(gameModeId); + } + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + allocation_result::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +game_server_platform_service::get_session_host_allocation_status( + _In_ uint32_t gameServerTitleId, + _In_ const string_t& sessionId + ) +{ + string_t pathAndQuery = pathandquery_game_server_allocation_status_subpath( + gameServerTitleId, + sessionId + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("gameserverds"), m_appConfig), + pathAndQuery, + xbox_live_api::get_session_host_allocation_status + ); + + httpCall->set_xbox_contract_version_header_value(_T("8")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + allocation_result::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + + +string_t +game_server_platform_service::pathandquery_game_server_create_cluster_subpath( + _In_ uint32_t gameServerTitleId, + _In_ bool inlineAlloc + ) +{ + stringstream_t source; + source << _T("/titles/"); + source << gameServerTitleId; + if (inlineAlloc) + { + source << _T("/inlineclusters"); + } + else + { + source << _T("/clusters"); + } + + return source.str(); +} + +string_t +game_server_platform_service::pathandquery_game_server_allocate_session_host_subpath( + _In_ uint32_t titleId + ) +{ + stringstream_t source; + source << _T("/titles/"); + source << titleId; + source << _T("/sessionhosts"); + + return source.str(); +} + +string_t +game_server_platform_service::pathandquery_game_server_allocation_status_subpath( + _In_ uint32_t titleId, + _In_ const string_t& sessionId + ) +{ + stringstream_t source; + source << _T("/titles/"); + source << titleId; + source << _T("/sessions"); + source << sessionId; + source << _T("/allocationStatus"); + + return source.str(); +} + +string_t +game_server_platform_service::pathandquery_game_server_gamevariant_list_subpath( + _In_ uint32_t titleId + ) +{ + stringstream_t source; + source << _T("/titles/"); + source << titleId; + source << _T("/variants"); + + return source.str(); +} + +string_t +game_server_platform_service::game_server_session_id_path( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& sessionName + ) +{ + stringstream_t source; + + source << _T("/serviceconfigs/"); + source << serviceConfigurationId; + source << _T("/sessionTemplates/"); + source << sessionTemplateName; + source << _T("/sessions/"); + source << sessionName; + + return source.str(); +} + +string_t +game_server_platform_service::pathandquery_game_server_ticket_status_subpath( + _In_ uint32_t titleId, + _In_ const string_t& ticketId + ) +{ + stringstream_t source; + + source << _T("/titles/"); + source << titleId; + source << _T("/tickets/"); + source << ticketId; + source << _T("/status"); + + return source.str(); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_server_port_mapping.cpp b/Source/Services/GameServerPlatform/game_server_port_mapping.cpp new file mode 100644 index 00000000..dc18089c --- /dev/null +++ b/Source/Services/GameServerPlatform/game_server_port_mapping.cpp @@ -0,0 +1,80 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_server_port_mapping::game_server_port_mapping() : + m_internalPortNumber(0), + m_externalPortNumber(0) +{ +} + +game_server_port_mapping::game_server_port_mapping( + _In_ string_t portName, + _In_ uint32_t internalPortNumber, + _In_ uint32_t externalPortNumber + ) : + m_portName(std::move(portName)), + m_internalPortNumber(internalPortNumber), + m_externalPortNumber(externalPortNumber) +{ +} + +const string_t& +game_server_port_mapping::port_name() const +{ + return m_portName; +} + +uint32_t +game_server_port_mapping::internal_port_number() const +{ + return m_internalPortNumber; +} + +uint32_t +game_server_port_mapping::external_port_number() const +{ + return m_externalPortNumber; +} + +xbox_live_result +game_server_port_mapping::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + uint32_t externalPort = 0; + uint32_t internalPort = 0; + + web::json::value relatedInfoObject = utils::extract_json_field(json, _T("Value"), false); + if (!relatedInfoObject.is_null()) + { + externalPort = utils::extract_json_int(relatedInfoObject, _T("external"), false, 0); + internalPort = utils::extract_json_int(relatedInfoObject, _T("internal"), false, 0); + } + + return game_server_port_mapping( + utils::extract_json_string(json, _T("Key"), true), + internalPort, + externalPort + ); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_server_ticket_status.cpp b/Source/Services/GameServerPlatform/game_server_ticket_status.cpp new file mode 100644 index 00000000..0823a93b --- /dev/null +++ b/Source/Services/GameServerPlatform/game_server_ticket_status.cpp @@ -0,0 +1,161 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_server_ticket_status::game_server_ticket_status() : + m_titleId(0), + m_status(game_server_host_status::unknown) +{ +} + +game_server_ticket_status::game_server_ticket_status( + _In_ string_t ticketId, + _In_ string_t clusterId, + _In_ uint32_t titleId, + _In_ string_t hostName, + _In_ game_server_host_status status, + _In_ string_t description, + _In_ string_t secureContext, + _In_ std::vector< game_server_port_mapping > portMappings, + _In_ string_t gameHostId, + _In_ string_t region + ) : + m_ticketId(std::move(ticketId)), + m_clusterId(std::move(clusterId)), + m_titleId(titleId), + m_hostName(std::move(hostName)), + m_status(status), + m_description(std::move(description)), + m_secureContext(std::move(secureContext)), + m_portMappings(std::move(portMappings)), + m_gameHostId(std::move(gameHostId)), + m_region(std::move(region)) +{ +} + +const string_t& +game_server_ticket_status::ticket_id() const +{ + return m_ticketId; +} + +const string_t& +game_server_ticket_status::cluster_id() const +{ + return m_clusterId; +} + +uint32_t +game_server_ticket_status::title_id() const +{ + return m_titleId; +} + +const string_t& +game_server_ticket_status::host_name() const +{ + return m_hostName; +} + +game_server_host_status +game_server_ticket_status::status() const +{ + return m_status; +} + +const string_t& +game_server_ticket_status::description() const +{ + return m_description; +} + +const string_t& +game_server_ticket_status::secure_context() const +{ + return m_secureContext; +} + +std::vector< game_server_port_mapping > +game_server_ticket_status::port_mappings() const +{ + return m_portMappings; +} + +const string_t& +game_server_ticket_status::game_host_id() const +{ + return m_gameHostId; +} + +const string_t& +game_server_ticket_status::region() const +{ + return m_region; +} + +xbox_live_result +game_server_ticket_status::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + auto portMappings = utils::extract_json_vector(game_server_port_mapping::_Deserialize, json, _T("portMappings"), errc, false); + + auto result = game_server_ticket_status( + utils::extract_json_string(json, _T("ticketId"), errc), + utils::extract_json_string(json, _T("clusterId"), errc), + utils::extract_json_int(json, _T("titleId"), errc), + utils::extract_json_string(json, _T("hostName"), errc), + convert_string_to_host_status(utils::extract_json_string(json, _T("status"), errc)), + utils::extract_json_string(json, _T("description"), errc), + utils::extract_json_string(json, _T("secureContext"), errc), + std::move(portMappings), + utils::extract_json_string(json, _T("gameHostId"), errc), + utils::extract_json_string(json, _T("region"), errc) + ); + + return xbox_live_result(result, errc); +} + +game_server_host_status +game_server_ticket_status::convert_string_to_host_status( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("active")) == 0) + { + return game_server_host_status::active; + } + else if (utils::str_icmp(value, _T("queued")) == 0) + { + return game_server_host_status::queued; + } + else if (utils::str_icmp(value, _T("aborted")) == 0) + { + return game_server_host_status::aborted; + } + else if (utils::str_icmp(value, _T("error")) == 0) + { + return game_server_host_status::error; + } + + return game_server_host_status::unknown; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_variant.cpp b/Source/Services/GameServerPlatform/game_variant.cpp new file mode 100644 index 00000000..bf5005fd --- /dev/null +++ b/Source/Services/GameServerPlatform/game_variant.cpp @@ -0,0 +1,107 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_variant::game_variant() : + m_isPublisher(false), + m_rank(0) +{ +} + +game_variant::game_variant( + _In_ string_t id, + _In_ string_t name, + _In_ bool isPublisher, + _In_ uint64_t rank, + _In_ string_t schemaId + ) : + m_id(id), + m_name(std::move(name)), + m_isPublisher(isPublisher), + m_rank(rank), + m_schemaId(std::move(schemaId)) +{ +} + +const string_t& +game_variant::id() const +{ + return m_id; +} + +const string_t& +game_variant::name() const +{ + return m_name; +} + +bool +game_variant::is_publisher() const +{ + return m_isPublisher; +} + +uint64_t +game_variant::rank() const +{ + return m_rank; +} + +const string_t& +game_variant::schema_content() const +{ + return m_schema.schema_content(); +} + +const string_t& +game_variant::schema_name() const +{ + return m_schema.schema_name(); +} + +const string_t& +game_variant::schema_id() const +{ + return m_schemaId; +} + +xbox_live_result +game_variant::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto isPublisher = utils::extract_json_string(json, _T("isPublisher"), errc); + + auto result = game_variant( + utils::extract_json_string(json, _T("gamevariantId"), errc), + utils::extract_json_string(json, _T("name"), errc), + utils::str_icmp(isPublisher, _T("True")) == 0, + utils::extract_json_string_to_uint64(json, _T("rank"), errc), + utils::extract_json_string(json, _T("gameVariantSchemaId"), errc) + ); + + return xbox_live_result(result, errc); +} + +void game_variant::_Set_schema(_In_ game_variant_schema schema) +{ + m_schema = std::move(schema); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/game_variant_schema.cpp b/Source/Services/GameServerPlatform/game_variant_schema.cpp new file mode 100644 index 00000000..3d5bca4d --- /dev/null +++ b/Source/Services/GameServerPlatform/game_variant_schema.cpp @@ -0,0 +1,68 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +game_variant_schema::game_variant_schema() +{ +} + +game_variant_schema::game_variant_schema( + _In_ string_t schemaId, + _In_ string_t m_schemaContent, + _In_ string_t schemaName + ) : + m_schemaId(std::move(schemaId)), + m_schemaContent(std::move(m_schemaContent)), + m_schemaName(std::move(schemaName)) +{ +} + +const string_t& +game_variant_schema::schema_id() const +{ + return m_schemaId; +} + +const string_t& +game_variant_schema::schema_content() const +{ + return m_schemaContent; +} + +const string_t& +game_variant_schema::schema_name() const +{ + return m_schemaName; +} + +xbox_live_result +game_variant_schema::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = game_variant_schema( + utils::extract_json_string(json, _T("variantSchemaId"), errc), + utils::extract_json_string(json, _T("schemaContent"), errc), + utils::extract_json_string(json, _T("name"), errc) + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/GameServerPlatform/quality_of_service_server.cpp b/Source/Services/GameServerPlatform/quality_of_service_server.cpp new file mode 100644 index 00000000..bf4400f0 --- /dev/null +++ b/Source/Services/GameServerPlatform/quality_of_service_server.cpp @@ -0,0 +1,69 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/game_server_platform.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_BEGIN + +quality_of_service_server::quality_of_service_server() +{ +} + +quality_of_service_server::quality_of_service_server( + _In_ string_t serverFullQualifiedDomainName, + _In_ string_t secureDeviceAddressBase64, + _In_ string_t targetLocation + ) : + m_serverFullQualifiedDomainName(std::move(serverFullQualifiedDomainName)), + m_secureDeviceAddressBase64(std::move(secureDeviceAddressBase64)), + m_targetLocation(std::move(targetLocation)) +{ +} + +const string_t& +quality_of_service_server::server_full_qualified_domain_name() const +{ + return m_serverFullQualifiedDomainName; +} + +const string_t& +quality_of_service_server::secure_device_address_base64() const +{ + return m_secureDeviceAddressBase64; +} + +const string_t& +quality_of_service_server::target_location() const +{ + return m_targetLocation; +} + +xbox_live_result +quality_of_service_server::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = quality_of_service_server( + utils::extract_json_string(json, _T("serverFqdn"), errc), + utils::extract_json_string(json, _T("serverSecureDeviceAddress"), errc), + utils::extract_json_string(json, _T("targetLocation"), errc) + ); + + return xbox_live_result(result, errc); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_GAMESERVERPLATFORM_CPP_END diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardColumn.cpp b/Source/Services/Leaderboard/WinRT/LeaderboardColumn.cpp new file mode 100644 index 00000000..671e5985 --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardColumn.cpp @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "LeaderboardColumn.h" +#include "xsapi/leaderboard.h" + +using namespace pplx; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +LeaderboardColumn::LeaderboardColumn( + _In_ xbox::services::leaderboard::leaderboard_column cppObj) : + m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::PropertyType +LeaderboardColumn::StatisticType::get() +{ + using namespace xbox::services::leaderboard; + + switch (m_cppObj.stat_type()) + { + case leaderboard_stat_type::stat_uint64: + return PropertyType::UInt64; + case leaderboard_stat_type::stat_double: + return PropertyType::Double; + case leaderboard_stat_type::stat_string: + return PropertyType::String; + case leaderboard_stat_type::stat_datetime: + return PropertyType::DateTime; + case leaderboard_stat_type::stat_other: + default: + return PropertyType::OtherType; + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardColumn.h b/Source/Services/Leaderboard/WinRT/LeaderboardColumn.h new file mode 100644 index 00000000..7119ff64 --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardColumn.h @@ -0,0 +1,53 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/leaderboard.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +/// +/// Represents a column in a collection of leaderboard items. +/// +public ref class LeaderboardColumn sealed +{ +public: + + /// + /// DEPRECATED + /// The display name of the column. + /// + DEFINE_PROP_GET_STR_OBJ(DisplayName, display_name) + + /// + /// The name the statistic displayed in the column. + /// + DEFINE_PROP_GET_STR_OBJ(StatisticName, stat_name) + + /// + /// The property type of the statistic in the column. + /// The type can be one of the following: + /// PropertyType.Uint64, PropertyType.Double, + /// PropertyType.String, PropertyType.DateTime, + /// or PropertyType.OtherType if unknown. + /// + property Windows::Foundation::PropertyType StatisticType { Windows::Foundation::PropertyType get(); } + +internal: + LeaderboardColumn( + _In_ xbox::services::leaderboard::leaderboard_column cppObj + ); + +private: + xbox::services::leaderboard::leaderboard_column m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardResult.cpp b/Source/Services/Leaderboard/WinRT/LeaderboardResult.cpp new file mode 100644 index 00000000..b810c001 --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardResult.cpp @@ -0,0 +1,67 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "LeaderboardResult.h" +#include "xsapi/leaderboard.h" +#include "Utils_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::leaderboard; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +LeaderboardResult::LeaderboardResult( + _In_ xbox::services::leaderboard::leaderboard_result cppObj) : + m_cppObj(std::move(cppObj)) +{ + m_rows = ref new Vector(); + + for (const auto& row : m_cppObj.rows()) + { + m_rows->Append(ref new LeaderboardRow(row)); + } + + m_columns = ref new Vector(); + + for (const auto& column : m_cppObj.columns()) + { + m_columns->Append(ref new LeaderboardColumn(column)); + } +} + +Windows::Foundation::Collections::IVectorView^ +LeaderboardResult::Columns::get() +{ + return m_columns->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +LeaderboardResult::Rows::get() +{ + return m_rows->GetView(); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardResult::GetNextAsync(_In_ uint32 maxItems) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox::services::xbox_live_result lb) + { + return ref new LeaderboardResult(std::move(lb.payload())); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardResult.h b/Source/Services/Leaderboard/WinRT/LeaderboardResult.h new file mode 100644 index 00000000..a8a3dae9 --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardResult.h @@ -0,0 +1,88 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/leaderboard.h" +#include "Macros_WinRT.h" +#include "LeaderboardColumn.h" +#include "LeaderboardRow.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +/// +/// Represents the results of a leaderboard request. +/// +public ref class LeaderboardResult sealed +{ +public: + + /// + /// DEPRECATED + /// The display name of the leaderboard results. + /// + DEFINE_PROP_GET_STR_OBJ(DisplayName, display_name) + + /// + /// The total number of rows in the leaderboard results. + /// + DEFINE_PROP_GET_OBJ(TotalRowCount, total_row_count, uint32); + + /// + /// The collection of columns in the leaderboard results. + /// + property Windows::Foundation::Collections::IVectorView^ Columns + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The collection of rows in the leaderboard results. + /// + property Windows::Foundation::Collections::IVectorView^ Rows + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// Indicates whether there is a next page of results. + /// + /// True if there is another page of results; otherwise false. + DEFINE_PROP_GET_OBJ(HasNext, has_next, bool); + + /// + /// Get the next page of a previous leaderboard call using the same service config Id and leaderboard name. + /// + /// The maximum number of items to return. + /// A LeaderboardResults object that contains the next set of results. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V1 GET + /// /scids/{scid}/leaderboards/{leaderboardname}? + /// [maxItems={maxItems}] + /// [continuationToken={token}] + /// + Windows::Foundation::IAsyncOperation^ GetNextAsync(_In_ uint32 maxItems); + +internal: + LeaderboardResult( + _In_ xbox::services::leaderboard::leaderboard_result cppObj + ); + +private: + xbox::services::leaderboard::leaderboard_result m_cppObj; + Windows::Foundation::Collections::IVector^ m_columns; + Windows::Foundation::Collections::IVector^ m_rows; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardRow.cpp b/Source/Services/Leaderboard/WinRT/LeaderboardRow.cpp new file mode 100644 index 00000000..f9325efe --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardRow.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "LeaderboardRow.h" +#include "xsapi/leaderboard.h" + +using namespace pplx; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +LeaderboardRow::LeaderboardRow( + _In_ xbox::services::leaderboard::leaderboard_row cppObj) : + m_cppObj(std::move(cppObj)) +{ + m_values = ref new Vector(); + + for (const auto& value : m_cppObj.column_values()) + { + m_values->Append(ref new String(value.c_str())); + } +} + +Windows::Foundation::Collections::IVectorView^ +LeaderboardRow::Values::get() +{ + return m_values->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardRow.h b/Source/Services/Leaderboard/WinRT/LeaderboardRow.h new file mode 100644 index 00000000..8a735957 --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardRow.h @@ -0,0 +1,62 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/leaderboard.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +/// +/// Represents a row in a collection of leaderboard items. +/// +public ref class LeaderboardRow sealed +{ +public: + + /// + /// The Gamertag of the player. + /// + DEFINE_PROP_GET_STR_OBJ(Gamertag, gamertag) + + /// + /// The Xbox user ID of the player. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id) + + /// + /// The percentile rank of the player. + /// + DEFINE_PROP_GET_OBJ(Percentile, percentile, double); + + /// + /// The rank of the player. + /// + DEFINE_PROP_GET_OBJ(Rank, rank, uint32); + + /// + /// Values for each column in the leaderboard row for the player. + /// + property Windows::Foundation::Collections::IVectorView^ Values + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + LeaderboardRow( + _In_ xbox::services::leaderboard::leaderboard_row cppObj + ); + +private: + xbox::services::leaderboard::leaderboard_row m_cppObj; + Windows::Foundation::Collections::IVector^ m_values; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardService.cpp b/Source/Services/Leaderboard/WinRT/LeaderboardService.cpp new file mode 100644 index 00000000..942be0a1 --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardService.cpp @@ -0,0 +1,364 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "LeaderboardService.h" +#include "xsapi/leaderboard.h" +#include "Utils_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::leaderboard; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services; + +#define PROJECT_LB(task) task.then([](xbox_live_result lb) \ + { \ + THROW_IF_ERR(lb); \ + return ref new LeaderboardResult(lb.payload()); \ + }); + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +LeaderboardService::LeaderboardService( + _In_ xbox::services::leaderboard::leaderboard_service cppObj) : + m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName) + )); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(additionalColumns) + )); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 maxItems + ) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + STRING_T_FROM_PLATFORM_STRING(xuid), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems, + std::vector() + )); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + STRING_T_FROM_PLATFORM_STRING(xuid), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems, + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(additionalColumns) + )); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ uint32 skipToRank, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + skipToRank, + maxItems, + std::vector())); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ uint32 skipToRank, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + skipToRank, + maxItems, + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(additionalColumns))); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 skipToRank, + _In_ uint32 maxItems + ) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + skipToRank, + STRING_T_FROM_PLATFORM_STRING(xuid), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems, + std::vector())); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 skipToRank, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + skipToRank, + STRING_T_FROM_PLATFORM_STRING(xuid), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems, + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(additionalColumns))); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithSkipToUserAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_opt_ Platform::String^ skipToXboxUserId, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_skip_to_xuid( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + STRING_T_FROM_PLATFORM_STRING(skipToXboxUserId), + maxItems, + std::vector())); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithSkipToUserWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ skipToXboxUserId, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_skip_to_xuid( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + STRING_T_FROM_PLATFORM_STRING(skipToXboxUserId), + maxItems, + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(additionalColumns))); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithSkipToUserAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ skipToXboxUserId, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 maxItems + ) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_skip_to_xuid( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + STRING_T_FROM_PLATFORM_STRING(skipToXboxUserId), + STRING_T_FROM_PLATFORM_STRING(xuid), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems, + std::vector())); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardWithSkipToUserWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ skipToXboxUserId, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_skip_to_xuid( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(leaderboardName), + STRING_T_FROM_PLATFORM_STRING(skipToXboxUserId), + STRING_T_FROM_PLATFORM_STRING(xuid), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems, + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(additionalColumns))); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardForSocialGroupAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_for_social_group( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(statisticName), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + maxItems)); + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardForSocialGroupAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_ Platform::String^ sortOrder, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_for_social_group( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(statisticName), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + STRING_T_FROM_PLATFORM_STRING(sortOrder), + maxItems)); + + return ASYNC_FROM_TASK(task); +} +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardForSocialGroupWithSkipToRankAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_ uint32 skipToRank, + _In_ Platform::String^ sortOrder, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_for_social_group_skip_to_rank( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(statisticName), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + skipToRank, + STRING_T_FROM_PLATFORM_STRING(sortOrder), + maxItems)); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +LeaderboardService::GetLeaderboardForSocialGroupWithSkipToUserAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_opt_ Platform::String^ skipToXboxUserId, + _In_ Platform::String^ sortOrder, + _In_ uint32 maxItems) +{ + auto task = PROJECT_LB( + m_cppObj.get_leaderboard_for_social_group_skip_to_xuid( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(statisticName), + STRING_T_FROM_PLATFORM_STRING(socialGroup), + STRING_T_FROM_PLATFORM_STRING(skipToXboxUserId), + STRING_T_FROM_PLATFORM_STRING(sortOrder), + maxItems)); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/WinRT/LeaderboardService.h b/Source/Services/Leaderboard/WinRT/LeaderboardService.h new file mode 100644 index 00000000..4776836a --- /dev/null +++ b/Source/Services/Leaderboard/WinRT/LeaderboardService.h @@ -0,0 +1,533 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/leaderboard.h" +#include "Macros_WinRT.h" +#include "LeaderboardColumn.h" +#include "LeaderboardRow.h" +#include "LeaderboardResult.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_BEGIN + +/// +/// Represents the leaderboard service. +/// +public ref class LeaderboardService sealed +{ +public: + + /// + /// Get a leaderboard for a single leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET /scids/{scid}/leaderboards/{leaderboardname} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName + ); + + /// + /// Get a page of leaderboard results for a single leaderboard given a service configuration ID + /// and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The number of ranks to skip before retrieving results. + /// The maximum number of items to retrieve. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipItems={skipItems}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ uint32 skipToRank, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard that shows members of a specified social group for a single leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET /scids/{scid}/leaderboards/{leaderboardname} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard that shows members of a specified social group for a single leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The number of ranks to skip before retrieving results. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET /scids/{scid}/leaderboards/{leaderboardname} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 skipToRank, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard with additional columns for a single leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The name of the stats for the additional columns. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET /scids/{scid}/leaderboards/{leaderboardname} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns + ); + + /// + /// Get a leaderboard that shows members of a specified social group with additional columns for a single + /// leaderboard given a service configuration ID and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The name of the stats for the additional columns. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET /scids/{scid}/leaderboards/{leaderboardname} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ); + + /// + /// Get a page of leaderboard results with additional columns for a single leaderboard given a service configuration ID + /// and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The number of ranks to skip before retrieving results. + /// The name of the stats for the additional columns. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipItems={skipItems}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ uint32 skipToRank, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ); + + /// + /// Get a page of leaderboard results with additional columns for a single leaderboard given a service configuration ID + /// and a leaderboard name. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The number of ranks to skip before retrieving results. + /// The name of the stats for the additional columns. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows, + /// ordered by player rank descending. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipItems={skipItems}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ uint32 skipToRank, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard starting at a specified player, regardless of the player's rank or score, ordered by + /// the player's percentile rank. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the player to skip to before retrieving results. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// There is no continuation Token provided for this query. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipToUser={xuid}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithSkipToUserAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_opt_ Platform::String^ skipToXboxUserId, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard starting at a specified player, regardless of the player's rank or score, ordered by + /// the player's percentile rank. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The Xbox user ID of the player to skip to before retrieving results. + /// The maximum number of items to return. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// There is no continuation Token provided for this query. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipToUser={xuid}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithSkipToUserAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ Platform::String^ skipToXboxUserId, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard starting at a specified player, regardless of the player's rank or score, ordered by + /// the player's percentile rank. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the requesting user. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The Xbox user ID of the player to skip to before retrieving results. + /// The maximum number of items to return. + /// The name of the stats for the additional columns. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// There is no continuation Token provided for this query. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipToUser={xuid}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithSkipToUserWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ skipToXboxUserId, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ); + + /// + /// Get a leaderboard starting at a specified player, regardless of the player's rank or score, ordered by + /// the player's percentile rank. + /// + /// The service configuration ID (SCID) of the title + /// The name of the leaderboard. + /// The Xbox user ID of the player to skip to before retrieving results. + /// The maximum number of items to return. + /// The name of the stats for the additional columns. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// There is no continuation Token provided for this query. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V3 GET + /// /scids/{scid}/leaderboards/{leaderboardname}?[&skipToUser={xuid}][&maxItems={maxItems}] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardWithSkipToUserWithAdditionalColumnsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ leaderboardName, + _In_ Platform::String^ xuid, + _In_ Platform::String^ socialGroup, + _In_ Platform::String^ skipToXboxUserId, + _In_ Windows::Foundation::Collections::IVectorView^ additionalColumns, + _In_ uint32 maxItems + ); + + /// + /// Get an unsorted leaderboard that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The maximum number of items to retrieve. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardForSocialGroupAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_ uint32 maxItems + ); + + /// + /// Get a sorted leaderboard that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites}[?sort=descending|ascending] + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardForSocialGroupAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_ Platform::String^ sortOrder, + _In_ uint32 maxItems + ); + + /// + /// Get a sorted leaderboard, starting at a specified rank, that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The number of ranks to skip before retrieving results. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. + /// + /// A LeaderboardResult object containing a collection of the leaderboard columns and rows. + /// + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the + /// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the + /// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites}[?sort=descending|ascending]&skipToRank={skipToUser} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardForSocialGroupWithSkipToRankAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_ uint32 skipToRank, + _In_ Platform::String^ sortOrder, + _In_ uint32 maxItems + ); + + /// + /// Get a sorted leaderboard, starting at a specified player, that shows members of a specified social group. + /// + /// The Xbox user ID of the requesting user. + /// The service configuration ID (SCID) of the title + /// The name of the statistic to get a leaderboard for. + /// The name of the group of users to get get leaderboard results for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// The Xbox user ID of the player to skip to before retrieving results. + /// A value indicating the sort order for the returned leaderboard result. + /// The possible values are 'ascending' or 'descending', without quotes. + /// The maximum number of items to retrieve. + /// + /// A LeaderboardResult object that contains a page of leaderboard results around the specifed player regardless + /// of that player's rank or score. + /// The result page is ordered by percentile rank, with the specified player in the last position of + /// the page for predefined views, or in the middle for stat leaderboard views. + /// + /// + /// There is no continuation Token provided for this query. + /// + /// Calls V1 GET + /// https://leaderboards.xboxlive.com/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{all|favorites}[?sort=descending|ascending]&skipToUser={skipToUser} + /// + Windows::Foundation::IAsyncOperation^ GetLeaderboardForSocialGroupWithSkipToUserAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName, + _In_ Platform::String^ socialGroup, + _In_opt_ Platform::String^ skipToXboxUserId, + _In_ Platform::String^ sortOrder, + _In_ uint32 maxItems + ); + +internal: + LeaderboardService( + _In_ xbox::services::leaderboard::leaderboard_service cppObj); + +private: + xbox::services::leaderboard::leaderboard_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_column.cpp b/Source/Services/Leaderboard/leaderboard_column.cpp new file mode 100644 index 00000000..94c55131 --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_column.cpp @@ -0,0 +1,42 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/leaderboard.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN + +leaderboard_column::leaderboard_column( + _In_ string_t display_name, + _In_ string_t statName, + _In_ leaderboard_stat_type stat_type + ) : + m_displayName(std::move(display_name)), + m_statName(std::move(statName)), + m_stat_type(std::move(stat_type)) +{ +} + +const string_t& leaderboard_column::display_name() const +{ + return m_displayName; +} + +const string_t& leaderboard_column::stat_name() const +{ + return m_statName; +} + +leaderboard_stat_type leaderboard_column::stat_type() const +{ + return m_stat_type; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_query.h b/Source/Services/Leaderboard/leaderboard_query.h new file mode 100644 index 00000000..c97fbe74 --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_query.h @@ -0,0 +1,36 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "shared_macros.h" +#include "xsapi/types.h" +#include + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN + +struct leaderboard_global_query +{ + string_t scid; + string_t name; + string_t xuid; + string_t socialGroup; + std::vector columns; +}; + +struct leaderboard_social_query +{ + string_t xuid; + string_t scid; + string_t statName; + string_t socialGroup; + string_t sortOrder; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_result.cpp b/Source/Services/Leaderboard/leaderboard_result.cpp new file mode 100644 index 00000000..8907a4fb --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_result.cpp @@ -0,0 +1,179 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "leaderboard_query.h" +#include "xsapi/leaderboard.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN + +leaderboard_result::leaderboard_result() : + m_totalRowCount(0) +{ +} + +leaderboard_result::leaderboard_result( + _In_ string_t display_name, + _In_ uint32_t total_row_count, + _In_ string_t continuationToken, + _In_ std::vector columns, + _In_ std::vector rows, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_displayName(std::move(display_name)), + m_totalRowCount(total_row_count), + m_continuationToken(std::move(continuationToken)), + m_columns(std::move(columns)), + m_rows(std::move(rows)), + m_userContext(std::move(userContext)), + m_appConfig(std::move(appConfig)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)) +{ +} + +const string_t& leaderboard_result::display_name() const +{ + return m_displayName; +} + +uint32_t leaderboard_result::total_row_count() const +{ + return m_totalRowCount; +} + +const std::vector& leaderboard_result::columns() const +{ + return m_columns; +} + +const std::vector& leaderboard_result::rows() const +{ + return m_rows; +} + +void leaderboard_result::_Set_next_query(std::shared_ptr query) +{ + m_globalQuery = std::move(query); +} + +void leaderboard_result::_Set_next_query(std::shared_ptr query) +{ + m_socialQuery = std::move(query); +} + +void leaderboard_result::_Parse_additional_columns(const std::vector& additionalColumnNames) +{ + std::vector columns; + if (m_columns.size() == 0) + { + return; + } + columns.push_back(m_columns[0]); + + std::unordered_map stats; + + for (auto& row : m_rows) + { + for (uint32_t i = 0; i < additionalColumnNames.size(); ++i) + { + const string_t& columnName = additionalColumnNames[i]; + auto stat = stats.find(columnName); + const web::json::value& val = row.m_metadata[columnName]; + if (stat == stats.end() || stat->second == leaderboard_stat_type::stat_other) + { + if(val.is_boolean()) + { + stats[columnName] = leaderboard_stat_type::stat_boolean; + } + else if (val.is_number()) + { + stats[columnName] = leaderboard_stat_type::stat_double; + } + else if (val.is_string()) + { + stats[columnName] = leaderboard_stat_type::stat_string; + } + else + { + stats[columnName] = leaderboard_stat_type::stat_other; + } + + } + if (i >= row.m_columnValues.size() - 1) + { + row.m_columnValues.push_back(val.serialize()); + } + else + { + row.m_columnValues[i] = val.serialize(); + } + } + } + + for (const auto& columnName : additionalColumnNames) + { + columns.push_back(leaderboard_column(columnName, columnName, stats[columnName])); + } + m_columns = columns; +} + +bool leaderboard_result::has_next() const +{ + return !m_continuationToken.empty(); +} + +pplx::task> leaderboard_result::get_next(_In_ uint32_t maxItems) const +{ + if (m_continuationToken.empty()) + { + return pplx::task_from_result(xbox_live_result(xbox_live_error_code::out_of_range, "leadboard_result does not have a next page")); + } + + leaderboard_service service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + + if (m_globalQuery != nullptr) + { + string_t& scid = m_globalQuery->scid; + string_t& name = m_globalQuery->name; + string_t& xuid = m_globalQuery->xuid; + string_t& socialGroup = m_globalQuery->socialGroup; + std::vector& columns = m_globalQuery->columns; + return service.get_leaderboard_internal( + scid, + name, + NO_SKIP_RANK, + NO_SKIP_XUID, + xuid, + socialGroup, + maxItems, + m_continuationToken, + columns); + } + else if (m_socialQuery != nullptr) + { + return service.get_leaderboard_for_social_group_internal( + m_socialQuery->xuid, + m_socialQuery->scid, + m_socialQuery->statName, + m_socialQuery->socialGroup, + NO_SKIP_RANK, + NO_SKIP_XUID, + m_socialQuery->sortOrder, + maxItems, + m_continuationToken); + } + + // This should never happen + return pplx::task_from_result(xbox_live_result(xbox_live_error_code::runtime_error, "no query found to continue")); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_row.cpp b/Source/Services/Leaderboard/leaderboard_row.cpp new file mode 100644 index 00000000..21343dcd --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_row.cpp @@ -0,0 +1,60 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/leaderboard.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN + +leaderboard_row::leaderboard_row( + _In_ string_t gamertag, + _In_ string_t xboxUserId, + _In_ double percentile, + _In_ uint32_t rank, + _In_ std::vector columnValues, + _In_ string_t metadata) : + m_gamertag(std::move(gamertag)), + m_xboxUserId(std::move(xboxUserId)), + m_percentile(percentile), + m_rank(rank), + m_columnValues(std::move(columnValues)) +{ + if(!metadata.empty()) + { + m_metadata = web::json::value::parse(metadata); + } +} + +const string_t& leaderboard_row::gamertag() const +{ + return m_gamertag; +} + +const string_t& leaderboard_row::xbox_user_id() const +{ + return m_xboxUserId; +} + +double leaderboard_row::percentile() const +{ + return m_percentile; +} + +uint32_t leaderboard_row::rank() const +{ + return m_rank; +} + +const std::vector& leaderboard_row::column_values() const +{ + return m_columnValues; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_serializers.cpp b/Source/Services/Leaderboard/leaderboard_serializers.cpp new file mode 100644 index 00000000..3ae59ae8 --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_serializers.cpp @@ -0,0 +1,134 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "utils.h" +#include "xsapi/leaderboard.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN +namespace serializers { + +leaderboard_stat_type parse_stat_type( + _In_ const string_t& type + ) +{ + if (type == _T("Integer")) + return leaderboard_stat_type::stat_uint64; + if (type == _T("Double")) + return leaderboard_stat_type::stat_double; + if (type == _T("String")) + return leaderboard_stat_type::stat_string; + if (type == _T("DateTime")) + return leaderboard_stat_type::stat_datetime; + + return leaderboard_stat_type::stat_other; +} + +leaderboard_row +deserialize_row( + _In_ const web::json::value& json, + _In_ std::error_code& errc + ) +{ + string_t gamertag = utils::extract_json_string(json, _T("gamertag"), errc, true); + string_t xuid = utils::extract_json_string(json, _T("xuid"), errc, true); + double percentile = utils::extract_json_double(json, _T("percentile"), errc, true); + int rank = utils::extract_json_int(json, _T("rank"), errc, true); + std::vector values; + web::json::object jsonObject = json.as_object(); + if(!jsonObject[_T("value")].is_null()) + { + values.push_back(utils::extract_json_string(json, _T("value"), errc, true)); + } + else + { + values = utils::extract_json_vector(utils::json_string_extractor, json, _T("values"), errc, true); + } + auto metadata = utils::extract_json_string(json, _T("valuemetadata"), errc, false); + + return leaderboard_row( + std::move(gamertag), + std::move(xuid), + percentile, + rank, + values, + metadata + ); +} + +leaderboard_column +deserialize_column( + _In_ const web::json::value& json, + _In_ std::error_code& errc + ) +{ + string_t statName = utils::extract_json_string(json, _T("statName"), errc, true); + string_t stat_type = utils::extract_json_string(json, _T("type"), errc, true); + + return leaderboard_column( + string_t(), + std::move(statName), + parse_stat_type(stat_type) + ); +} + +xbox_live_result +deserialize_result( + _In_ const web::json::value& json, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + std::error_code errc; + web::json::value lb_info = utils::extract_json_field(json, _T("leaderboardInfo"), errc, true); + int totalCount = utils::extract_json_int(lb_info, _T("totalCount"), errc, true); + + web::json::value paging_info = utils::extract_json_field(json, _T("pagingInfo"), errc, false); + string_t continuationToken; + if (!paging_info.is_null()) + { + continuationToken = utils::extract_json_string(paging_info, _T("continuationToken"), errc, false); + } + + std::vector columns; + web::json::value json_column = + utils::extract_json_field(lb_info, _T("columnDefinition"), errc, true); + + columns.push_back(deserialize_column(json_column, errc)); + + std::vector rows; + web::json::array json_rows = + utils::extract_json_as_array( + utils::extract_json_field(json, _T("userList"), errc, true), + errc + ); + + for (const auto& row : json_rows) + { + rows.push_back(deserialize_row(row, errc)); + } + + auto result = leaderboard_result( + string_t(), + totalCount, + std::move(continuationToken), + std::move(columns), + std::move(rows), + userContext, + xboxLiveContextSettings, + appConfig + ); + + return xbox_live_result(result, errc); +} + +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_serializers.h b/Source/Services/Leaderboard/leaderboard_serializers.h new file mode 100644 index 00000000..2beee548 --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_serializers.h @@ -0,0 +1,31 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "shared_macros.h" +#include "leaderboard_query.h" +#include "xsapi/leaderboard.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN +namespace serializers { + +leaderboard_row deserialize_row(_In_ const web::json::value& json, _In_ std::error_code& errc); + +leaderboard_column deserialize_column(_In_ const web::json::value& json, _In_ std::error_code& errc); + +xbox_live_result deserialize_result( + _In_ const web::json::value& json, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Leaderboard/leaderboard_service.cpp b/Source/Services/Leaderboard/leaderboard_service.cpp new file mode 100644 index 00000000..68fd4bb2 --- /dev/null +++ b/Source/Services/Leaderboard/leaderboard_service.cpp @@ -0,0 +1,534 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xbox_system_factory.h" +#include "leaderboard_serializers.h" +#include "leaderboard_query.h" +#include "xsapi/leaderboard.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_BEGIN + +const string_t c_leaderboard_social_stat_name_contract_version = _T("1"); +const string_t c_leaderboard_with_metadata_contract_version = _T("3"); + +leaderboard_service::leaderboard_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> leaderboard_service::get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const std::vector& additionalColumnNames + ) +{ + return get_leaderboard_internal( + scid, + name, + NO_SKIP_RANK, + NO_SKIP_XUID, + NO_XUID, + NO_SOCIAL_GROUP, + NO_MAX_ITEMS, + NO_CONTINUATION, + additionalColumnNames); +} + +pplx::task> leaderboard_service::get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems, + _In_ const std::vector& additionalColumnNames + ) +{ + return get_leaderboard_internal( + scid, + name, + NO_SKIP_RANK, + NO_SKIP_XUID, + xuid, + socialGroup, + maxItems, + NO_CONTINUATION, + additionalColumnNames); +} + +pplx::task> leaderboard_service::get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ uint32_t maxItems, + _In_ const std::vector& additionalColumnNames + ) +{ + return get_leaderboard_internal( + scid, + name, + skipToRank, + NO_SKIP_XUID, + NO_XUID, + NO_SOCIAL_GROUP, + maxItems, + NO_CONTINUATION, + additionalColumnNames); +} + + +pplx::task> leaderboard_service::get_leaderboard( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems, + _In_ const std::vector& additionalColumnNames + ) +{ + return get_leaderboard_internal( + scid, + name, + skipToRank, + NO_SKIP_XUID, + xuid, + socialGroup, + maxItems, + NO_CONTINUATION, + additionalColumnNames); +} + +pplx::task> leaderboard_service::get_leaderboard_skip_to_xuid( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const string_t& skipToXuid, + _In_ uint32_t maxItems, + _In_ const std::vector& additionalColumnNames + ) +{ + return get_leaderboard_internal( + scid, + name, + NO_SKIP_RANK, + skipToXuid, + NO_XUID, + NO_SOCIAL_GROUP, + maxItems, + NO_CONTINUATION, + additionalColumnNames); +} + +_XSAPIIMP pplx::task> leaderboard_service::get_leaderboard_skip_to_xuid( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ const string_t& skipToXuid, + _In_ uint32_t maxItems, + _In_ const std::vector& additionalColumnNames + ) +{ + return get_leaderboard_internal( + scid, + name, + NO_SKIP_RANK, + skipToXuid, + xuid, + socialGroup, + maxItems, + NO_CONTINUATION, + additionalColumnNames); +} + +pplx::task> leaderboard_service::get_leaderboard_for_social_group( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems + ) +{ + return get_leaderboard_for_social_group_internal( + xuid, + scid, + statName, + socialGroup, + NO_SKIP_RANK, + NO_SKIP_XUID, + NO_SORT_ORDER, + maxItems, + NO_CONTINUATION); +} + +pplx::task> leaderboard_service::get_leaderboard_for_social_group( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems + ) +{ + return get_leaderboard_for_social_group_internal( + xuid, + scid, + statName, + socialGroup, + NO_SKIP_RANK, + NO_SKIP_XUID, + sortOrder, + maxItems, + NO_CONTINUATION); +} + +pplx::task> leaderboard_service::get_leaderboard_for_social_group_skip_to_rank( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t skipToRank, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems + ) +{ + return get_leaderboard_for_social_group_internal( + xuid, + scid, + statName, + socialGroup, + skipToRank, + NO_SKIP_XUID, + sortOrder, + maxItems, + NO_CONTINUATION); +} + +pplx::task> leaderboard_service::get_leaderboard_for_social_group_skip_to_xuid( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ const string_t& skipToXuid, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems + ) +{ + return get_leaderboard_for_social_group_internal( + xuid, + scid, + statName, + socialGroup, + NO_SKIP_RANK, + skipToXuid, + sortOrder, + maxItems, + NO_CONTINUATION); +} + +xbox_live_result create_leaderboard_url( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ const string_t& skipToXuid, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ bool metadata, + _In_ const string_t& xuid = string_t(), + _In_ const string_t& socialGroup = string_t() + ) +{ + if (scid.empty()) + return xbox_live_result(xbox_live_error_code::invalid_argument, "scid is required for getting leaderboards"); + if (name.empty()) + return xbox_live_result(xbox_live_error_code::invalid_argument, "name is required for getting leaderboards"); + + web::uri_builder builder; + + stringstream_t path; + path << _T("/scids/"); + path << web::uri::encode_uri(scid, web::uri::components::path); + path << _T("/leaderboards/"); + path << web::uri::encode_uri(name, web::uri::components::path); + builder.set_path(path.str()); + + if (metadata) + { + builder.append_query(_T("include"), _T("valuemetadata")); + } + + if (!xuid.empty()) + { + builder.append_query(_T("xuid"), xuid); + } + + if (maxItems > 0) + { + builder.append_query(_T("maxItems"), maxItems); + } + + if (!skipToXuid.empty()) + { + if (skipToRank > 0) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Cannot skip to XUID and rank"); + } + + builder.append_query(_T("skipToUser"), skipToXuid); + } + else + { + if (!continuationToken.empty()) + { + builder.append_query(_T("continuationToken"), continuationToken); + } + else if (skipToRank > 0) + { + builder.append_query(_T("skipToRank"), skipToRank); + } + } + + if (!socialGroup.empty()) + { + builder.append_query(_T("view"), _T("People")); + builder.append_query(_T("viewTarget"), socialGroup); + } + + return xbox_live_result(builder.to_string()); +} + +pplx::task> leaderboard_service::get_leaderboard_internal( + _In_ const string_t& scid, + _In_ const string_t& name, + _In_ uint32_t skipToRank, + _In_ const string_t& skipToXuid, + _In_ const string_t& xuid, + _In_ const string_t& socialGroup, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ const std::vector& additionalColumnNames + ) +{ + xbox_live_result url = create_leaderboard_url( + scid, + name, + skipToRank, + skipToXuid, + maxItems, + continuationToken, + additionalColumnNames.size() != 0, + xuid, + socialGroup + ); + + RETURN_TASK_CPP_IF_ERR(url, leaderboard_result); + + std::shared_ptr query = std::make_shared(); + query->scid = scid; + query->name = name; + query->xuid = xuid; + query->socialGroup = socialGroup; + query->columns = additionalColumnNames; + + std::shared_ptr http_call = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("leaderboards"), m_appConfig), + url.payload(), + xbox_live_api::get_leaderboard_internal + ); + + http_call->set_xbox_contract_version_header_value(c_leaderboard_with_metadata_contract_version); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + + auto task = http_call->get_response_with_auth(m_userContext) + .then([userContext, xboxLiveContextSettings, appConfig, additionalColumnNames](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + serializers::deserialize_result( + response->response_body_json(), + userContext, + xboxLiveContextSettings, + appConfig + ), + response + ); + + }).then([query, additionalColumnNames](xbox_live_result lb) + { + leaderboard_result& lbRes = lb.payload(); + lbRes._Set_next_query(query); + if (additionalColumnNames.size() > 0) + { + lbRes._Parse_additional_columns(additionalColumnNames); + } + + return lb; + }); + + return utils::create_exception_free_task( + task + ); +} + +xbox_live_result create_leaderboard_for_social_group_url( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t skipToRank, + _In_ const string_t& skipToXuid, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ) +{ + if (xuid.empty()) return xbox_live_result(xbox_live_error_code::invalid_argument, "xuid is required for getting leaderboard for social group"); + if (scid.empty()) return xbox_live_result(xbox_live_error_code::invalid_argument, "scid is required for getting leaderboard for social group"); + if (statName.empty()) return xbox_live_result(xbox_live_error_code::invalid_argument, "statName is required for getting leaderboard for social group"); + if (socialGroup.empty()) return xbox_live_result(xbox_live_error_code::invalid_argument, "socialGroup is required for getting leaderboard for social group"); + + // "/users/xuid({xuid})/scids/{scid}/stats/{statname}/people/{group}" + + web::uri_builder builder; + + stringstream_t path; + path << _T("/users/xuid("); + path << web::uri::encode_uri(xuid, web::uri::components::path); + path << _T(")/scids/"); + path << web::uri::encode_uri(scid, web::uri::components::path); + path << _T("/stats/"); + path << web::uri::encode_uri(statName, web::uri::components::path); + path << _T("/people/"); + path << web::uri::encode_uri(socialGroup, web::uri::components::path); + builder.set_path(path.str()); + + if (!sortOrder.empty()) + { + builder.append_query(_T("sort"), sortOrder); + } + + if (maxItems > 0) + { + builder.append_query(_T("maxItems"), maxItems); + } + + if (!skipToXuid.empty()) + { + builder.append_query(_T("skipToUser"), skipToXuid); + } + else + { + if (!continuationToken.empty()) + { + builder.append_query(_T("continuationToken"), continuationToken); + } + else if (skipToRank > 0) + { + builder.append_query(_T("skipToRank"), skipToRank); + } + } + + return xbox_live_result(builder.to_string()); +} + +pplx::task> leaderboard_service::get_leaderboard_for_social_group_internal( + _In_ const string_t& xuid, + _In_ const string_t& scid, + _In_ const string_t& statName, + _In_ const string_t& socialGroup, + _In_ uint32_t skipToRank, + _In_ const string_t& skipToXuid, + _In_ const string_t& sortOrder, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ) +{ + // To align with People moniker support, we are mapping "People" to "all" until the + // leaderboard service can align with naming conventions. + string_t group = socialGroup; + if (utils::str_icmp(socialGroup, _T("People")) == 0) + { + group = _T("all"); + } + + xbox_live_result url = create_leaderboard_for_social_group_url( + xuid, + scid, + statName, + group, + skipToRank, + skipToXuid, + sortOrder, + maxItems, + continuationToken); + + if (url.err()) + { + return pplx::task_from_result(xbox_live_result(url.err(), url.err_message())); + } + auto query = std::make_shared(); + query->xuid = xuid; + query->scid = scid; + query->statName = statName; + query->socialGroup = group; + query->sortOrder = sortOrder; + + std::shared_ptr http_call = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("leaderboards"), m_appConfig), + url.payload(), + xbox_live_api::get_leaderboard_for_social_group_internal + ); + + http_call->set_xbox_contract_version_header_value(c_leaderboard_social_stat_name_contract_version); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + + auto task = http_call->get_response_with_auth(m_userContext) + .then([userContext, xboxLiveContextSettings, appConfig](std::shared_ptr response) + { + + return utils::generate_xbox_live_result( + serializers::deserialize_result( + response->response_body_json(), + userContext, + xboxLiveContextSettings, + appConfig + ), + response + ); + + }).then([query](xbox_live_result lb) + { + auto leaderboardResult = lb.payload(); + leaderboardResult._Set_next_query(query); + return xbox_live_result(leaderboardResult, lb.err(), lb.err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.cpp b/Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.cpp new file mode 100644 index 00000000..192782cc --- /dev/null +++ b/Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.cpp @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "BrowseCatalogResult_WinRT.h" +#include "CatalogItem_WinRT.h" + +using namespace xbox::services::marketplace; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +BrowseCatalogResult::BrowseCatalogResult( + _In_ xbox::services::marketplace::browse_catalog_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_items = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.items())->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +BrowseCatalogResult::Items::get() +{ + return m_items; +} + +Windows::Foundation::IAsyncOperation^ +BrowseCatalogResult::GetNextAsync( + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox::services::xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new BrowseCatalogResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.h b/Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.h new file mode 100644 index 00000000..24c2b334 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/BrowseCatalogResult_WinRT.h @@ -0,0 +1,80 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" +#include "CatalogItem_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class BrowseCatalogResult sealed +{ +public: + // "Items": + // [ + // { + // // ... + // } + // ], + // + // "Totals": + // [ + // { + // "Name":"GameType", + // "Count":126, + // "MediaItemTypes": + // [ + // { + // "Name":"XboxGameConsumable", + // "Count":126 + // } + // ] + // } + // ], + + /// + /// Collection of XboxCatalogItem objects returned by a request + /// + property Windows::Foundation::Collections::IVectorView^ Items + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + // The total count of the items + /// + DEFINE_PROP_GET_OBJ(TotalCount, total_count, uint32); + + /// + /// Returns an BrowseCatalogResult object containing the next page of BrowseCatalogResult + /// + /// The maximum number of items the result can contain. Pass 0 to attempt retrieving all items. + /// A BrowseCatalogResult object. + /// Calls V3.2 GET /media/{marketplaceId}/browse + Windows::Foundation::IAsyncOperation^ GetNextAsync( + _In_ uint32 maxItems + ); + + /// + /// Indicates if there is additional data to retrieve from a GetNextAsync call + /// + DEFINE_PROP_GET_OBJ(HasNext, has_next, bool); + +internal: + BrowseCatalogResult( + _In_ xbox::services::marketplace::browse_catalog_result cppObj + ); + +private: + xbox::services::marketplace::browse_catalog_result m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_items; +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/BundleRelationshipType_WinRT.h b/Source/Services/Marketplace/WinRT/BundleRelationshipType_WinRT.h new file mode 100644 index 00000000..594f6930 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/BundleRelationshipType_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +/// Enumeration values that indicate the media item type +public enum class BundleRelationshipType +{ + /// Unknown media type. + Unknown = xbox::services::marketplace::bundle_relationship_type::unknown, + + /// Find which bundles include this product + BundlesWithProduct = xbox::services::marketplace::bundle_relationship_type::bundles_with_product, + + /// Find which products are included in a specified bundle + ProductsInBundle = xbox::services::marketplace::bundle_relationship_type::products_in_bundle +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.cpp b/Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.cpp new file mode 100644 index 00000000..737a4e7d --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "CatalogItemAvailability_WinRT.h" +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +CatalogItemAvailability::CatalogItemAvailability( + _In_ xbox::services::marketplace::catalog_item_availability cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_acceptablePaymentInstrumentTypes = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.acceptable_payment_Instrument_types())->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +CatalogItemAvailability::AcceptablePaymentInstrumentTypes::get() +{ + return m_acceptablePaymentInstrumentTypes; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.h new file mode 100644 index 00000000..620cc478 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItemAvailability_WinRT.h @@ -0,0 +1,130 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class CatalogItemAvailability sealed +{ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // "OfferDisplayData": + // { + // "acceptablePaymentInstrumentTypes": + // [ + // "CreditCard", + // "Tokens" + // ], + // "availabilityDescription":"AvailabilityDescription for 3cba007c-50db-4332-89c1-3ebc116fa27b", + // "currencyCode":"USD", + // "displayPrice":"$0.01", + // "displayListPrice":"$5.00", + // "distributionType":"Full", + // "isPurchasable":true, + // "listPrice":5.0, + // "price":0.01, + // "promotionalText":"Need Gold subscription. Click to buy" + // }, + // "SignedOffer":"etc" + // } + +public: + /// + /// The content ID + /// + DEFINE_PROP_GET_STR_OBJ(ContentId, content_id); + + /// + /// A collection of acceptable payment instrument types + /// + property Windows::Foundation::Collections::IVectorView^ AcceptablePaymentInstrumentTypes { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The title of the availability + /// + DEFINE_PROP_GET_STR_OBJ(AvailabilityTitle, availability_title); + + /// + /// The description of the availability + /// + DEFINE_PROP_GET_STR_OBJ(AvailabilityDescription, availability_description); + + /// + /// The currency code + /// + DEFINE_PROP_GET_STR_OBJ(CurrencyCode, currency_code); + + /// + /// The display price + /// + DEFINE_PROP_GET_STR_OBJ(DisplayPrice, display_price); + + /// + /// The display list price + /// + DEFINE_PROP_GET_STR_OBJ(DisplayListPrice, display_list_price); + + /// + /// The distribution type + /// + DEFINE_PROP_GET_STR_OBJ(DistributionType, distribution_type); + + /// + /// Indicates if the availability is purchasable + /// + DEFINE_PROP_GET_OBJ(IsPurchasable, is_purchasable, bool); + + /// + /// The list price in numeric form + /// + DEFINE_PROP_GET_OBJ(ListPrice, list_price, double); + + /// + /// The price in numeric form + /// + DEFINE_PROP_GET_OBJ(Price, price, double); + + /// + /// The quantity of the catalog item + /// + DEFINE_PROP_GET_OBJ(ConsumableQuantity, consumable_quantity, uint32); + + /// + /// The distribution type + /// + DEFINE_PROP_GET_STR_OBJ(PromotionalText, promotional_text); + + /// + /// The signed offer + /// + DEFINE_PROP_GET_STR_OBJ(SignedOffer, signed_offer); + + /// + /// The offer ID + /// + DEFINE_PROP_GET_STR_OBJ(OfferId, offer_id); + + /// + /// Json string that contains the offer display data. + /// + DEFINE_PROP_GET_STR_OBJ(OfferDisplayDataJson, offer_display_data_json); + +internal: + CatalogItemAvailability( + _In_ xbox::services::marketplace::catalog_item_availability cppObj + ); + +private: + xbox::services::marketplace::catalog_item_availability m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_acceptablePaymentInstrumentTypes; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.cpp b/Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.cpp new file mode 100644 index 00000000..0e48addd --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "CatalogItemDetails_WinRT.h" +#include "CatalogItemImage_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::marketplace; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +CatalogItemDetails::CatalogItemDetails( + _In_ xbox::services::marketplace::catalog_item_details cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_images = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.images())->GetView(); + m_availabilities = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.availabilities())->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +CatalogItemDetails::Images::get() +{ + return m_images; +} + +Windows::Foundation::Collections::IVectorView^ +CatalogItemDetails::Availabilities::get() +{ + return m_availabilities; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.h new file mode 100644 index 00000000..5f5f89f7 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItemDetails_WinRT.h @@ -0,0 +1,178 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" +#include "CatalogItemImage_WinRT.h" +#include "CatalogItemAvailability_WinRT.h" +#include "MediaItemType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class CatalogItemDetails sealed +{ + //{ + // "desiredMediaItemTypes":"Subscription.DGame.DGameDemo.DDurable.DConsumable.DApp", + // "MediaItemType":"DConsumable", + // "ID":"44c99601-7db8-4ad6-9610-218bbff99daf", + // "Name":"Gold Coins", + // "Description":"Consumable in-game currency", + // "ReleaseDate":"2013-05-15T00:00:00Z", + // "TitleId":"521617E4", + // "VuiDisplayName":"Gold Coins V", + // + // "Genres": + // [ + // { + // "Name":"Educational" + // } + // ], + // + // "Images": + // [ + // { + // "ID":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944", + // "ResizeUrl":"http://images.xboxlive.com/image?url=etc", + // "Purposes": + // [ + // "Box_Art" + // ], + // "Purpose":"Box_Art", + // "Height":1080, + // "Width":1080 + // } + // ], + // + // "SortName":"Gold s", + // "KValue":"4", + // "KValueNamespace":"bingbox", + // "LegacyIds": + // [ + // { + // "IdType":"ProductId", + // "Value":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944" + // } + // ], + // + // "Availabilities": + // [ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // "OfferDisplayData": + // { + // "acceptablePaymentInstrumentTypes": + // [ + // "CreditCard", + // "Tokens" + // ], + // "availabilityDescription":"AvailabilityDescription for 3cba007c-50db-4332-89c1-3ebc116fa27b", + // "currencyCode":"USD", + // "displayPrice":"$0.01", + // "displayListPrice":"$5.00", + // "distributionType":"Full", + // "isPurchasable":true, + // "listPrice":5.0, + // "price":0.01, + // "promotionalText":"Need Gold subscription. Click to buy" + // }, + // "SignedOffer":"Q" + // } + // ], + // "SandboxId":"DECO.0" + // "IsBundle": true, + // "IsPartOfAnyBundle": true + //} + +public: + /// + /// The media item type of the catalog item + /// + DEFINE_PROP_GET_ENUM_OBJ(MediaItemType, item_type, Microsoft::Xbox::Services::Marketplace::MediaItemType); + + /// + /// The catalog ID of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// The name of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The reduced name of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(ReducedName, reduced_name); + + /// + /// The description of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(Description, description); + + /// + /// The title ID of the catalog item + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The release date of the catalog item + /// + DEFINE_PROP_GET_DATETIME_OBJ(ReleaseDate, release_date); + + /// + /// The product ID of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(ProductId, product_id); + + /// + /// The sandbox ID of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(SandboxId, sandbox_id); + + /// + /// Is this product a Bundle and includes entitlements to other products + /// + DEFINE_PROP_GET_OBJ(IsBundle, is_bundle, bool); + + /// + /// Is this product a member of a bundle in the Marketplace + /// + DEFINE_PROP_GET_OBJ(IsPartOfAnyBundle, is_part_of_any_bundle, bool); + + /// + /// A collection of images for this catalog item + /// + property Windows::Foundation::Collections::IVectorView^ Images + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// A collection of images for this catalog item + /// + property Windows::Foundation::Collections::IVectorView^ Availabilities + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + CatalogItemDetails( + _In_ xbox::services::marketplace::catalog_item_details cppObj + ); + +private: + xbox::services::marketplace::catalog_item_details m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_images; + Windows::Foundation::Collections::IVectorView^ m_availabilities; +}; + +} // namespace Marketplace +} // namespace Services +} // namespace Xbox +} // namespace Microsoft diff --git a/Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.cpp b/Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.cpp new file mode 100644 index 00000000..4ac3dc5e --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "CatalogItemImage_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +CatalogItemImage::CatalogItemImage( + _In_ xbox::services::marketplace::catalog_item_image cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_purposes = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.purposes())->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +CatalogItemImage::Purposes::get() +{ + return m_purposes; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.h new file mode 100644 index 00000000..3c03d97c --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItemImage_WinRT.h @@ -0,0 +1,73 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class CatalogItemImage sealed +{ + // { + // "ID":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944", + // "ResizeUrl":"http://images.xboxlive.com/image?url=etc", + // "Purposes": + // [ + // "Box_Art" + // ], + // "Purpose":"Box_Art", + // "Height":1080, + // "Width":1080 + // } + +public: + /// + /// Returns the URI of the catalog item image + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// Returns the URI of the catalog item image + /// + DEFINE_PROP_GET_URI_OBJ(ResizeUrl, resize_url); + + /// + /// A collection of purposes + /// + property Windows::Foundation::Collections::IVectorView^ Purposes + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + // The default purpose of the catalog item image + /// + DEFINE_PROP_GET_STR_OBJ(Purpose, purpose); + + /// + // The height of the image + /// + DEFINE_PROP_GET_OBJ(Height, height, uint32); + + /// + // The width of the image + /// + DEFINE_PROP_GET_OBJ(Width, width, uint32); + +internal: + CatalogItemImage( + _In_ xbox::services::marketplace::catalog_item_image cppObj + ); + +private: + xbox::services::marketplace::catalog_item_image m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_purposes; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/CatalogItem_WinRT.cpp b/Source/Services/Marketplace/WinRT/CatalogItem_WinRT.cpp new file mode 100644 index 00000000..bb4e6879 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItem_WinRT.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "CatalogItem_WinRT.h" +#include "CatalogItemImage_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::marketplace; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +CatalogItem::CatalogItem( + _In_ xbox::services::marketplace::catalog_item cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_images = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.images())->GetView(); + m_availabilityContentIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.availability_content_ids())->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +CatalogItem::Images::get() +{ + return m_images; +} + +Windows::Foundation::Collections::IVectorView^ +CatalogItem::AvailabilityContentIds::get() +{ + return m_availabilityContentIds; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogItem_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogItem_WinRT.h new file mode 100644 index 00000000..07a06f8a --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogItem_WinRT.h @@ -0,0 +1,150 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" +#include "CatalogItemImage_WinRT.h" +#include "MediaItemType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class CatalogItem sealed +{ + //{ + // "desiredMediaItemTypes":"Subscription.DGame.DGameDemo.DDurable.DConsumable.DApp", + // "MediaItemType":"DConsumable", + // "ID":"44c99601-7db8-4ad6-9610-218bbff99daf", + // "Name":"Gold Coins", + // "ReleaseDate":"2013-05-15T00:00:00Z", + // "TitleId":"521617E4", + // "VuiDisplayName":"Gold Coins V", + // + // "Genres": + // [ + // { + // "Name":"Educational" + // } + // ], + // + // "Images": + // [ + // { + // "ID":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944", + // "ResizeUrl":"http://images.xboxlive.com/image?url=etc", + // "Purposes": + // [ + // "Box_Art" + // ], + // "Purpose":"Box_Art", + // "Height":1080, + // "Width":1080 + // } + // ], + // + // "SortName":"Gold s", + // "KValue":"4", + // "KValueNamespace":"bingbox", + // "LegacyIds": + // [ + // { + // "IdType":"ProductId", + // "Value":"b3e560ae-dd9c-4ac5-b41d-5ddee19a7944" + // } + // ], + // + // "Availabilities": + // [ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // } + // ], + // "SandboxId":"DECO.0", + // "IsBundle": true, + // "IsPartOfAnyBundle": true + //} + +public: + /// + /// The media type of the catalog item + /// + DEFINE_PROP_GET_ENUM_OBJ(MediaItemType, item_type, Microsoft::Xbox::Services::Marketplace::MediaItemType); + + /// + /// The catalog ID of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(Id, id); + + /// + /// The name of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The name of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(ReducedName, reduced_name); + + /// + /// The title ID of the catalog item + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The release date of the catalog item + /// + DEFINE_PROP_GET_DATETIME_OBJ(ReleaseDate, release_date); + + /// + /// The product ID of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(ProductId, product_id); + + /// + /// The sandbox ID of the catalog item + /// + DEFINE_PROP_GET_STR_OBJ(SandboxId, sandbox_id); + + /// + /// Is this product a Bundle and includes entitlements to other products + /// + DEFINE_PROP_GET_OBJ(IsBundle, is_bundle, bool); + + /// + /// Is this product a member of a bundle in the Marketplace + /// + DEFINE_PROP_GET_OBJ(IsPartOfAnyBundle, is_part_of_any_bundle, bool); + + /// + /// A collection of images for this catalog item + /// + property Windows::Foundation::Collections::IVectorView^ Images + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// A collection of availability content IDs for this catalog item + /// + property Windows::Foundation::Collections::IVectorView^ AvailabilityContentIds + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + CatalogItem( + _In_ xbox::services::marketplace::catalog_item cppObj + ); + +private: + xbox::services::marketplace::catalog_item m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_images; + Windows::Foundation::Collections::IVectorView^ m_availabilityContentIds; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogService_WinRT.cpp b/Source/Services/Marketplace/WinRT/CatalogService_WinRT.cpp new file mode 100644 index 00000000..38e7d1e9 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogService_WinRT.cpp @@ -0,0 +1,109 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "CatalogService_WinRT.h" + +using namespace Concurrency; +using namespace Platform::Collections; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace Windows::Storage::Streams; +using namespace Windows::Media; +using namespace Windows::Data::Json; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::marketplace; +using namespace xbox::services; + +#if TV_API +using namespace Windows::Media::ContentRestrictions; +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +CatalogService::CatalogService( + _In_ xbox::services::marketplace::catalog_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::IAsyncOperation^ +CatalogService::BrowseCatalogAsync( + _In_ Platform::String^ parentId, + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType parentMediaType, + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType childMediaType, + _In_ CatalogSortOrder orderBy, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.browse_catalog( + STRING_T_FROM_PLATFORM_STRING(parentId), + static_cast(parentMediaType), + static_cast(childMediaType), + static_cast(orderBy), + skipItems, + maxItems + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new BrowseCatalogResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +CatalogService::BrowseCatalogBundlesAsync( + _In_ Platform::String^ parentId, + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType parentMediaType, + _In_ Platform::String^ productId, + _In_ BundleRelationshipType relationship, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.browse_catalog_bundles( + STRING_T_FROM_PLATFORM_STRING(parentId), + static_cast(parentMediaType), + STRING_T_FROM_PLATFORM_STRING(productId), + static_cast(relationship), + skipItems, + maxItems + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new BrowseCatalogResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^>^ +CatalogService::GetCatalogItemDetailsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ productIds + ) +{ + auto task = m_cppObj.get_catalog_item_details( + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(productIds) + ) + .then([](xbox_live_result> cppResult) + { + THROW_IF_ERR(cppResult); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(cppResult.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogService_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogService_WinRT.h new file mode 100644 index 00000000..d43be6df --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogService_WinRT.h @@ -0,0 +1,86 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" +#include "CatalogItemDetails_WinRT.h" +#include "CatalogSortOrder_WinRT.h" +#include "BrowseCatalogResult_WinRT.h" +#include "MediaItemType_WinRT.h" +#include "BundleRelationshipType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class CatalogService sealed +{ +public: + + /// + /// Browse for catalog items from within a single media group. + /// + /// The product ID of the parent product + /// The media type of the parent + /// The media type of the child + /// Controls how the list is ordered + /// The number of items to skip + /// The maximum number of items the result can contain. Pass 0 to attempt retrieve as many items as possible. + /// BrowseCatalogResult object containing the items + /// Calls V3.2 GET /media/{marketplaceId}/browse + Windows::Foundation::IAsyncOperation^ + BrowseCatalogAsync( + _In_ Platform::String^ parentId, + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType parentMediaType, + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType childMediaType, + _In_ CatalogSortOrder orderBy, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ); + + /// + /// Browse the catalog related to bundles an item is a member of or included items of a bundle + /// + /// The product ID of the parent product + /// The media type of the parent + /// The ID of the product we are browsing the relationship for + /// The relationship to be used in the browse call either included products in a bundle, or bundles the product is a member of + /// The number of items to skip + /// The maximum number of items the result can contain. Pass 0 to attempt retrieve as many items as possible. + /// BrowseCatalogResult object containing the items + /// Calls V3.2 GET /media/{marketplaceId}/browse + Windows::Foundation::IAsyncOperation^ + BrowseCatalogBundlesAsync( + _In_ Platform::String^ parentId, + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType parentMediaType, + _In_ Platform::String^ productId, + _In_ BundleRelationshipType relationship, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ); + + /// + /// Get the product details for a set of ProductIDs + /// + /// A collection of product IDs to get item details for. A maximum of ten strings may be passed per call to this method. + /// A collection of CatalogItems + /// Calls V3.2 GET /media/{marketplaceId}/details + Windows::Foundation::IAsyncOperation^>^ + GetCatalogItemDetailsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ productIds + ); + +internal: + CatalogService::CatalogService( + _In_ xbox::services::marketplace::catalog_service cppObj + ); + +private: + xbox::services::marketplace::catalog_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/CatalogSortOrder_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogSortOrder_WinRT.h new file mode 100644 index 00000000..5a262f81 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogSortOrder_WinRT.h @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public enum class CatalogSortOrder +{ + /// + /// Sort by count of free and paid purchases, for the most recent day + /// + FreeAndPaidCountDaily = xbox::services::marketplace::catalog_sort_order::free_and_paid_count_daily, + + /// + /// Sort by count of only paid purchases, for all time. + /// + PaidCountAllTime = xbox::services::marketplace::catalog_sort_order::paid_count_all_time, + + /// + /// Sort by count of only paid purchases, for the most recent day. + /// + PaidCountDaily = xbox::services::marketplace::catalog_sort_order::paid_count_daily, + + /// + /// Sort by date available for download + /// + DigitalReleaseDate = xbox::services::marketplace::catalog_sort_order::digital_release_date, + + /// + /// Sort by date available in stores, falling back to digital release date (if available) + /// + ReleaseDate = xbox::services::marketplace::catalog_sort_order::release_date, + + /// + /// Sort by average user ratings + /// + UserRatings = xbox::services::marketplace::catalog_sort_order::user_ratings +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.cpp b/Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.cpp new file mode 100644 index 00000000..d3573f6a --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.cpp @@ -0,0 +1,23 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "CatalogTotal_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +CatalogTotal::CatalogTotal( + _In_ xbox::services::marketplace::catalog_total cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.h b/Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.h new file mode 100644 index 00000000..2f7a7df4 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/CatalogTotal_WinRT.h @@ -0,0 +1,31 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" +#include "CatalogTotal_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +private ref class CatalogTotal sealed +{ +public: + DEFINE_PROP_GET_OBJ(Total, total, uint32); + +internal: + CatalogTotal( + _In_ xbox::services::marketplace::catalog_total cppObj + ); + +private: + xbox::services::marketplace::catalog_total m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END + diff --git a/Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.cpp b/Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.cpp new file mode 100644 index 00000000..c14de66b --- /dev/null +++ b/Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.cpp @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ConsumeInventoryItemResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +ConsumeInventoryItemResult::ConsumeInventoryItemResult( + _In_ xbox::services::marketplace::consume_inventory_item_result cppObj + ): + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.h b/Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.h new file mode 100644 index 00000000..5139ebab --- /dev/null +++ b/Source/Services/Marketplace/WinRT/ConsumeInventoryItemResult_WinRT.h @@ -0,0 +1,42 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class ConsumeInventoryItemResult sealed +{ +public: + /// + /// The consumable item Url of the item that was consumed + /// + DEFINE_PROP_GET_URI_OBJ(ConsumableUrl, consumable_url); + + /// + /// The new balance for the consumable item. + /// + DEFINE_PROP_GET_OBJ(ConsumableBalance, consumable_balance, uint32); + + /// + /// The transaction Id that serves to acknowledge receipt of a specific request + /// + DEFINE_PROP_GET_STR_OBJ(TransactionId, transaction_id); + +internal: + ConsumeInventoryItemResult( + _In_ xbox::services::marketplace::consume_inventory_item_result cppObj + ); + +private: + xbox::services::marketplace::consume_inventory_item_result m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/InventoryItemAvailability_WinRT.h b/Source/Services/Marketplace/WinRT/InventoryItemAvailability_WinRT.h new file mode 100644 index 00000000..d3a3a748 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryItemAvailability_WinRT.h @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +/// Enumeration values that indicate the current availability inventory items +public enum class InventoryItemAvailability +{ + /// + /// All items should be returned regardless of availability. + /// + All = xbox::services::marketplace::inventory_item_availability::all, + + /// + /// Item is available. The current date falls between the start and end date of the item. + /// + Available = xbox::services::marketplace::inventory_item_availability::available, + + /// + /// Item is unavailable. The current date falls outside the start and end date of the item. + /// + Unavailable = xbox::services::marketplace::inventory_item_availability::unavailable +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/InventoryItemState_WinRT.h b/Source/Services/Marketplace/WinRT/InventoryItemState_WinRT.h new file mode 100644 index 00000000..ceeb5143 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryItemState_WinRT.h @@ -0,0 +1,36 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +/// Enumeration values that indicate the inventory item state +public enum class InventoryItemState +{ + /// Unknown item state. + Unknown = xbox::services::marketplace::inventory_item_state::unknown, + + /// All is used to request inventory items for all states. + All = xbox::services::marketplace::inventory_item_state::all, + + /// Enabled item state. + Enabled = xbox::services::marketplace::inventory_item_state::enabled, + + /// Suspended item state. + Suspended = xbox::services::marketplace::inventory_item_state::suspended, + + /// Expired item state. + Expired = xbox::services::marketplace::inventory_item_state::expired, + + /// Canceled item state. This state pertains to subscriptions that have been canceled. + Canceled = xbox::services::marketplace::inventory_item_state::canceled +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/InventoryItem_WinRT.cpp b/Source/Services/Marketplace/WinRT/InventoryItem_WinRT.cpp new file mode 100644 index 00000000..c8b35f0e --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryItem_WinRT.cpp @@ -0,0 +1,42 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "InventoryItem_WinRT.h" + +using namespace Microsoft::Xbox::Services::Marketplace; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +InventoryItem::InventoryItem( + _In_ xbox::services::marketplace::inventory_item cppObj + ): + m_cppObj(std::move(cppObj)) +{ + m_containerIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.container_ids())->GetView(); +} + +IVectorView^ +InventoryItem::ContainerIds::get() +{ + return m_containerIds; +} + +xbox::services::marketplace::inventory_item +InventoryItem::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/InventoryItem_WinRT.h b/Source/Services/Marketplace/WinRT/InventoryItem_WinRT.h new file mode 100644 index 00000000..d46bb398 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryItem_WinRT.h @@ -0,0 +1,100 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/marketplace.h" +#include "InventoryItemState_WinRT.h" +#include "MediaItemType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class InventoryItem sealed +{ +public: + /// + /// The inventory item Url + /// + DEFINE_PROP_GET_URI_OBJ(Url, url); + + /// + /// The state of the inventory item. + /// + DEFINE_PROP_GET_ENUM_OBJ(InventoryItemState, item_state, Microsoft::Xbox::Services::Marketplace::InventoryItemState); + + /// + /// The media item type of the inventory item. + /// + DEFINE_PROP_GET_ENUM_OBJ(MediaItemType, item_type, Microsoft::Xbox::Services::Marketplace::MediaItemType); + + /// + /// The unique identifier of the product that this item represents. + /// + DEFINE_PROP_GET_STR_OBJ(ProductId, product_id); + + /// + /// The title Id that a durable item is associated with or null for consumable and subscription items. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The list of container Ids that contain this item + /// + property Windows::Foundation::Collections::IVectorView^ ContainerIds + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The date when the rights to the item were obtained. + /// + DEFINE_PROP_GET_DATETIME_OBJ(RightsObtainedDate, rights_obtained_date); + + /// + /// The start date when the item became available for use. + /// + DEFINE_PROP_GET_DATETIME_OBJ(StartDate, start_date); + + /// + /// The end date when the item became or will become unusable. + /// + DEFINE_PROP_GET_DATETIME_OBJ(EndDate, end_date); + + /// + /// The consumable item Url or null for non-consumable inventory items. + /// + DEFINE_PROP_GET_URI_OBJ(ConsumableUrl, consumable_url); + + /// + /// The balance of the consumable inventory item at the time the request was received. For non-consumable items, the quantity will be 0. + /// + DEFINE_PROP_GET_OBJ(ConsumableBalance, consumable_balance, uint32); + + /// + /// True if this entitlement is a trial; otherwise, false. If you buy the trial version of an entitlement and then buy the full version, you will receive both + /// + DEFINE_PROP_GET_OBJ(IsTrialEntitlement, is_trial_entitlement, bool); + + /// + /// How much time is remaining on the trial. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(TrialTimeRemaining, trial_time_remaining); + +internal: + InventoryItem( + _In_ xbox::services::marketplace::inventory_item cppObj + ); + xbox::services::marketplace::inventory_item GetCppObj() const; + +private: + xbox::services::marketplace::inventory_item m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_containerIds; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.cpp b/Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.cpp new file mode 100644 index 00000000..410b2c16 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.cpp @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "InventoryItem_WinRT.h" +#include "InventoryItemsResult_WinRT.h" + +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::marketplace; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +InventoryItemsResult::InventoryItemsResult( + _In_ xbox::services::marketplace::inventory_items_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_items = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.items())->GetView(); +} + +IVectorView^ +InventoryItemsResult::Items::get() +{ + return m_items; +} + +IAsyncOperation^ +InventoryItemsResult::GetNextAsync( + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox::services::xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.h b/Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.h new file mode 100644 index 00000000..01600c77 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryItemsResult_WinRT.h @@ -0,0 +1,59 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/marketplace.h" +#include "InventoryItem_WinRT.h" +#include "InventoryItemAvailability_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class InventoryItemsResult sealed +{ +public: + /// + /// Collection of InventoryItem objects returned by a request + /// + property Windows::Foundation::Collections::IVectorView^ Items + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The total number of inventory items that matched the request. + /// + DEFINE_PROP_GET_OBJ(TotalItems, total_items, uint32); + + /// + /// Returns an InventoryResult object containing the next page of InventoryItems + /// + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// InventoryResult object containing the next page of InventoryItem objects. + /// Calls V2 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetNextAsync( + _In_ uint32 maxItems + ); + + /// + /// Indicates if there is additional data to retrieve from a GetNextAsync call + /// + DEFINE_PROP_GET_OBJ(HasNext, has_next, bool); + +internal: + InventoryItemsResult( + _In_ xbox::services::marketplace::inventory_items_result cppObj + ); + +private: + xbox::services::marketplace::inventory_items_result m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_items; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/WinRT/InventoryService_WinRT.cpp b/Source/Services/Marketplace/WinRT/InventoryService_WinRT.cpp new file mode 100644 index 00000000..c981e186 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryService_WinRT.cpp @@ -0,0 +1,294 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "InventoryService_WinRT.h" +#include "utils_winrt.h" + +using namespace Concurrency; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::Marketplace; +using namespace Microsoft::Xbox::Services::System; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::marketplace; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +const wchar_t c_inventoryContractVersionHeaderValue[] = L"4"; + +InventoryService::InventoryService( + _In_ xbox::services::marketplace::inventory_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +IAsyncOperation^ +InventoryService::GetInventoryItemsAsync( + _In_ MediaItemType mediaItemType + ) +{ + auto task = m_cppObj.get_inventory_items( + static_cast(mediaItemType) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +InventoryService::GetInventoryItemsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ productIds, + _In_ bool expandSatisfyingEntitlements + ) +{ + auto task = m_cppObj.get_inventory_items( + UtilsWinRT::CovertVectorViewToStdVectorString(productIds), + expandSatisfyingEntitlements + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +InventoryService::GetInventoryItemsAsync( + _In_ MediaItemType mediaItemType, + _In_ bool expandSatisfyingEntitlements, + _In_ bool includeAllItemStatesAndAvailabilities + ) +{ + auto task = m_cppObj.get_inventory_items( + static_cast(mediaItemType), + expandSatisfyingEntitlements, + includeAllItemStatesAndAvailabilities + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +InventoryService::GetInventoryItemsAsync( + _In_ MediaItemType mediaItemType, + _In_ InventoryItemState inventoryItemState, + _In_ InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_inventory_items( + static_cast(mediaItemType), + static_cast(inventoryItemState), + static_cast(inventoryItemAvailability), + STRING_T_FROM_PLATFORM_STRING(inventoryItemContainerId), + maxItems + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +InventoryService::GetInventoryItemsAsync( + _In_ MediaItemType mediaItemType, + _In_ InventoryItemState inventoryItemState, + _In_ InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems, + _In_ bool expandSatisfyingEntitlements + ) +{ + auto task = m_cppObj.get_inventory_items( + static_cast(mediaItemType), + static_cast(inventoryItemState), + static_cast(inventoryItemAvailability), + STRING_T_FROM_PLATFORM_STRING(inventoryItemContainerId), + maxItems, + expandSatisfyingEntitlements + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +InventoryService::GetInventoryItemsForAllUsersAsync( + _In_ MediaItemType mediaItemType + ) +{ + auto task = m_cppObj.get_inventory_items_for_all_users( + static_cast(mediaItemType) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +InventoryService::GetInventoryItemsForAllUsersAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ bool expandSatisfyingEntitlements, + _In_ bool includeAllItemStatesAndAvailabilities + ) +{ + auto task = m_cppObj.get_inventory_items_for_all_users( + static_cast(mediaItemType), + expandSatisfyingEntitlements, + includeAllItemStatesAndAvailabilities + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +InventoryService::GetInventoryItemsForAllUsersAsync( + _In_ Windows::Foundation::Collections::IVectorView^ productIds, + _In_ bool expandSatisfyingEntitlements + ) +{ + auto task = m_cppObj.get_inventory_items_for_all_users( + UtilsWinRT::CovertVectorViewToStdVectorString(productIds), + expandSatisfyingEntitlements + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +InventoryService::GetInventoryItemsForAllUsersAsync( + _In_ MediaItemType mediaItemType, + _In_ InventoryItemState inventoryItemState, + _In_ InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_inventory_items_for_all_users( + static_cast(mediaItemType), + static_cast(inventoryItemState), + static_cast(inventoryItemAvailability), + STRING_T_FROM_PLATFORM_STRING(inventoryItemContainerId), + maxItems + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +InventoryService::GetInventoryItemsForAllUsersAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemState inventoryItemState, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems, + _In_ bool expandSatisfyingEntitlements + ) +{ + auto task = m_cppObj.get_inventory_items_for_all_users( + static_cast(mediaItemType), + static_cast(inventoryItemState), + static_cast(inventoryItemAvailability), + STRING_T_FROM_PLATFORM_STRING(inventoryItemContainerId), + maxItems, + expandSatisfyingEntitlements + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItemsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +InventoryService::GetInventoryItemAsync( + _In_ InventoryItem^ inventoryItem + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(inventoryItem); + + auto task = m_cppObj.get_inventory_item( + inventoryItem->GetCppObj() + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new InventoryItem(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +InventoryService::ConsumeInventoryItemAsync( + _In_ InventoryItem^ inventoryItem, + _In_ uint32 quantityToConsume, + _In_ Platform::String^ transactionId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(inventoryItem); + + auto task = m_cppObj.consume_inventory_item( + inventoryItem->GetCppObj(), + quantityToConsume, + STRING_T_FROM_PLATFORM_STRING(transactionId) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new ConsumeInventoryItemResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/InventoryService_WinRT.h b/Source/Services/Marketplace/WinRT/InventoryService_WinRT.h new file mode 100644 index 00000000..82dacc5f --- /dev/null +++ b/Source/Services/Marketplace/WinRT/InventoryService_WinRT.h @@ -0,0 +1,220 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/marketplace.h" +#include "ConsumeInventoryItemResult_WinRT.h" +#include "InventoryItem_WinRT.h" +#include "InventoryItemAvailability_WinRT.h" +#include "InventoryItemsResult_WinRT.h" +#include "InventoryItemState_WinRT.h" +#include "MediaItemType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +public ref class InventoryService sealed +{ +public: + + /// + /// Enumerate user's inventory for all available items of the specified type that are in the enabled state. + /// + /// The media item type to enumerate + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType + ); + + /// + /// Get the inventory results for a set of ProductIDs for the current user + /// + /// A collection of IDs to query the inventory for + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// InventoryItemsResult object containing the inventoryItems + /// + /// It is recommended that you limit your ProductIds requested per list to a maximum of 100. + /// + /// Calls V4 GET /users/me/inventory + /// + Windows::Foundation::IAsyncOperation^ GetInventoryItemsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ productIds, + _In_ bool expandSatisfyingEntitlements + ); + + /// + /// Enumerate user's inventory with filter options to include satisfying entitlements and pre-order or unavailable items. + /// + /// The media item type to enumerate + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// Include results of pre-orders and now-unavailable products the user owns + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ bool expandSatisfyingEntitlements, + _In_ bool includeAllItemStatesAndAvailabilities + ); + + /// + /// Enumerate a user's inventory + /// + /// The media item type to enumerate + /// The state of the inventory items to include in the result + /// The availability of the inventory items to include in the result + /// The container Id of the inventory items to include in the result (Optional) + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemState inventoryItemState, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems + ); + + /// + /// Enumerate a user's inventory with filter options to include satisfying entitlements + /// + /// The media item type to enumerate + /// The state of the inventory items to include in the result + /// The availability of the inventory items to include in the result + /// The container Id of the inventory items to include in the result (Optional) + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemState inventoryItemState, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems, + _In_ bool expandSatisfyingEntitlements + ); + + /// + /// Enumerate inventory for all signed-in users for all available items of the specified type that are in the enabled state. + /// + /// The media item type to enumerate + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsForAllUsersAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType + ); + + /// + /// Enumerate inventory for all signed-in users with filter options to include satisfying entitlements and pre-order or unavailable items. + /// + /// The media item type to enumerate + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// Include results of pre-orders and now-unavailable products the user owns + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsForAllUsersAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ bool expandSatisfyingEntitlements, + _In_ bool includeAllItemStatesAndAvailabilities + ); + + /// + /// Enumerate inventory for all signed-in users + /// + /// The media item type to enumerate + /// The state of the inventory items to include in the result + /// The availability of the inventory items to include in the result + /// The container Id of the inventory items to include in the result (Optional) + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsForAllUsersAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemState inventoryItemState, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems + ); + + /// + /// Enumerate inventory for all signed-in users + /// + /// The media item type to enumerate + /// The state of the inventory items to include in the result + /// The availability of the inventory items to include in the result + /// The container Id of the inventory items to include in the result (Optional) + /// The maximum number of items the result can contain. Pass 0 to attempt + /// retrieving all items. + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// InventoryItemsResult object containing the inventoryItems + /// Calls V4 GET /users/me/inventory + Windows::Foundation::IAsyncOperation^ GetInventoryItemsForAllUsersAsync( + _In_ Microsoft::Xbox::Services::Marketplace::MediaItemType mediaItemType, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemState inventoryItemState, + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItemAvailability inventoryItemAvailability, + _In_opt_ Platform::String^ inventoryItemContainerId, + _In_ uint32 maxItems, + _In_ bool expandSatisfyingEntitlements + ); + + /// + /// Get the inventory results for a set of ProductIDs for the current user + /// + /// A collection of IDs to query the inventory for + /// Include all satisfying entitlements from bundles, Xbox 360 entitlements, etc. in the results + /// InventoryItemsResult object containing the inventoryItems + /// + /// It is recommended that you limit your ProductIds requested per list to a maximum of 100. + /// + /// Calls V4 GET /users/me/inventory + /// + Windows::Foundation::IAsyncOperation^ GetInventoryItemsForAllUsersAsync( + _In_ Windows::Foundation::Collections::IVectorView^ productIds, + _In_ bool expandSatisfyingEntitlements + ); + + /// + /// Gets a single inventory item for the specified Id + /// + /// The InventoryItem to get an update for. + /// The requested InventoryItem object + /// Calls V4 GET /users/me/inventory/{inventoryItemId} + Windows::Foundation::IAsyncOperation^ GetInventoryItemAsync( + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItem^ inventoryItem + ); + + /// + /// Consumes the specified quantity of a consumable inventory item. + /// + /// The InventoryItem to consume quantity from. + /// The quantity to consume of the specified InventoryItem. + /// A client generated unique Id for the transaction. + /// Transactions with the same Id will only be processed once. + /// A ConsumeInventoryItemResult object. + /// Calls V4 POST /users/me/consumables/{consumableId} + Windows::Foundation::IAsyncOperation^ ConsumeInventoryItemAsync( + _In_ Microsoft::Xbox::Services::Marketplace::InventoryItem^ inventoryItem, + _In_ uint32 quantityToConsume, + _In_ Platform::String^ transactionId + ); + +internal: + InventoryService( + _In_ xbox::services::marketplace::inventory_service cppObj + ); + +private: + xbox::services::marketplace::inventory_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END \ No newline at end of file diff --git a/Source/Services/Marketplace/WinRT/MediaItemType_WinRT.h b/Source/Services/Marketplace/WinRT/MediaItemType_WinRT.h new file mode 100644 index 00000000..3e2e0585 --- /dev/null +++ b/Source/Services/Marketplace/WinRT/MediaItemType_WinRT.h @@ -0,0 +1,63 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_BEGIN + +/// Enumeration values that indicate the media item type +public enum class MediaItemType +{ + /// Unknown media type. + Unknown = xbox::services::marketplace::media_item_type::unknown, + + /// Game media type. + Game = xbox::services::marketplace::media_item_type::game, + + /// GameV2 media type. + GameV2 = xbox::services::marketplace::media_item_type::game_v2, + + /// Application media type. + Application = xbox::services::marketplace::media_item_type::application, + + /// Game content media type. + GameContent = xbox::services::marketplace::media_item_type::game_content, + + /// Game consumable media type. + GameConsumable = xbox::services::marketplace::media_item_type::game_consumable, + + /// Subscription media type. + Subscription = xbox::services::marketplace::media_item_type::subscription, + + /// Movie media type. + Movie = xbox::services::marketplace::media_item_type::movie, + + /// Television Show media type. + TelevisionShow = xbox::services::marketplace::media_item_type::television_show, + + /// Television Series media type. + TelevisionSeries = xbox::services::marketplace::media_item_type::television_series, + + /// Television Season media type. + TelevisionSeason = xbox::services::marketplace::media_item_type::television_season, + + /// Service detects if media type is an application or a game. + ApplicationOrGameUnknown = xbox::services::marketplace::media_item_type::application_or_game_unknown, + + /// Game demo media type. + GameDemo = xbox::services::marketplace::media_item_type::game_demo, + + /// WebVideo media type. + WebVideo = xbox::services::marketplace::media_item_type::web_video, + + /// Request All media types for inventory calls. + All = xbox::services::marketplace::media_item_type::all +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_END diff --git a/Source/Services/Marketplace/browse_catalog_result.cpp b/Source/Services/Marketplace/browse_catalog_result.cpp new file mode 100644 index 00000000..e42ed818 --- /dev/null +++ b/Source/Services/Marketplace/browse_catalog_result.cpp @@ -0,0 +1,164 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +const wchar_t c_browseCatalogContractVersionHeaderValue[] = L"3.2"; + +browse_catalog_result::browse_catalog_result() : + m_parentMediaItemType(media_item_type::unknown), + m_childMediaItemType(media_item_type::unknown), + m_orderBy(catalog_sort_order::digital_release_date), + m_skipItems(0), + m_bundleRelationship(bundle_relationship_type::unknown), + m_totalCount(0), + m_isBundleRelated(false) +{ +} + +browse_catalog_result::browse_catalog_result( + _In_ string_t parentId, + _In_ media_item_type parentMediaItemType, + _In_ media_item_type childMediaItemType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems, + _In_ string_t productId, + _In_ bundle_relationship_type bundleRelationship, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::vector items, + _In_ uint32_t totalCount, + _In_ string_t continuationToken, + _In_ bool m_isBundleRelated + ) : + m_parentId(std::move(parentId)), + m_parentMediaItemType(parentMediaItemType), + m_childMediaItemType(childMediaItemType), + m_orderBy(orderBy), + m_skipItems(skipItems), + m_productId(std::move(productId)), + m_bundleRelationship(bundleRelationship), + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_items(std::move(items)), + m_totalCount(totalCount), + m_continuationToken(std::move(continuationToken)), + m_isBundleRelated(m_isBundleRelated) +{ +} + +const std::vector& browse_catalog_result::items() const +{ + return m_items; +} + +uint32_t browse_catalog_result::total_count() const +{ + return m_totalCount; +} + +bool +browse_catalog_result::has_next() const +{ + return m_skipItems < m_totalCount; +} + +xbox_live_result +browse_catalog_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + browse_catalog_result result; + result.m_items = utils::extract_json_vector(catalog_item::_Deserialize, json, _T("Items"), errc, true); + + std::vector catalogTotals = utils::extract_json_vector( + catalog_total::_Deserialize, + json, + _T("Totals"), + errc, + false + ); + + for (auto& catalogTotal : catalogTotals) + { + result.m_totalCount = result.m_totalCount > catalogTotal.total() ? result.m_totalCount : catalogTotal.total(); + } + + return xbox_live_result(result); +} + +void browse_catalog_result::_Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ string_t parentId, + _In_ media_item_type parentMediaType, + _In_ media_item_type childItemType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems + ) +{ + m_userContext = std::move(userContext); + m_xboxLiveContextSettings = std::move(xboxLiveContextSettings); + m_parentId = std::move(parentId); + m_parentMediaItemType = parentMediaType; + m_childMediaItemType = childItemType; + m_orderBy = orderBy; + m_skipItems = skipItems; +} + +void browse_catalog_result::_Set_browse_bundles( + _In_ string_t productId, + _In_ bundle_relationship_type relationship + ) +{ + m_productId = std::move(productId); + m_bundleRelationship = relationship; + m_isBundleRelated = true; +} + +pplx::task> +browse_catalog_result::get_next( + _In_ uint32_t maxItems + ) +{ + catalog_service service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + + // Is this a bundle related call or a standard BrowseCall? + if (m_isBundleRelated) + { + return service.browse_catalog_bundles( + m_parentId, + m_parentMediaItemType, + m_productId, + m_bundleRelationship, + m_skipItems, + maxItems + ); + } + + // Standard Browse Call + return service.browse_catalog( + m_parentId, + m_parentMediaItemType, + m_childMediaItemType, + m_orderBy, + m_skipItems, + maxItems + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/catalog_item.cpp b/Source/Services/Marketplace/catalog_item.cpp new file mode 100644 index 00000000..58b11cf2 --- /dev/null +++ b/Source/Services/Marketplace/catalog_item.cpp @@ -0,0 +1,156 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +catalog_item::catalog_item() +{ +} + +catalog_item::catalog_item( + _In_ string_t id, + _In_ string_t name, + _In_ string_t reducedName, + _In_ uint32_t titleId, + _In_ utility::datetime releaseDate, + _In_ string_t productId, + _In_ string_t sandboxId, + _In_ bool isBundle, + _In_ bool isPartOfAnyBundle, + _In_ std::vector images, + _In_ std::vector availabilityContentIds, + _In_ media_item_type mediaItemType + ) : + m_id(std::move(id)), + m_name(std::move(name)), + m_reducedName(std::move(reducedName)), + m_titleId(titleId), + m_releaseDate(std::move(releaseDate)), + m_productId(std::move(productId)), + m_sandboxId(std::move(sandboxId)), + m_isBundle(isBundle), + m_isPartOfAnyBundle(isPartOfAnyBundle), + m_images(std::move(images)), + m_availabilityContentIds(std::move(availabilityContentIds)), + m_mediaItemType(mediaItemType) +{ +} + +media_item_type catalog_item::item_type() const +{ + return m_mediaItemType; +} + +const string_t& catalog_item::id() const +{ + return m_id; +} + +const string_t& catalog_item::name() const +{ + return m_name; +} + +const string_t& catalog_item::reduced_name() const +{ + return m_reducedName; +} + +uint32_t catalog_item::title_id() const +{ + return m_titleId; +} + +const utility::datetime& catalog_item::release_date() const +{ + return m_releaseDate; +} + +const string_t& catalog_item::product_id() const +{ + return m_productId; +} + +const string_t& catalog_item::sandbox_id() const +{ + return m_sandboxId; +} + +bool catalog_item::is_bundle() const +{ + return m_isBundle; +} + +bool catalog_item::is_part_of_any_bundle() const +{ + return m_isPartOfAnyBundle; +} + +const std::vector& catalog_item::images() const +{ + return m_images; +} + +const std::vector& catalog_item::availability_content_ids() const +{ + return m_availabilityContentIds; +} + +xbox_live_result +catalog_item::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + // Turn this into a collection of content ID strings: + // + // "Availabilities": + // [ + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116d", + // }, + // { + // "ContentId":"562acf0f-2021-42d8-b158-f3493214116e", + // } + // ], + + std::error_code errc; + std::vector availabilities = utils::extract_json_vector(catalog_item_availability::_Deserialize, json, _T("Availabilities"), errc, true); + std::vector availabilityContentIds; + for (uint32_t i = 0; i < availabilities.size(); ++i) + { + if (!availabilities.at(i).content_id().empty()) + { + availabilityContentIds.push_back(availabilities.at(i).content_id()); + } + } + + auto catalogItemResult = catalog_item( + utils::extract_json_string(json, _T("ID"), errc, true), + utils::extract_json_string(json, _T("Name"), errc, true), + utils::extract_json_string(json, _T("ReducedName"), errc, false), + utils::extract_json_int(json, _T("TitleId"), errc, false), + utils::extract_json_time(json, _T("ReleaseDate"), errc, false), + utils::extract_json_string(json, _T("ID"), errc, true), //ProductId has been deprecated, use ID instead. + utils::extract_json_string(json, _T("SandboxId"), errc, false), + utils::extract_json_bool(json, _T("IsBundle"), errc, false), + utils::extract_json_bool(json, _T("IsPartOfAnyBundle"), errc, false), + utils::extract_json_vector(catalog_item_image::_Deserialize, json, _T("Images"), errc, false), + std::move(availabilityContentIds), + catalog_service::_Convert_string_to_media_item_type(utils::extract_json_string(json, _T("MediaItemType"), errc, true)) + ); + + return xbox_live_result(catalogItemResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/catalog_item_availability.cpp b/Source/Services/Marketplace/catalog_item_availability.cpp new file mode 100644 index 00000000..871388b5 --- /dev/null +++ b/Source/Services/Marketplace/catalog_item_availability.cpp @@ -0,0 +1,195 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +catalog_item_availability::catalog_item_availability() : + m_isPurchasable(false), + m_listPrice(0), + m_price(0), + m_consumableQuantity(0) +{ +} + +catalog_item_availability::catalog_item_availability( + _In_ string_t contentId, + _In_ string_t signedOffer + ) : + m_contentId(std::move(contentId)), + m_signedOffer(std::move(signedOffer)), + m_isPurchasable(false), + m_listPrice(0), + m_price(0), + m_consumableQuantity(0) +{ +} + +catalog_item_availability::catalog_item_availability( + _In_ string_t contentId, + _In_ std::vector acceptablePaymentInstrumentTypes, + _In_ string_t availabilityTitle, + _In_ string_t availabilityDescription, + _In_ string_t currencyCode, + _In_ string_t displayPrice, + _In_ string_t displayListPrice, + _In_ string_t distributionType, + _In_ bool isPurchasable, + _In_ double listPrice, + _In_ double price, + _In_ uint32_t consumableQuantity, + _In_ string_t promotionalText, + _In_ string_t signedOffer, + _In_ string_t offerId, + _In_ string_t offerDisplayDataJson + ) : + m_contentId(std::move(contentId)), + m_acceptablePaymentInstrumentTypes(std::move(acceptablePaymentInstrumentTypes)), + m_availabilityTitle(std::move(availabilityTitle)), + m_availabilityDescription(std::move(availabilityDescription)), + m_currencyCode(std::move(currencyCode)), + m_displayPrice(std::move(displayPrice)), + m_displayListPrice(std::move(displayListPrice)), + m_distributionType(std::move(distributionType)), + m_isPurchasable(isPurchasable), + m_listPrice(listPrice), + m_price(price), + m_consumableQuantity(consumableQuantity), + m_promotionalText(std::move(promotionalText)), + m_signedOffer(std::move(signedOffer)), + m_offerId(std::move(offerId)), + m_offerDisplayDataJson(std::move(offerDisplayDataJson)) +{ +} + +const string_t& catalog_item_availability::content_id() const +{ + return m_contentId; +} + +const std::vector& catalog_item_availability::acceptable_payment_Instrument_types() const +{ + return m_acceptablePaymentInstrumentTypes; +} + +const string_t& catalog_item_availability::availability_title() const +{ + return m_availabilityTitle; +} + +const string_t& catalog_item_availability::availability_description() const +{ + return m_availabilityDescription; +} + +const string_t& catalog_item_availability::currency_code() const +{ + return m_currencyCode; +} + +const string_t& catalog_item_availability::display_price() const +{ + return m_displayPrice; +} + +const string_t& catalog_item_availability::display_list_price() const +{ + return m_displayListPrice; +} + +const string_t& catalog_item_availability::distribution_type() const +{ + return m_distributionType; +} + +bool catalog_item_availability::is_purchasable() const +{ + return m_isPurchasable; +} + +double catalog_item_availability::list_price() const +{ + return m_listPrice; +} + +double catalog_item_availability::price() const +{ + return m_price; +} + +uint32_t catalog_item_availability::consumable_quantity() const +{ + return m_consumableQuantity; +} + +const string_t& catalog_item_availability::promotional_text() const +{ + return m_promotionalText; +} + +const string_t& catalog_item_availability::signed_offer() const +{ + return m_signedOffer; +} + +const string_t& catalog_item_availability::offer_id() const +{ + return m_offerId; +} + +const string_t& catalog_item_availability::offer_display_data_json() const +{ + return m_offerDisplayDataJson; +} + +xbox_live_result +catalog_item_availability::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + web::json::value offerDisplayDataJson = utils::extract_json_field(json, _T("OfferDisplayData"), errc, false); + if (!offerDisplayDataJson.is_null()) + { + web::json::value offerDisplayDataJsonObject = utils::json_get_value_from_string(offerDisplayDataJson.as_string()); + + auto result = catalog_item_availability( + utils::extract_json_string(json, _T("ContentId"), true), + utils::extract_json_vector(utils::json_string_extractor, offerDisplayDataJsonObject, _T("acceptablePaymentInstrumentTypes"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("availabilityTitle"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("availabilityDescription"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("currencyCode"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("displayPrice"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("displayListPrice"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("distributionType"), errc, false), + utils::extract_json_bool(offerDisplayDataJsonObject, _T("isPurchasable"), errc, false), + utils::extract_json_double(offerDisplayDataJsonObject, _T("listPrice"), errc, false), + utils::extract_json_double(offerDisplayDataJsonObject, _T("price"), errc, false), + utils::extract_json_int(offerDisplayDataJsonObject, _T("quantity"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("promotionalText"), errc, false), + utils::extract_json_string(json, _T("SignedOffer"), errc, false), + utils::extract_json_string(offerDisplayDataJsonObject, _T("offerId"), errc, true), + offerDisplayDataJsonObject.serialize() + ); + + return xbox_live_result(result, errc); + } + + auto result = catalog_item_availability( + utils::extract_json_string(json, _T("ContentId"), errc, true), + utils::extract_json_string(json, _T("SignedOffer"), errc, false) + ); + + return xbox_live_result(result, errc); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END diff --git a/Source/Services/Marketplace/catalog_item_details.cpp b/Source/Services/Marketplace/catalog_item_details.cpp new file mode 100644 index 00000000..f4bada54 --- /dev/null +++ b/Source/Services/Marketplace/catalog_item_details.cpp @@ -0,0 +1,144 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +catalog_item_details::catalog_item_details() : + m_isBundle(false), + m_isPartOfAnyBundle(false), + m_mediaItemType(media_item_type::unknown) +{ +} + +catalog_item_details::catalog_item_details( + _In_ string_t id, + _In_ string_t name, + _In_ string_t reducedName, + _In_ string_t description, + _In_ uint32_t titleId, + _In_ utility::datetime releaseDate, + _In_ string_t productId, + _In_ string_t sandboxId, + _In_ bool isBundle, + _In_ bool isPartOfAnyBundle, + _In_ std::vector images, + _In_ std::vector availabilities, + _In_ media_item_type mediaItemType + ) : + m_id(std::move(id)), + m_name(std::move(name)), + m_reducedName(std::move(reducedName)), + m_description(std::move(description)), + m_titleId(titleId), + m_releaseDate(std::move(releaseDate)), + m_productId(std::move(productId)), + m_sandboxId(std::move(sandboxId)), + m_isBundle(isBundle), + m_isPartOfAnyBundle(isPartOfAnyBundle), + m_images(std::move(images)), + m_availabilities(std::move(availabilities)), + m_mediaItemType(mediaItemType) +{ +} + +const media_item_type catalog_item_details::item_type() const +{ + return m_mediaItemType; +} + +const string_t& catalog_item_details::id() const +{ + return m_id; +} + +const string_t& catalog_item_details::name() const +{ + return m_name; +} + +const string_t& catalog_item_details::reduced_name() const +{ + return m_reducedName; +} + +const string_t& catalog_item_details::description() const +{ + return m_description; +} + +uint32_t catalog_item_details::title_id() const +{ + return m_titleId; +} + +const utility::datetime& catalog_item_details::release_date() const +{ + return m_releaseDate; +} + +const string_t& catalog_item_details::product_id() const +{ + return m_productId; +} + +const string_t& catalog_item_details::sandbox_id() const +{ + return m_sandboxId; +} + +bool catalog_item_details::is_bundle() const +{ + return m_isBundle; +} + +bool catalog_item_details::is_part_of_any_bundle() const +{ + return m_isPartOfAnyBundle; +} + +const std::vector& catalog_item_details::images() const +{ + return m_images; +} + +const std::vector& catalog_item_details::availabilities() const +{ + return m_availabilities; +} + +xbox_live_result +catalog_item_details::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + catalog_item_details result; + result.m_id = utils::extract_json_string(json, _T("ID"), errc, true); + result.m_name = utils::extract_json_string(json, _T("Name"), errc, true); + result.m_reducedName = utils::extract_json_string(json, _T("ReducedName"), errc, false); + result.m_description = utils::extract_json_string(json, _T("Description"), errc, false); + result.m_titleId = utils::extract_json_int(json, _T("TitleId"), errc, false); + result.m_releaseDate = utils::extract_json_time(json, _T("ReleaseDate"), errc, false); + result.m_productId = utils::extract_json_string(json, _T("ID"), errc, true); //ProductId has been deprecated, use ID instead. + result.m_sandboxId = utils::extract_json_string(json, _T("SandboxId"), errc, false); + result.m_isBundle = utils::extract_json_bool(json, _T("IsBundle"), errc, false); + result.m_isPartOfAnyBundle = utils::extract_json_bool(json, _T("IsPartOfAnyBundle"), errc, false); + result.m_images = utils::extract_json_vector(catalog_item_image::_Deserialize, json, _T("Images"), errc, false); + result.m_availabilities = utils::extract_json_vector(catalog_item_availability::_Deserialize, json, _T("Availabilities"), errc, false); + result.m_mediaItemType = catalog_service::_Convert_string_to_media_item_type(utils::extract_json_string(json, _T("MediaItemType"), errc, true)); + + return xbox_live_result(result, errc); + +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/catalog_item_image.cpp b/Source/Services/Marketplace/catalog_item_image.cpp new file mode 100644 index 00000000..4f44f77c --- /dev/null +++ b/Source/Services/Marketplace/catalog_item_image.cpp @@ -0,0 +1,86 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +catalog_item_image::catalog_item_image() : + m_height(0), + m_width(0) +{ +} + +catalog_item_image::catalog_item_image( + _In_ string_t id, + _In_ web::uri resizeUrl, + _In_ std::vector purposes, + _In_ string_t purpose, + _In_ uint32_t height, + _In_ uint32_t width + ) : + m_id(std::move(id)), + m_resizeUrl(std::move(resizeUrl)), + m_purposes(std::move(purposes)), + m_purpose(std::move(purpose)), + m_height(height), + m_width(width) +{ +} + +const string_t& catalog_item_image::id() const +{ + return m_id; +} + +const web::uri& catalog_item_image::resize_url() const +{ + return m_resizeUrl; +} + +const std::vector& catalog_item_image::purposes() const +{ + return m_purposes; +} + +const string_t& catalog_item_image::purpose() const +{ + return m_purpose; +} + +uint32_t catalog_item_image::height() const +{ + return m_height; +} + +uint32_t catalog_item_image::width() const +{ + return m_width; +} + +xbox_live_result +catalog_item_image::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + catalog_item_image result; + result.m_id = utils::extract_json_string(json, _T("ID"), errc, true); + result.m_resizeUrl = utils::extract_json_string(json, _T("ResizeUrl"), errc, false); + result.m_purpose = utils::extract_json_string(json, _T("Purpose"), errc, false); + result.m_purposes = utils::extract_json_vector(utils::json_string_extractor, json, _T("Purposes"), errc, false); + result.m_height = utils::extract_json_int(json, _T("Height"), errc, true); + result.m_width = utils::extract_json_int(json, _T("Width"), errc, true); + + return xbox_live_result(result, errc); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/catalog_service.cpp b/Source/Services/Marketplace/catalog_service.cpp new file mode 100644 index 00000000..67231e8a --- /dev/null +++ b/Source/Services/Marketplace/catalog_service.cpp @@ -0,0 +1,632 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; +using namespace xbox::services::system; +#if TV_API +using namespace Windows::Storage::Streams; +using namespace Windows::Media::ContentRestrictions; +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +const string_t catalog_service::BROWSE_CATALOG_CONTRACT_HEADER_VALUE = _T("3.2"); + +catalog_service::catalog_service() +{ +} + +catalog_service::catalog_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +xbox_live_result +catalog_service::convert_sort_order_to_string( + _In_ catalog_sort_order type + ) +{ + switch (type) + { + case catalog_sort_order::digital_release_date: + return xbox_live_result(_T("DigitalReleaseDate")); + + case catalog_sort_order::free_and_paid_count_daily: + return xbox_live_result(_T("FreeAndPaidCountDaily")); + + case catalog_sort_order::paid_count_all_time: + return xbox_live_result(_T("PaidCountAllTime")); + + case catalog_sort_order::paid_count_daily: + return xbox_live_result(_T("PaidCountDaily")); + + case catalog_sort_order::release_date: + return xbox_live_result(_T("ReleaseDate")); + + case catalog_sort_order::user_ratings: + return xbox_live_result(_T("UserRatings")); + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Unsupported catalog_sort_order type"); + } +} + +string_t +catalog_service::_Convert_media_item_type_to_string( + _In_ media_item_type itemType + ) +{ + switch (itemType) + { + case media_item_type::game_content: + return _T("DDurable"); + + case media_item_type::game_consumable: + return _T("DConsumable"); + + case media_item_type::subscription: + return _T("Subscription"); + + case media_item_type::application: + return _T("DApp"); + + case media_item_type::game: + return _T("DGame"); + + case media_item_type::movie: + return _T("Movie"); + + case media_item_type::television_show: + return _T("TVShow"); + + case media_item_type::television_series: + return _T("TVSeries"); + + case media_item_type::television_season: + return _T("TVSeason"); + + case media_item_type::application_or_game_unknown: + return _T("AppOrGameUnknown"); + + case media_item_type::game_demo: + return _T("DGameDemo"); + + case media_item_type::web_video: + return _T("WebVideo"); + + default: + throw std::invalid_argument("Unsupported media_item_type type"); + break; + } +} + +media_item_type +catalog_service::_Convert_string_to_media_item_type( + _In_ const string_t& itemType + ) +{ + if (itemType.empty()) + { + return media_item_type::unknown; + } + else if (utils::str_icmp(itemType, _T("DDurable")) == 0) + { + return media_item_type::game_content; + } + else if (utils::str_icmp(itemType, _T("DConsumable")) == 0) + { + return media_item_type::game_consumable; + } + else if (utils::str_icmp(itemType, _T("Subscription")) == 0) + { + return media_item_type::subscription; + } + else if (utils::str_icmp(itemType, _T("DApp")) == 0) + { + return media_item_type::application; + } + else if (utils::str_icmp(itemType, _T("DGame")) == 0) + { + return media_item_type::game; + } + else if (utils::str_icmp(itemType, _T("Movie")) == 0) + { + return media_item_type::movie; + } + else if (utils::str_icmp(itemType, _T("TVShow")) == 0) + { + return media_item_type::television_show; + } + else if (utils::str_icmp(itemType, _T("TVSeries")) == 0) + { + return media_item_type::television_series; + } + else if (utils::str_icmp(itemType, _T("TVSeason")) == 0) + { + return media_item_type::television_season; + } + else if (utils::str_icmp(itemType, _T("AppOrGameUnknown")) == 0) + { + return media_item_type::application_or_game_unknown; + } + else if (utils::str_icmp(itemType, _T("DGameDemo")) == 0) + { + return media_item_type::game_demo; + } + else if (utils::str_icmp(itemType, _T("WebVideo")) == 0) + { + return media_item_type::web_video; + } + + return media_item_type::unknown; +} + +string_t +catalog_service::convert_bundle_relationship_type_to_string( + _In_ bundle_relationship_type type + ) +{ + switch (type) + { + case bundle_relationship_type::bundles_with_product: + return _T("bundledWith"); + + case bundle_relationship_type::products_in_bundle: + return _T("bundledProducts"); + + default: + throw std::invalid_argument("Unsupported bundle_relationship_type type"); + break; + } +} + +pplx::task> +catalog_service::browse_catalog( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ media_item_type childMediaType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(parentId, browse_catalog_result, "parentId was empty"); + +#if TV_API + auto contentRestrictions = ref new RatedContentRestrictions(); + auto asyncOp = contentRestrictions->GetBrowsePolicyAsync(); + + auto userContextShared = m_userContext; + auto httpContextShared = m_xboxLiveContextSettings; + auto appConfigShared = m_appConfig; + return create_task(asyncOp) + .then([userContextShared, httpContextShared, appConfigShared, parentId, parentMediaType, childMediaType, orderBy, skipItems, maxItems](task browsePolicyTask) + { + ContentRestrictionsBrowsePolicy^ browsePolicy; + browsePolicy = browsePolicyTask.get(); + + web::json::value jsonHeader; + jsonHeader[_T("version")] = web::json::value::string(_T("2")); + + web::json::value jsonData; + jsonData[_T("geographicRegion")] = web::json::value::string(browsePolicy->GeographicRegion->Data()); + if (browsePolicy->MaxBrowsableAgeRating != nullptr) + { + jsonData[_T("maxAgeRating")] = web::json::value::string(browsePolicy->MaxBrowsableAgeRating->Value.ToString()->Data()); + }; + if (browsePolicy->PreferredAgeRating != nullptr) + { + jsonData[_T("preferredAgeRating")] = web::json::value::string(browsePolicy->PreferredAgeRating->Value.ToString()->Data()); + } + jsonHeader[_T("data")] = jsonData; + + utf8string utf8String = utility::conversions::utf16_to_utf8(jsonHeader.serialize()); + std::vector input(utf8String.c_str(), utf8String.c_str() + utf8String.size()); + string_t base64ContentRestriction = utility::conversions::to_base64(input); + + return browse_catalog_helper(parentId, parentMediaType, childMediaType, orderBy, skipItems, maxItems, base64ContentRestriction, userContextShared, httpContextShared, appConfigShared); + }); +#else + return browse_catalog_helper(parentId, parentMediaType, childMediaType, orderBy, skipItems, maxItems, string_t(), m_userContext, m_xboxLiveContextSettings, m_appConfig); +#endif +} + +pplx::task> +catalog_service::browse_catalog_bundles( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ const string_t& productId, + _In_ bundle_relationship_type relationship, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(parentId, browse_catalog_result, "parentId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(productId, browse_catalog_result, "productId is empty"); + +#if TV_API + auto contentRestrictions = ref new RatedContentRestrictions(); + auto asyncOp = contentRestrictions->GetBrowsePolicyAsync(); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + return create_task(asyncOp) + .then([parentId, parentMediaType, productId, relationship, skipItems, maxItems, userContext, xboxLiveContextSettings, appConfig](task browsePolicyTask) + { + ContentRestrictionsBrowsePolicy^ browsePolicy; + browsePolicy = browsePolicyTask.get(); + + web::json::value jsonHeader; + jsonHeader[_T("version")] = web::json::value::string(_T("2")); + + web::json::value jsonData; + jsonData[_T("geographicRegion")] = web::json::value::string(browsePolicy->GeographicRegion->Data()); + if (browsePolicy->MaxBrowsableAgeRating != nullptr) + { + jsonData[_T("maxAgeRating")] = web::json::value::string(browsePolicy->MaxBrowsableAgeRating->Value.ToString()->Data()); + }; + if (browsePolicy->PreferredAgeRating != nullptr) + { + jsonData[_T("preferredAgeRating")] = web::json::value::string(browsePolicy->PreferredAgeRating->Value.ToString()->Data()); + } + jsonHeader[_T("data")] = jsonData; + + utf8string utf8String = utility::conversions::utf16_to_utf8(jsonHeader.serialize()); + std::vector input(utf8String.c_str(), utf8String.c_str() + utf8String.size()); + string_t base64ContentRestriction = utility::conversions::to_base64(input); + + return browse_catalog_bundles_helper(parentId, parentMediaType, productId, relationship, skipItems, maxItems, base64ContentRestriction, userContext, xboxLiveContextSettings, appConfig); + }); +#else + return browse_catalog_bundles_helper(parentId, parentMediaType, productId, relationship, skipItems, maxItems, string_t(), m_userContext, m_xboxLiveContextSettings, m_appConfig); +#endif +} + +pplx::task>> +catalog_service::get_catalog_item_details( + _In_ const std::vector& productIds + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(productIds.size() == 0, std::vector, "productIds cannot be empty"); + + string_t subpathAndQuery = marketplace_catalog_details_subpath(productIds); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("eds"), m_appConfig), + std::move(subpathAndQuery), + xbox_live_api::get_catalog_item_details + ); + + httpCall->set_xbox_contract_version_header_value(BROWSE_CATALOG_CONTRACT_HEADER_VALUE); + httpCall->set_custom_header(_T("Accept"), _T("application/json")); + httpCall->set_custom_header(_T("x-xbl-client-type"), _T("Console")); + httpCall->set_custom_header(_T("x-xbl-client-version"), _T("0")); + httpCall->set_custom_header(_T("x-xbl-device-type"), _T("XboxOne")); + + // Need to remove the ContentType for this call + httpCall->set_content_type_header_value(_T("")); + + return httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc; + auto result = utils::extract_json_vector( + catalog_item_details::_Deserialize, + response->response_body_json(), + _T("Items"), + errc, + true + ); + + auto catalogItemResult = xbox_live_result>( + result, + errc + ); + + return utils::generate_xbox_live_result>( + catalogItemResult, + response + ); + }); +} + +string_t catalog_service::marketplace_browse_catalog_subpath( + _In_ const string_t& parentId, + _In_ const string_t& titleType, + _In_ const string_t& desiredMediaItemTypes, + _In_ const string_t& relationship, + _In_ const string_t& orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ) +{ + stringstream_t source; + source << _T("/media/"); +#if TV_API + source << Windows::Xbox::ApplicationModel::Store::Configuration::MarketplaceId->Data(); +#else + source << utils::get_locales(); +#endif + source << _T("/browse"); + + std::vector params; + params.push_back(_T("fields=all")); + + if (!parentId.empty()) + { + stringstream_t param; + param << _T("id="); + param << web::uri::encode_uri(parentId); + params.push_back(param.str()); + } + + if (!titleType.empty()) + { + stringstream_t param; + param << _T("mediaItemType="); + param << web::uri::encode_uri(titleType); + params.push_back(param.str()); + } + + if (!relationship.empty()) + { + stringstream_t param; + param << _T("relationship="); + param << web::uri::encode_uri(relationship); + params.push_back(param.str()); + + // We don't add the 'orderBy' with a bundle relationship browse + } + else + { + // If this is not a bundle relationship call, add the orderBy filter + stringstream_t param; + param << _T("orderBy="); + param << web::uri::encode_uri(orderBy); + params.push_back(param.str()); + } + + if (!desiredMediaItemTypes.empty()) + { + stringstream_t param; + param << _T("desiredMediaItemTypes="); + param << web::uri::encode_uri(desiredMediaItemTypes); + params.push_back(param.str()); + } + + if (maxItems > 0) + { + stringstream_t param; + param << _T("maxItems="); + param << maxItems; + params.push_back(param.str()); + } + + // use skip items value if continuation token is empty + if (skipItems > 0) + { + stringstream_t param; + param << _T("skipItems="); + param << skipItems; + params.push_back(param.str()); + } + + source << utils::get_query_from_params(params); + return source.str(); +} + +string_t +catalog_service::marketplace_catalog_details_subpath( + _In_ const std::vector& productIds + ) +{ + stringstream_t source; + source << _T("/media/"); +#if TV_API + source << Windows::Xbox::ApplicationModel::Store::Configuration::MarketplaceId->Data(); +#else + source << utils::get_locales(); +#endif + source << _T("/details"); + + std::vector params; + params.push_back(_T("fields=all")); + params.push_back(_T("desiredMediaItemTypes=Subscription.DGame.DGameDemo.DDurable.DConsumable.DApp")); + + { + stringstream_t param; + param << _T("ids="); + auto &last = productIds.back(); + for (const string_t& productId : productIds) + { + param << productId; + if (&productId != &last) + { + param << _T("."); + } + } + params.push_back(param.str()); + } + + source << utils::get_query_from_params(params); + return source.str(); +} + +pplx::task> +catalog_service::browse_catalog_bundles_helper( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ const string_t& productId, + _In_ bundle_relationship_type relationship, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ string_t customHeader, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + string_t subpathAndQuery = marketplace_browse_catalog_subpath( + productId, + _Convert_media_item_type_to_string(parentMediaType), + _T("DGame.DDurable.DConsumable.DApp"), // get all related product types in the bundle + convert_bundle_relationship_type_to_string(relationship), + string_t(), // No need to sort on a bundle search + skipItems, + maxItems + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("eds"), appConfig), + std::move(subpathAndQuery), + xbox_live_api::browse_catalog_bundles_helper + ); + + httpCall->set_xbox_contract_version_header_value(BROWSE_CATALOG_CONTRACT_HEADER_VALUE); + httpCall->set_custom_header(_T("Accept"), _T("application/json")); + httpCall->set_custom_header(_T("x-xbl-client-type"), _T("Console")); + httpCall->set_custom_header(_T("x-xbl-client-version"), _T("0")); + httpCall->set_custom_header(_T("x-xbl-device-type"), _T("XboxOne")); + + // Need to remove the ContentType for this call + httpCall->set_content_type_header_value(_T("")); + if( !customHeader.empty() ) + { + httpCall->set_custom_header(_T("x-xbl-contentRestrictions"), customHeader); + } + + return httpCall->get_response_with_auth(userContext, http_call_response_body_type::json_body) + .then([userContext, xboxLiveContextSettings, parentId, parentMediaType, productId, relationship, skipItems](std::shared_ptr response) + { + auto catalogResult = browse_catalog_result::_Deserialize(response->response_body_json()); + auto& result = catalogResult.payload(); + uint32_t itemSize = static_cast(result.items().size()); + if (itemSize > 0) + { + uint32_t continuationSkip = skipItems + itemSize; + + // Initialize the request params for get_next() + result._Initialize( + userContext, + xboxLiveContextSettings, + parentId, + parentMediaType, + media_item_type::unknown, + catalog_sort_order::release_date, //The Bundle Browse Calls do not support the sort by field, so this is just arbitrary + continuationSkip + ); + + //Mark this as a bundle related call to use the correct API on a GetNextAsync call + result._Set_browse_bundles( + productId, + relationship + ); + } + + return utils::generate_xbox_live_result( + browse_catalog_result::_Deserialize(response->response_body_json()), + response + ); + }); +} + +pplx::task> +catalog_service::browse_catalog_helper( + _In_ const string_t& parentId, + _In_ media_item_type parentMediaType, + _In_ media_item_type childMediaType, + _In_ catalog_sort_order orderBy, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ string_t customHeader, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + auto sortOrderResult = convert_sort_order_to_string(orderBy); + + string_t subpathAndQuery = marketplace_browse_catalog_subpath( + parentId, + _Convert_media_item_type_to_string(parentMediaType), + _Convert_media_item_type_to_string(childMediaType), + string_t(), // not a bundle search + sortOrderResult.payload(), + skipItems, + maxItems + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("eds"), appConfig), + std::move(subpathAndQuery), + xbox_live_api::browse_catalog_helper + ); + + httpCall->set_xbox_contract_version_header_value(BROWSE_CATALOG_CONTRACT_HEADER_VALUE); + httpCall->set_custom_header(_T("Accept"), _T("application/json")); + httpCall->set_custom_header(_T("x-xbl-client-type"), _T("Console")); + httpCall->set_custom_header(_T("x-xbl-client-version"), _T("0")); + httpCall->set_custom_header(_T("x-xbl-device-type"), _T("XboxOne")); + + // Need to remove the ContentType for this call + httpCall->set_content_type_header_value(_T("")); + if( !customHeader.empty()) + { + httpCall->set_custom_header(_T("x-xbl-contentRestrictions"), customHeader); + } + + return httpCall->get_response_with_auth(userContext, http_call_response_body_type::json_body) + .then([userContext, xboxLiveContextSettings, parentId, parentMediaType, childMediaType, orderBy, skipItems](std::shared_ptr response) + { + auto catalogResult = browse_catalog_result::_Deserialize(response->response_body_json()); + auto& result = catalogResult.payload(); + uint32_t itemSize = static_cast(result.items().size()); + if (itemSize > 0) + { + uint32_t continuationSkip = skipItems + itemSize; + + // Initialize the request params for get_next() + result._Initialize( + userContext, + xboxLiveContextSettings, + parentId, + parentMediaType, + childMediaType, + orderBy, + continuationSkip + ); + } + + return utils::generate_xbox_live_result( + catalogResult, + response + ); + }); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/catalog_total.cpp b/Source/Services/Marketplace/catalog_total.cpp new file mode 100644 index 00000000..f91646c8 --- /dev/null +++ b/Source/Services/Marketplace/catalog_total.cpp @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +catalog_total::catalog_total() : + m_total(0) +{ +} + +catalog_total::catalog_total( + _In_ uint32_t total + ) : + m_total(total) +{ +} + +uint32_t catalog_total::total() const +{ + return m_total; +} + +xbox_live_result +catalog_total::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + catalog_total result; + result.m_total = utils::extract_json_int(json, _T("Count"), errc, true); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END diff --git a/Source/Services/Marketplace/consume_inventory_item_request.cpp b/Source/Services/Marketplace/consume_inventory_item_request.cpp new file mode 100644 index 00000000..ce1dcc21 --- /dev/null +++ b/Source/Services/Marketplace/consume_inventory_item_request.cpp @@ -0,0 +1,53 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +consume_inventory_item_request::consume_inventory_item_request() +{ +} + +consume_inventory_item_request::consume_inventory_item_request( + _In_ string_t transactionId, + _In_ uint32_t removeQuantity + ) : + m_transactionId(std::move(transactionId)), + m_removeQuantity(removeQuantity) +{ +} + +xbox_live_result +consume_inventory_item_request::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + consume_inventory_item_request result; + result.m_transactionId = utils::extract_json_string(json, _T("TransactionId"), errc, true); + result.m_removeQuantity = utils::extract_json_int(json, _T("RemoveQuantity"), errc, true); + + return result; +} + +web::json::value +consume_inventory_item_request::_Serialize() +{ + web::json::value serializedObject; + serializedObject[_T("RemoveQuantity")] = web::json::value(m_removeQuantity); + serializedObject[_T("TransactionId")] = web::json::value(m_transactionId); + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/consume_inventory_item_result.cpp b/Source/Services/Marketplace/consume_inventory_item_result.cpp new file mode 100644 index 00000000..d019607f --- /dev/null +++ b/Source/Services/Marketplace/consume_inventory_item_result.cpp @@ -0,0 +1,62 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +consume_inventory_item_result::consume_inventory_item_result() : + m_consumableBalance(0) +{ +} + +consume_inventory_item_result::consume_inventory_item_result( + _In_ web::uri consumableUrl, + _In_ uint32_t consumableBalance, + _In_ string_t transactionId + ) : + m_consumableUrl(std::move(consumableUrl)), + m_consumableBalance(consumableBalance), + m_transactionId(std::move(transactionId)) +{ +} + +const web::uri& consume_inventory_item_result::consumable_url() const +{ + return m_consumableUrl; +} + +uint32_t consume_inventory_item_result::consumable_balance() const +{ + return m_consumableBalance; +} + +const string_t& consume_inventory_item_result::transaction_id() const +{ + return m_transactionId; +} + +xbox_live_result +consume_inventory_item_result::_Deserialize( +_In_ const web::json::value& json +) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + consume_inventory_item_result result; + result.m_consumableUrl = utils::extract_json_string(json, _T("url"), errc, true); + result.m_consumableBalance = utils::extract_json_int(json, _T("newQuantity"), errc, true); + result.m_transactionId = utils::extract_json_string(json, _T("transactionId"), errc, true); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/inventory_item.cpp b/Source/Services/Marketplace/inventory_item.cpp new file mode 100644 index 00000000..bfda01da --- /dev/null +++ b/Source/Services/Marketplace/inventory_item.cpp @@ -0,0 +1,209 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +inventory_item::inventory_item() : + m_inventoryItemState(inventory_item_state::unknown), + m_itemType(media_item_type::unknown), + m_consumableBalance(0), + m_titleId(0), + m_isTrialEntitlement(false) +{ +} + +inventory_item::inventory_item( + _In_ web::uri url, + _In_ inventory_item_state inventoryItemState, + _In_ media_item_type mediaItemType, + _In_ string_t productId, + _In_ uint32_t titleId, + _In_ std::vector containerIds, + _In_ utility::datetime rightsObtainedDate, + _In_ utility::datetime startDate, + _In_ utility::datetime endDate, + _In_ web::uri consumableUrl, + _In_ uint32_t consumableBalance, + _In_ bool isTrialEntitlement, + _In_ std::chrono::seconds trialTimeRemaining + ) : + m_url(std::move(url)), + m_inventoryItemState(inventoryItemState), + m_itemType(mediaItemType), + m_productId(std::move(productId)), + m_titleId(titleId), + m_containerIds(std::move(containerIds)), + m_rightsObtainedDate(std::move(rightsObtainedDate)), + m_startDate(std::move(startDate)), + m_endDate(std::move(endDate)), + m_consumableUrl(std::move(consumableUrl)), + m_consumableBalance(consumableBalance), + m_isTrialEntitlement(isTrialEntitlement), + m_trialTimeRemaining(std::move(trialTimeRemaining)) +{ +} + +const web::uri& inventory_item::url() const +{ + return m_url; +} + +inventory_item_state inventory_item::item_state() const +{ + return m_inventoryItemState; +} + +media_item_type inventory_item::item_type() const +{ + return m_itemType; +} + +const string_t& inventory_item::product_id() const +{ + return m_productId; +} + +uint32_t inventory_item::title_id() const +{ + return m_titleId; +} + +const std::vector& inventory_item::container_ids() const +{ + return m_containerIds; +} + +const utility::datetime& inventory_item::rights_obtained_date() const +{ + return m_rightsObtainedDate; +} + +const utility::datetime& inventory_item::start_date() const +{ + return m_startDate; +} + +const utility::datetime& inventory_item::end_date() const +{ + return m_endDate; +} + +const web::uri& inventory_item::consumable_url() const +{ + return m_consumableUrl; +} + +uint32_t inventory_item::consumable_balance() const +{ + return m_consumableBalance; +} + +bool inventory_item::is_trial_entitlement() const +{ + return m_isTrialEntitlement; +} + +const std::chrono::seconds& inventory_item::trial_time_remaining() const +{ + return m_trialTimeRemaining; +} + +xbox_live_result +inventory_item::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + inventory_item result; + result.m_url = utils::extract_json_string(json, _T("url"), errc, true); + result.m_inventoryItemState = convert_string_to_inventory_item_state(utils::extract_json_string(json, _T("state"), errc, true)); + result.m_itemType = convert_string_to_media_item_type(utils::extract_json_string(json, _T("itemType"), errc, true)); + result.m_productId = utils::extract_json_string(json, _T("productId"), errc, true); + result.m_titleId = utils::extract_json_int(json, _T("titleId"), errc, false); + result.m_containerIds = utils::extract_json_vector(utils::json_string_extractor, json, _T("containers"), errc, false); + result.m_rightsObtainedDate = utils::extract_json_time(json, _T("obtained"), errc, true); + result.m_startDate = utils::extract_json_time(json, _T("beginDate"), errc, true); + result.m_endDate = utils::extract_json_time(json, _T("endDate"), errc, true); + result.m_isTrialEntitlement = utils::extract_json_bool(json, _T("trial"), errc, false); + result.m_trialTimeRemaining = utils::extract_json_string_timespan_in_seconds(json, _T("trialTimeRemaining"), errc, false); + + web::json::value consumableJson = utils::extract_json_field(json, _T("consumable"), errc, false); + if (!consumableJson.is_null()) + { + result.m_consumableUrl = utils::extract_json_string(consumableJson, _T("url"), errc, true); + result.m_consumableBalance = utils::extract_json_int(consumableJson, _T("quantity"), errc, true); + } + + return xbox_live_result(result); +} + +inventory_item_state +inventory_item::convert_string_to_inventory_item_state( + _In_ const string_t& itemType + ) +{ + if (itemType.empty()) + { + return inventory_item_state::unknown; + } + else if (utils::str_icmp(itemType, _T("Enabled")) == 0) + { + return inventory_item_state::enabled; + } + else if (utils::str_icmp(itemType, _T("Suspended")) == 0) + { + return inventory_item_state::suspended; + } + else if (utils::str_icmp(itemType, _T("Expired")) == 0) + { + return inventory_item_state::expired; + } + else if (utils::str_icmp(itemType, _T("Canceled")) == 0) + { + return inventory_item_state::canceled; + } + + return inventory_item_state::unknown; +} + +media_item_type +inventory_item::convert_string_to_media_item_type( + _In_ const string_t& itemType + ) +{ + if (itemType.empty()) + { + return media_item_type::unknown; + } + else if (utils::str_icmp(itemType, _T("GameV2")) == 0) + { + return media_item_type::game_v2; + } + else if (utils::str_icmp(itemType, _T("GameContent")) == 0) + { + return media_item_type::game_content; + } + else if (utils::str_icmp(itemType, _T("GameConsumable")) == 0) + { + return media_item_type::game_consumable; + } + else if (utils::str_icmp(itemType, _T("Subscription")) == 0) + { + return media_item_type::subscription; + } + + return media_item_type::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/inventory_items_result.cpp b/Source/Services/Marketplace/inventory_items_result.cpp new file mode 100644 index 00000000..01e906f3 --- /dev/null +++ b/Source/Services/Marketplace/inventory_items_result.cpp @@ -0,0 +1,137 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/marketplace.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +inventory_items_result::inventory_items_result() : + m_totalItems(0), + m_allUsersAuthRequired(false), + m_mediaItemType(media_item_type::unknown), + m_inventoryItemState(inventory_item_state::unknown), + m_inventoryItemAvailability(inventory_item_availability::unavailable), + m_expandSatisfyingEntitlements(false) +{ +} + +inventory_items_result::inventory_items_result( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ string_t inventoryItemContainerId, + _In_ bool allUsersAuthRequired, + _In_ std::vector items, + _In_ uint32_t totalItems, + _In_ string_t continuationToken, + _In_ bool expandSatisfyingEntitlements + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_mediaItemType(mediaItemType), + m_inventoryItemState(inventoryItemState), + m_inventoryItemAvailability(inventoryItemAvailability), + m_inventoryItemContainerId(std::move(inventoryItemContainerId)), + m_allUsersAuthRequired(allUsersAuthRequired), + m_items(std::move(items)), + m_totalItems(totalItems), + m_continuationToken(std::move(continuationToken)), + m_expandSatisfyingEntitlements(expandSatisfyingEntitlements) +{ +} + +const std::vector& inventory_items_result::items() const +{ + return m_items; +} + +uint32_t inventory_items_result::total_items() const +{ + return m_totalItems; +} + +const string_t& inventory_items_result::continuation_token() const +{ + return m_continuationToken; +} +pplx::task> +inventory_items_result::get_next( + _In_ uint32_t maxItems + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(m_continuationToken.empty(), inventory_items_result, "Continuation token is empty"); + + inventory_service service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + return service.get_inventory_items( + m_mediaItemType, + m_inventoryItemState, + m_inventoryItemAvailability, + m_inventoryItemContainerId, + m_allUsersAuthRequired, + maxItems, + m_continuationToken, + m_expandSatisfyingEntitlements, + std::vector() + ); +} + +bool +inventory_items_result::has_next() const +{ + return !m_continuationToken.empty(); +} + +void inventory_items_result::_Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ string_t inventoryItemContainerId, + _In_ bool allUsersAuthRequired, + _In_ bool expandSatisfyingEntitlements + ) +{ + m_userContext = std::move(userContext); + m_xboxLiveContextSettings = std::move(xboxLiveContextSettings); + m_appConfig = std::move(appConfig); + m_mediaItemType = mediaItemType; + m_inventoryItemState = inventoryItemState; + m_inventoryItemAvailability = inventoryItemAvailability; + m_inventoryItemContainerId = std::move(inventoryItemContainerId); + m_allUsersAuthRequired = allUsersAuthRequired; + m_expandSatisfyingEntitlements = expandSatisfyingEntitlements; +} + +xbox_live_result +inventory_items_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc; + inventory_items_result result; + result.m_items = utils::extract_json_vector(inventory_item::_Deserialize, json, _T("items"), errc, true); + web::json::value pagingInfoJson = utils::extract_json_field(json, _T("pagingInfo"), errc, false); + if (!pagingInfoJson.is_null()) + { + result.m_continuationToken = utils::extract_json_string(pagingInfoJson, _T("continuationToken"), errc, false); + result.m_totalItems = utils::extract_json_int(pagingInfoJson, _T("totalItems"), errc, true); + } + + return xbox_live_result(result, errc); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Marketplace/inventory_service.cpp b/Source/Services/Marketplace/inventory_service.cpp new file mode 100644 index 00000000..0a2cc47e --- /dev/null +++ b/Source/Services/Marketplace/inventory_service.cpp @@ -0,0 +1,462 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xsapi/marketplace.h" + +using namespace pplx; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_BEGIN + +const string_t::value_type c_inventoryContractVersionHeaderValue[] = _T("4"); + +inventory_service::inventory_service() +{ +} + +inventory_service::inventory_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +inventory_service::get_inventory_items( + _In_ media_item_type mediaItemType, + _In_ bool expandSatisfyingEntitlements, + _In_ bool includeAllItemStatesAndAvailabilities + ) +{ + auto inventoryItemState = inventory_item_state::enabled; + auto inventoryItemAvailability = inventory_item_availability::available; + if(includeAllItemStatesAndAvailabilities) + { + inventoryItemState = inventory_item_state::all; + inventoryItemAvailability = inventory_item_availability::all; + } + + return get_inventory_items( + mediaItemType, + inventoryItemState, + inventoryItemAvailability, + string_t(), + false, + 0, + string_t(), + expandSatisfyingEntitlements, + std::vector() + ); +} + +pplx::task> +inventory_service::get_inventory_items( + _In_ const std::vector& productIds, + _In_ bool expandSatisfyingEntitlements + ) +{ + return get_inventory_items( + media_item_type::all, + inventory_item_state::all, + inventory_item_availability::all, + string_t(), + false, + 0, + string_t(), + expandSatisfyingEntitlements, + productIds + ); +} + +pplx::task> +inventory_service::get_inventory_items( + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ uint32_t maxItems, + _In_ bool expandSatisfyingEntitlements + ) +{ + return get_inventory_items( + mediaItemType, + inventoryItemState, + inventoryItemAvailability, + inventoryItemContainerId, + false, + maxItems, + string_t(), + expandSatisfyingEntitlements, + std::vector() + ); +} + +pplx::task> +inventory_service::get_inventory_items_for_all_users( + _In_ media_item_type mediaItemType, + _In_ bool expandSatisfyingEntitlements, + _In_ bool includeAllItemStatesAndAvailabilities + ) +{ + auto inventoryItemState = inventory_item_state::enabled; + auto inventoryItemAvailability = inventory_item_availability::available; + if(includeAllItemStatesAndAvailabilities) + { + inventoryItemState = inventory_item_state::all; + inventoryItemAvailability = inventory_item_availability::all; + } + + return get_inventory_items( + mediaItemType, + inventoryItemState, + inventoryItemAvailability, + string_t(), + true, + 0, + string_t(), + expandSatisfyingEntitlements, + std::vector() + ); +} + +pplx::task> +inventory_service::get_inventory_items_for_all_users( + _In_ const std::vector& productIds, + _In_ bool expandSatisfyingEntitlements + ) +{ + return get_inventory_items( + media_item_type::all, + inventory_item_state::all, + inventory_item_availability::all, + string_t(), + true, + 0, + string_t(), + expandSatisfyingEntitlements, + productIds + ); +} + +pplx::task> +inventory_service::get_inventory_items_for_all_users( + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ uint32_t maxItems, + _In_ bool expandSatisfyingEntitlements + ) +{ + return get_inventory_items( + mediaItemType, + inventoryItemState, + inventoryItemAvailability, + inventoryItemContainerId, + true, + maxItems, + string_t(), + expandSatisfyingEntitlements, + std::vector() + ); +} + +pplx::task> +inventory_service::get_inventory_item( + _In_ inventory_item inventoryItem + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(inventoryItem.url().is_empty(), inventory_item, "inventoryItem url cannot be empty"); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + inventoryItem.url().to_string(), + nullptr, + xbox_live_api::get_inventory_item + ); + + httpCall->set_xbox_contract_version_header_value(c_inventoryContractVersionHeaderValue); + + return httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto result = inventory_item::_Deserialize(response->response_body_json()); + return utils::generate_xbox_live_result( + result, + response + ); + }); +} + +pplx::task> +inventory_service::consume_inventory_item( + _In_ inventory_item inventoryItem, + _In_ uint32_t quantityToConsume, + _In_ const string_t& transactionId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(inventoryItem.consumable_url().to_string().empty(), consume_inventory_item_result, "inventoryItems consumableUrl cannot be empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(quantityToConsume == 0, consume_inventory_item_result, "quantityToConsume"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(transactionId, consume_inventory_item_result, "transactionId cannot be empty"); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + inventoryItem.consumable_url().to_string(), + _T(""), + xbox_live_api::consume_inventory_item + ); + consume_inventory_item_request request( + transactionId, + quantityToConsume + ); + + httpCall->set_retry_allowed(false); + httpCall->set_request_body(request._Serialize().serialize()); + httpCall->set_xbox_contract_version_header_value(c_inventoryContractVersionHeaderValue); + + return httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto result = consume_inventory_item_result::_Deserialize(response->response_body_json()); + return utils::generate_xbox_live_result( + result, + response + ); + }); +} + +pplx::task> +inventory_service::get_inventory_items( + _In_ media_item_type mediaItemType, + _In_ inventory_item_state inventoryItemState, + _In_ inventory_item_availability inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ bool allUsersAuthRequired, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ bool expandSatisfyingEntitlements, + _In_ const std::vector& productIds + ) +{ + auto mediaItemTypeResult = convert_media_item_type_to_string(mediaItemType); + RETURN_TASK_CPP_IF_ERR(mediaItemTypeResult, inventory_items_result); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(productIds.size() == 0 && expandSatisfyingEntitlements && mediaItemType == media_item_type::all, inventory_items_result, "expandSatisfyingEntitlements is not supported with mediaItemType::All"); + + auto inventoryItemStateResult = convert_inventory_item_state_to_string(inventoryItemState); + RETURN_TASK_CPP_IF_ERR(inventoryItemStateResult, inventory_items_result); + auto inventoryItemAvailabilityResult = convert_inventory_item_availability_to_string(inventoryItemAvailability); + RETURN_TASK_CPP_IF_ERR(inventoryItemAvailabilityResult, inventory_items_result); + + auto subpathAndQuery = get_inventory_items_sub_path( + mediaItemType, + mediaItemTypeResult.payload(), + inventoryItemStateResult.payload(), + inventoryItemAvailabilityResult.payload(), + inventoryItemContainerId, + maxItems, + continuationToken, + expandSatisfyingEntitlements, + productIds + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("inventory"), m_appConfig), + subpathAndQuery, + xbox_live_api::get_inventory_items + ); + + httpCall->set_xbox_contract_version_header_value(c_inventoryContractVersionHeaderValue); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + + auto task = httpCall->get_response_with_auth(m_userContext, http_call_response_body_type::json_body, allUsersAuthRequired) + .then([userContext, xboxLiveContextSettings, appConfig, mediaItemType, inventoryItemState, inventoryItemAvailability, inventoryItemContainerId, allUsersAuthRequired, expandSatisfyingEntitlements](std::shared_ptr response) + { + auto inventoryResult = inventory_items_result::_Deserialize(response->response_body_json()); + + auto& result = inventoryResult.payload(); + // Initialize the request params for get_next() + result._Initialize( + userContext, + xboxLiveContextSettings, + appConfig, + mediaItemType, + inventoryItemState, + inventoryItemAvailability, + inventoryItemContainerId, + allUsersAuthRequired, + expandSatisfyingEntitlements + ); + + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +const string_t inventory_service::get_inventory_items_sub_path( + _In_ media_item_type mediaItemType, + _In_ const string_t& mediaItemTypeString, + _In_ const string_t& inventoryItemState, + _In_ const string_t& inventoryItemAvailability, + _In_ const string_t& inventoryItemContainerId, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken, + _In_ bool expandSatisfyingEntitlements, + _In_ const std::vector& productIds + ) +{ + stringstream_t source; + source << _T("/users/me/inventory"); + + web::uri_builder builder; + builder.set_path(source.str()); + std::vector params; + + if(mediaItemType != media_item_type::all) + { + builder.append_query(_T("itemType"), mediaItemTypeString); + } + + if (!inventoryItemState.empty()) + { + builder.append_query(_T("state"), inventoryItemState); + } + + if (!inventoryItemContainerId.empty()) + { + builder.append_query(_T("container"), inventoryItemContainerId); + } + + if (!inventoryItemAvailability.empty()) + { + builder.append_query(_T("availability"), inventoryItemAvailability); + } + + if(expandSatisfyingEntitlements) + { + builder.append_query(_T("expandSatisfyingEntitlements"), _T("true")); + } + + if (!productIds.empty()) + { + stringstream_t param; + uint32_t addedIds = 0; + for (auto& productId : productIds) + { + if ( addedIds != 0 ) + { + param << _T(","); + } + + param << web::uri::encode_uri(productId); + ++addedIds; + } + builder.append_query(_T("productIds"), param.str()); + } + + utils::append_paging_info( + builder, + 0, + maxItems, + continuationToken + ); + + return builder.to_string(); +} + +const xbox_live_result +inventory_service::convert_media_item_type_to_string( + _In_ media_item_type mediaItemType + ) +{ + switch (mediaItemType) + { + case media_item_type::game_v2: return xbox_live_result(_T("GameV2")); + + case media_item_type::game_content: return xbox_live_result(_T("GameContent")); + + case media_item_type::game_consumable: return xbox_live_result(_T("GameConsumable")); + + case media_item_type::subscription: return xbox_live_result(_T("Subscription")); + + case media_item_type::all: return xbox_live_result(_T("All")); + + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Unsupported media_item_type type"); + } +} + +const xbox_live_result +inventory_service::convert_inventory_item_state_to_string( + _In_ inventory_item_state inventorytItemState + ) +{ + switch (inventorytItemState) + { + case inventory_item_state::all: + return xbox_live_result(); + + case inventory_item_state::enabled: + return xbox_live_result(_T("Enabled")); + + case inventory_item_state::suspended: + return xbox_live_result(_T("Suspended")); + + case inventory_item_state::expired: + return xbox_live_result(_T("Expired")); + + case inventory_item_state::canceled: + return xbox_live_result(_T("Canceled")); + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Unsupported inventory_item_state type"); + } +} + +const xbox_live_result +inventory_service::convert_inventory_item_availability_to_string( + _In_ inventory_item_availability inventorytItemAvailability + ) +{ + switch (inventorytItemAvailability) + { + case inventory_item_availability::all: + return xbox_live_result(_T("All")); + + case inventory_item_availability::available: + return xbox_live_result(_T("Available")); + + case inventory_item_availability::unavailable: + return xbox_live_result(_T("Unavailable")); + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Unsupported inventory_item_availability type"); + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MARKETPLACE_CPP_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/WinRT/CreateMatchTicketResponse_WinRT.h b/Source/Services/Matchmaking/WinRT/CreateMatchTicketResponse_WinRT.h new file mode 100644 index 00000000..438e935f --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/CreateMatchTicketResponse_WinRT.h @@ -0,0 +1,44 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi\multiplayer.h" +#include "xsapi\matchmaking.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +/// +/// Represents a server response to a create match ticket request. +/// +public ref class CreateMatchTicketResponse sealed +{ +public: + /// + /// Ticket ID of a match request. + /// + DEFINE_PROP_GET_STR_OBJ(MatchTicketId, match_ticket_id) + + /// + /// Estimated wait time for a match request to be matched with other players. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(EstimatedWaitTime, estimated_wait_time) + +internal: + CreateMatchTicketResponse( + _In_ xbox::services::matchmaking::create_match_ticket_response cppObj + ): + m_cppObj(std::move(cppObj)) + { + } + +private: + xbox::services::matchmaking::create_match_ticket_response m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END diff --git a/Source/Services/Matchmaking/WinRT/HopperStatisticsResponse_WinRT.h b/Source/Services/Matchmaking/WinRT/HopperStatisticsResponse_WinRT.h new file mode 100644 index 00000000..d7e6610a --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/HopperStatisticsResponse_WinRT.h @@ -0,0 +1,49 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi\multiplayer.h" +#include "xsapi\matchmaking.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +/// +/// Represents a server response to a hopper statistics request. +/// +public ref class HopperStatisticsResponse sealed +{ +public: + /// + /// Name of the hopper in which a match was requested. + /// + DEFINE_PROP_GET_STR_OBJ(HopperName, hopper_name) + + /// + /// Estimated wait time for a match request to be matched with other players. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(EstimatedWaitTime, estimated_wait_time) + + /// + /// The number of players in the hopper waiting to be matched. + /// + DEFINE_PROP_GET_OBJ(PlayersWaitingToMatch, players_waiting_to_match, uint32) + +internal: + HopperStatisticsResponse( + _In_ xbox::services::matchmaking::hopper_statistics_response cppObj + ) : + m_cppObj(std::move(cppObj)) + { + } + +private: + xbox::services::matchmaking::hopper_statistics_response m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.cpp b/Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.cpp new file mode 100644 index 00000000..fd791748 --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.cpp @@ -0,0 +1,61 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "xsapi/matchmaking.h" +#include "MatchTicketDetailsResponse_WinRT.h" + +using namespace Platform::Collections; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::matchmaking; +using namespace Microsoft::Xbox::Services::Multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +MatchTicketDetailsResponse::MatchTicketDetailsResponse( + _In_ match_ticket_details_response cppObj + ): + m_cppObj(std::move(cppObj)) +{ + if (!m_cppObj.ticket_session().is_null()) + { + m_ticketSession = ref new MultiplayerSessionReference(m_cppObj.ticket_session()); + } + + if (!m_cppObj.target_session().is_null()) + { + m_targetSession = ref new MultiplayerSessionReference(m_cppObj.target_session()); + } + + m_ticketAttributes = ref new String(m_cppObj.ticket_attributes().serialize().c_str()); +} + +MultiplayerSessionReference^ +MatchTicketDetailsResponse::TicketSession::get() +{ + return m_ticketSession; +} + +MultiplayerSessionReference^ +MatchTicketDetailsResponse::TargetSession::get() +{ + return m_targetSession; +} + +Platform::String^ +MatchTicketDetailsResponse::TicketAttributes::get() +{ + return m_ticketAttributes; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.h b/Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.h new file mode 100644 index 00000000..826f95c0 --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/MatchTicketDetailsResponse_WinRT.h @@ -0,0 +1,74 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "PreserveSessionMode_WinRT.h" +#include "TicketStatus_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +/// +/// Represents a server response to a request for match ticket details. +/// +public ref class MatchTicketDetailsResponse sealed +{ +public: + /// + /// Status of a match request. + /// + DEFINE_PROP_GET_ENUM_OBJ(MatchStatus, match_status, TicketStatus); + + /// + /// Estimated wait time for a match request to be matched with other players. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(EstimatedWaitTime, estimated_wait_time); + + /// + /// An enum value to specify whether the match should preserve the session on which the match has been requested. + /// + DEFINE_PROP_GET_ENUM_OBJ(PreserveSession, preserve_session, PreserveSessionMode); + + /// + /// The session on which the match was requested. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ TicketSession + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ get(); + } + + /// + /// The session on which a match request has been found. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ TargetSession + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ get(); + } + + /// + /// The attributes of a match request. + /// + property Platform::String^ TicketAttributes + { + Platform::String^ get(); + } + +internal: + MatchTicketDetailsResponse( + _In_ xbox::services::matchmaking::match_ticket_details_response cppObj + ); + +private: + Multiplayer::MultiplayerSessionReference^ m_ticketSession; + Multiplayer::MultiplayerSessionReference^ m_targetSession; + Platform::String^ m_ticketAttributes; + xbox::services::matchmaking::match_ticket_details_response m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.cpp b/Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.cpp new file mode 100644 index 00000000..026b8989 --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.cpp @@ -0,0 +1,129 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "matchmakingService_winrt.h" +#include "Utils_WinRT.h" + +using namespace Concurrency; +using namespace Platform::Collections; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::matchmaking; +using namespace xbox::services::multiplayer; +using namespace Microsoft::Xbox::Services::Multiplayer; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +const wchar_t c_matchmakingContractVersionHeaderValue[] = L"103"; + +MatchmakingService::MatchmakingService( + _In_ xbox::services::matchmaking::matchmaking_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +IAsyncOperation^ +MatchmakingService::CreateMatchTicketAsync( + _In_ MultiplayerSessionReference^ ticketSessionReference, + _In_ String^ matchmakingServiceConfigurationId, + _In_ String^ hopperName, + _In_ TimeSpan ticketTimeout, + _In_ PreserveSessionMode preserveSession, + _In_opt_ String^ ticketAttributesJson + ) +{ + web::json::value ticketAttributes; + + if (!ticketAttributesJson->IsEmpty()) + { + ticketAttributes = web::json::value::parse(STRING_T_FROM_PLATFORM_STRING(ticketAttributesJson)); + } + + auto task = m_cppObj.create_match_ticket( + ticketSessionReference == nullptr ? multiplayer_session_reference() : ticketSessionReference->GetCppObj(), + STRING_T_FROM_PLATFORM_STRING(matchmakingServiceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(hopperName), + UtilsWinRT::ConvertTimeSpanToSeconds(ticketTimeout), + static_cast(preserveSession), + ticketAttributes + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new CreateMatchTicketResponse(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncAction^ +MatchmakingService::DeleteMatchTicketAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ hopperName, + _In_ Platform::String^ ticketId + ) +{ + auto task = m_cppObj.delete_match_ticket( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(hopperName), + STRING_T_FROM_PLATFORM_STRING(ticketId) + ).then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MatchmakingService::GetMatchTicketDetailsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ hopperName, + _In_ Platform::String^ ticketId + ) +{ + auto task = m_cppObj.get_match_ticket_details( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(hopperName), + STRING_T_FROM_PLATFORM_STRING(ticketId) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new MatchTicketDetailsResponse(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MatchmakingService::GetHopperStatisticsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ hopperName + ) +{ + auto task = m_cppObj.get_hopper_statistics( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(hopperName) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new HopperStatisticsResponse(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END diff --git a/Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.h b/Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.h new file mode 100644 index 00000000..e799cc52 --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/MatchmakingService_WinRT.h @@ -0,0 +1,101 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "CreateMatchTicketResponse_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MatchTicketDetailsResponse_WinRT.h" +#include "PreserveSessionMode_WinRT.h" +#include "HopperStatisticsResponse_WinRT.h" +#include "xsapi/matchmaking.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN +/// +/// Represents a service for matchmaking. +/// + +public ref class MatchmakingService sealed +{ +public: + /// + /// Sends a matchmaking request to the server and returns the match ticket with a ticket id. + /// + /// The multiplayer session to use for the match. + /// The service configuration ID for the match. + /// The name of the hopper. + /// The maximum time to wait for players to join the session. + /// Indicates if the session should be preserved. + /// The ticket attributes for the session. (Optional) + /// The async object for notifying when the operation is completed. With the handler, a new match ticket + /// object is returned. The match ticket object contains server returned information such as ticket id and wait + /// time, and also contains copies of the title specified data from the ticket data object. + /// Calls V103 POST /serviceconfigs/{serviceConfigId}/hoppers/{hopperName} + Windows::Foundation::IAsyncOperation^ CreateMatchTicketAsync( + _In_ Multiplayer::MultiplayerSessionReference^ ticketSessionReference, + _In_ Platform::String^ matchmakingServiceConfigurationId, + _In_ Platform::String^ hopperName, + _In_ Windows::Foundation::TimeSpan ticketTimeout, + _In_ PreserveSessionMode preserveSession, + _In_opt_ Platform::String^ ticketAttributesJson + ); + + /// + /// Deletes a the match ticket on the server. + /// + /// The service config id that is specific for the title. + /// The name of the hopper where the match ticket is located. + /// The id of the ticket to delete on the server. + /// The async object for notifying when the operation has been completed. + /// Calls V103 DELETE /serviceconfigs/{serviceConfigId}/hoppers/{hopperName}/tickets/{ticketId} + Windows::Foundation::IAsyncAction^ DeleteMatchTicketAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ hopperName, + _In_ Platform::String^ ticketId + ); + + /// + /// Retrieves the properties of a match ticket from the server. + /// + /// The service config id that is specific for the title. + /// The name of the hopper where the match ticket is located. + /// The ticket id of the match ticket to retrieve. + /// The async object for notifying when the operation is completed. With the handler, the match + /// ticket object with the data for the ticket, including ticket id and wait time information, is returned + /// returned from the server. + /// Calls V103 GET /serviceconfigs/{serviceConfigId}/hoppers/{hopperName}/tickets/{ticketId} + Windows::Foundation::IAsyncOperation^ GetMatchTicketDetailsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ hopperName, + _In_ Platform::String^ ticketId + ); + + /// + /// Gets statistics about a hopper such as how many players are in it. + /// + /// The service config id that is specific for the title. + /// The name of the hopper to query stats for. + /// The async object for notifying when the operation is completed. With the handler, an object + /// containing statistics about the hopper is returned. + /// Calls V103 GET /serviceconfigs/{serviceConfigId}/hoppers/{hopperName}/stats + Windows::Foundation::IAsyncOperation^ GetHopperStatisticsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ hopperName + ); + +internal: + MatchmakingService( + _In_ xbox::services::matchmaking::matchmaking_service cppObj + ); + +private: + xbox::services::matchmaking::matchmaking_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END diff --git a/Source/Services/Matchmaking/WinRT/PreserveSessionMode_WinRT.h b/Source/Services/Matchmaking/WinRT/PreserveSessionMode_WinRT.h new file mode 100644 index 00000000..83fe28c5 --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/PreserveSessionMode_WinRT.h @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +/// +/// Defines values that indicate if a match ticket is for a new +/// game session or an existing session. +/// +public enum class PreserveSessionMode +{ + /// + /// The server returned an unrecognized response. + /// + Unknown = xbox::services::matchmaking::preserve_session_mode::unknown, + + /// + /// Always use an existing game session. This is for matching more players + /// for a game session that is already created or in progress. + /// + Always = xbox::services::matchmaking::preserve_session_mode::always, + + /// + /// Never use an existing game session. This is for matching players + /// for a new game session. + /// + Never = xbox::services::matchmaking::preserve_session_mode::never +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/WinRT/TicketStatus_WinRT.h b/Source/Services/Matchmaking/WinRT/TicketStatus_WinRT.h new file mode 100644 index 00000000..fbb44f87 --- /dev/null +++ b/Source/Services/Matchmaking/WinRT/TicketStatus_WinRT.h @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_BEGIN + +/// +/// Defines values that indicate the status of the match request. +/// request. +/// +public enum class TicketStatus +{ + /// + /// The status of the match request has not been returned by the server yet + /// or the server returned an unrecognized response. + /// + Unknown = xbox::services::matchmaking::ticket_status::unknown, + + /// + /// Matchmaking has not found a match and the search + /// request has expired according to its give up duration. + /// + Expired = xbox::services::matchmaking::ticket_status::expired, + + /// + /// Matchmaking has not found a match yet and it is + /// still searching. + /// + Searching = xbox::services::matchmaking::ticket_status::searching, + + /// + /// Matchmaking has found a match and the ticket contains a + /// reference to the session that is to be created. + /// + Found = xbox::services::matchmaking::ticket_status::found, + + /// + /// Matchmaking has been canceled for this ticket. + /// + Canceled = xbox::services::matchmaking::ticket_status::canceled +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/create_match_ticket_response.cpp b/Source/Services/Matchmaking/create_match_ticket_response.cpp new file mode 100644 index 00000000..130357b6 --- /dev/null +++ b/Source/Services/Matchmaking/create_match_ticket_response.cpp @@ -0,0 +1,60 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" +#include "xsapi/matchmaking.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_BEGIN + +create_match_ticket_response::create_match_ticket_response() +{ +} + +create_match_ticket_response::create_match_ticket_response( + _In_ string_t matchTicketId, + _In_ std::chrono::seconds estimatedWaitTime + ) : + m_matchTicketId(std::move(matchTicketId)), + m_estimatedWaitTime(std::move(estimatedWaitTime)) +{ +} + +const string_t& +create_match_ticket_response::match_ticket_id() const +{ + return m_matchTicketId; +} + +const std::chrono::seconds& +create_match_ticket_response::estimated_wait_time() const +{ + return m_estimatedWaitTime; +} + +xbox_live_result +create_match_ticket_response::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto response = create_match_ticket_response( + utils::extract_json_string(json, _T("ticketId"), errc, true), + std::chrono::seconds(utils::extract_json_int(json, _T("waitTime"), errc)) + ); + + return xbox_live_result(response, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/hopper_statistics_response.cpp b/Source/Services/Matchmaking/hopper_statistics_response.cpp new file mode 100644 index 00000000..52518a1f --- /dev/null +++ b/Source/Services/Matchmaking/hopper_statistics_response.cpp @@ -0,0 +1,74 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" +#include "xsapi/matchmaking.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_BEGIN + +hopper_statistics_response::hopper_statistics_response(): + m_playersWaitingToMatch(0) +{ +} + +hopper_statistics_response::hopper_statistics_response( + _In_ string_t hopperName, + _In_ std::chrono::seconds estimatedWaitTime, + _In_ uint32_t playersWaitingToMatch + ) : + m_hopperName(std::move(hopperName)), + m_estimatedWaitTime(std::move(estimatedWaitTime)), + m_playersWaitingToMatch(playersWaitingToMatch) +{ +} + +/// +/// Name of the hopper in which a match was requested. +/// +const string_t& +hopper_statistics_response::hopper_name() const +{ + return m_hopperName; +} + +/// +/// Estimated wait time for a match request to be matched with other players. +/// +const std::chrono::seconds& hopper_statistics_response::estimated_wait_time() const +{ + return m_estimatedWaitTime; +} + +/// +/// The number of players in the hopper waiting to be matched. +/// +uint32_t hopper_statistics_response::players_waiting_to_match() const +{ + return m_playersWaitingToMatch; +} + +xbox_live_result +hopper_statistics_response::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + return hopper_statistics_response( + utils::extract_json_string(json, _T("name"), errc, true), + std::chrono::seconds(utils::extract_json_int(json, _T("waitTime"), errc, false)), + utils::extract_json_int(json, _T("population"), errc, false) + ); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/match_ticket_details_response.cpp b/Source/Services/Matchmaking/match_ticket_details_response.cpp new file mode 100644 index 00000000..58f4e1c2 --- /dev/null +++ b/Source/Services/Matchmaking/match_ticket_details_response.cpp @@ -0,0 +1,149 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" +#include "xsapi/matchmaking.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_BEGIN + +match_ticket_details_response::match_ticket_details_response() : + m_matchStatus(ticket_status::unknown), + m_preserveSession(preserve_session_mode::unknown) +{ +} + +match_ticket_details_response::match_ticket_details_response( + _In_ ticket_status matchStatus, + _In_ std::chrono::seconds estimatedWaitTime, + _In_ preserve_session_mode preserveSession, + _In_ multiplayer_session_reference ticketSession, + _In_ multiplayer_session_reference targetSession, + _In_ web::json::value ticketAttributes + ) : + m_matchStatus(matchStatus), + m_estimatedWaitTime(std::move(estimatedWaitTime)), + m_preserveSession(preserveSession), + m_ticketSession(std::move(ticketSession)), + m_targetSession(std::move(targetSession)), + m_ticketAttributes(std::move(ticketAttributes)) +{ +} + +ticket_status +match_ticket_details_response::match_status() const +{ + return m_matchStatus; +} + +const std::chrono::seconds& +match_ticket_details_response::estimated_wait_time() const +{ + return m_estimatedWaitTime; +} + +preserve_session_mode +match_ticket_details_response::preserve_session() const +{ + return m_preserveSession; +} + +const multiplayer_session_reference& +match_ticket_details_response::ticket_session() const +{ + return m_ticketSession; +} + +const multiplayer_session_reference& +match_ticket_details_response::target_session() const +{ + return m_targetSession; +} + +const web::json::value& +match_ticket_details_response::ticket_attributes() const +{ + return m_ticketAttributes; +} + +xbox_live_result +match_ticket_details_response::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + auto ticketSessionRef = multiplayer_session_reference::_Deserialize(utils::extract_json_field(json, _T("ticketSessionRef"), errc, false)); + auto targetSessionRef = multiplayer_session_reference::_Deserialize(utils::extract_json_field(json, _T("targetSessionRef"), errc, false)); + + auto result = match_ticket_details_response( + convert_string_to_ticket_status(utils::extract_json_string(json, _T("ticketStatus"), errc, true)), + std::chrono::seconds(utils::extract_json_int(json, _T("waitTime"), errc)), + convert_string_to_preserve_session_mode(utils::extract_json_string(json, _T("preserveSession"), errc, false)), + ticketSessionRef.payload(), + targetSessionRef.payload(), + utils::extract_json_field(json, _T("ticketAttributes"), errc, false) + ); + + return xbox_live_result(result, errc); +} + +ticket_status match_ticket_details_response::convert_string_to_ticket_status( + _In_ const string_t& value + ) +{ + ticket_status ticketStatus = ticket_status::unknown; + if (!value.empty()) + { + if (utils::str_icmp(value, _T("expired")) == 0) + { + ticketStatus = ticket_status::expired; + } + else if (utils::str_icmp(value, _T("searching")) == 0) + { + ticketStatus = ticket_status::searching; + } + else if (utils::str_icmp(value, _T("found")) == 0) + { + ticketStatus = ticket_status::found; + } + else if (utils::str_icmp(value, _T("canceled")) == 0) + { + ticketStatus = ticket_status::canceled; + } + } + + return ticketStatus; +} + +preserve_session_mode match_ticket_details_response::convert_string_to_preserve_session_mode( + _In_ const string_t& value + ) +{ + preserve_session_mode preserve_session_mode = preserve_session_mode::unknown; + if (!value.empty()) + { + if (utils::str_icmp(value, _T("always")) == 0) + { + preserve_session_mode = preserve_session_mode::always; + } + else if (utils::str_icmp(value, _T("never")) == 0) + { + preserve_session_mode = preserve_session_mode::never; + } + } + return preserve_session_mode; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_END \ No newline at end of file diff --git a/Source/Services/Matchmaking/matchmaking_service.cpp b/Source/Services/Matchmaking/matchmaking_service.cpp new file mode 100644 index 00000000..0fa4290d --- /dev/null +++ b/Source/Services/Matchmaking/matchmaking_service.cpp @@ -0,0 +1,257 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xbox_system_factory.h" +#include "xsapi/multiplayer.h" +#include "xsapi/matchmaking.h" +#include "utils.h" + +using namespace xbox::services::multiplayer; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MATCHMAKING_CPP_BEGIN + +matchmaking_service::matchmaking_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +matchmaking_service::create_match_ticket( + _In_ const multiplayer_session_reference& ticketSessionReference, + _In_ const string_t& matchmakingServiceConfigurationId, + _In_ const string_t& hopperName, + _In_ const std::chrono::seconds& ticketTimeout, + _In_ preserve_session_mode preserveSession, + _In_ const web::json::value& ticketAttributesJson + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(ticketSessionReference.is_null(), create_match_ticket_response, "ticket session reference is null"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(matchmakingServiceConfigurationId, create_match_ticket_response, "hopper name is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(hopperName, create_match_ticket_response, "hopper name is empty"); + + string_t subPath = matchmaking_sub_path( + matchmakingServiceConfigurationId, + hopperName, + string_t() // ticketId + ); + + web::json::value request; + request[_T("giveUpDuration")] = web::json::value::number(static_cast(ticketTimeout.count())); + request[_T("preserveSession")] = web::json::value::string(convert_preserve_session_mode_to_string(preserveSession)); + request[_T("ticketSessionRef")] = ticketSessionReference._Serialize(); + if (!ticketAttributesJson.is_null()) + { + request[_T("ticketAttributes")] = std::move(ticketAttributesJson); + } + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("smartmatch"), m_appConfig), + subPath, + xbox_live_api::create_match_ticket + ); + + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(_T("103")); + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + create_match_ticket_response::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +matchmaking_service::delete_match_ticket( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& hopperName, + _In_ const string_t& ticketId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, void, "service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(hopperName, void, "hopper name is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(ticketId, void, "ticket id is empty"); + + string_t subPath = matchmaking_sub_path( + serviceConfigurationId, + hopperName, + ticketId + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("DELETE"), + utils::create_xboxlive_endpoint(_T("smartmatch"), m_appConfig), + subPath, + xbox_live_api::delete_match_ticket + ); + httpCall->set_xbox_contract_version_header_value(_T("103")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +matchmaking_service::get_match_ticket_details( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& hopperName, + _In_ const string_t& ticketId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, match_ticket_details_response, "service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(hopperName, match_ticket_details_response, "hopper name is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(ticketId, match_ticket_details_response, "ticket id is empty"); + + string_t subPath = matchmaking_sub_path( + serviceConfigurationId, + hopperName, + ticketId + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("smartmatch"), m_appConfig), + subPath, + xbox_live_api::get_match_ticket_details + ); + httpCall->set_xbox_contract_version_header_value(_T("103")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + match_ticket_details_response::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +matchmaking_service::get_hopper_statistics( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& hopperName + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, hopper_statistics_response, "service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(hopperName, hopper_statistics_response, "hopper name is empty"); + + string_t subPath = hopper_sub_path( + serviceConfigurationId, + hopperName + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("smartmatch"), m_appConfig), + subPath, + xbox_live_api::get_hopper_statistics + ); + httpCall->set_xbox_contract_version_header_value(_T("103")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + hopper_statistics_response::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +string_t +matchmaking_service::matchmaking_sub_path( + _In_ const string_t& serviceConfigId, + _In_ const string_t& hopperName, + _In_ const string_t& ticketId + ) +{ + stringstream_t ss; + ss << _T("/serviceconfigs/"); + ss << serviceConfigId; + ss << _T("/hoppers/"); + ss << hopperName; + + if (!ticketId.empty()) + { + ss << _T("/tickets/"); + ss << ticketId; + } + + return ss.str(); +} + +string_t matchmaking_service::hopper_sub_path( + _In_ const string_t& serviceConfigId, + _In_ const string_t& hopperName + ) +{ + stringstream_t ss; + ss << _T("/serviceconfigs/"); + ss << serviceConfigId; + ss << _T("/hoppers/"); + ss << hopperName; + ss << _T("/stats"); + + return ss.str(); +} + +string_t +matchmaking_service::convert_preserve_session_mode_to_string( + _In_ preserve_session_mode preserve_session + ) +{ + string_t retval(_T("unknown")); + if (preserve_session == preserve_session_mode::always) + { + retval = _T("always"); + } + else if (preserve_session == preserve_session_mode::never) + { + retval = _T("never"); + } + + return retval; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_LEADERBOARD_CPP_END \ No newline at end of file diff --git a/Source/Services/Misc/Android/title_callable_static_glue.h b/Source/Services/Misc/Android/title_callable_static_glue.h new file mode 100644 index 00000000..2437de53 --- /dev/null +++ b/Source/Services/Misc/Android/title_callable_static_glue.h @@ -0,0 +1,2 @@ +#pragma once +bool title_callable_ui_register_natives(JNIEnv *env, jobject clsLoader, jmethodID loadClass); \ No newline at end of file diff --git a/Source/Services/Misc/Android/title_callable_ui_android.cpp b/Source/Services/Misc/Android/title_callable_ui_android.cpp new file mode 100644 index 00000000..95466a81 --- /dev/null +++ b/Source/Services/Misc/Android/title_callable_ui_android.cpp @@ -0,0 +1,406 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/title_callable_ui.h" +#include "a/java_interop.h" +#include "a/jni_utils.h" +#include "Misc/Android/title_callable_ui_jni.h" +#include "a/user_impl_a.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_BEGIN + +bool title_callable_ui_internal::s_isTcuiRunning = false; +pplx::task_completion_event title_callable_ui_internal::s_tcuiEventCompleted; + +void +title_callable_ui_internal::tcui_completed_callback(JNIEnv *, jclass, int errorCode) +{ + s_tcuiEventCompleted.set(errorCode); +} + +xbox_live_result> +tcui_init() +{ + if (title_callable_ui_internal::s_isTcuiRunning) + { + return xbox_live_result>(xbox_live_result>( + xbox_live_error_code::logic_error, + _T("Previous tcui operation has not been completed")) + ); + } + + std::shared_ptr interop = java_interop::get_java_interop_singleton(); + if (interop == nullptr) + { + return xbox_live_result>(xbox_live_result>( + xbox_live_error_code::logic_error, + _T("XSAPI has not been initialized with the JVM")) + ); + } + + title_callable_ui_internal::s_tcuiEventCompleted = task_completion_event(); + return interop; +} + +pplx::task> +title_callable_ui::show_profile_card_ui( + _In_ const string_t& targetXboxUserId +) +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto activity = interop->get_activity(); + auto xblUser = xbox_live_user::get_last_signed_in_user(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + + jmethodID showProfileCardUIMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowProfileCardUI", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (showProfileCardUIMethodId != NULL && xblUser != nullptr) + { + title_callable_ui_internal::s_isTcuiRunning = true; + auto userXuid = xblUser->xbox_user_id(); + auto userPrivileges = xblUser->privileges(); + auto currentUserIdString = jniEnv->NewStringUTF(userXuid.c_str()); + auto targetUserIdString = jniEnv->NewStringUTF(targetXboxUserId.c_str()); + auto currentUserPrivileges = jniEnv->NewStringUTF(userPrivileges.c_str()); + jniEnv->CallStaticVoidMethod(interopTcuiClass, showProfileCardUIMethodId, activity, currentUserIdString, targetUserIdString, currentUserPrivileges); + } + else + { + pplx::task_from_result>(xbox_live_result( + xbox_live_error_code::logic_error, + _T("ShowProfileCardUI method not found")) + ); + } + + JNI_ERROR_CHECK(jniEnv) + return task; +} + +pplx::task> +title_callable_ui::show_friend_finder_ui() +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto activity = interop->get_activity(); + auto xblUser = xbox_live_user::get_last_signed_in_user(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + jmethodID showFriendFinderMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowFriendFinder", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;)V"); + if (showFriendFinderMethodId != NULL && xblUser != nullptr) + { + title_callable_ui_internal::s_isTcuiRunning = true; + auto userXuid = xblUser->xbox_user_id(); + auto userPrivileges = xblUser->privileges(); + auto currentUserIdString = jniEnv->NewStringUTF(userXuid.c_str()); + auto currentUserPrivileges = jniEnv->NewStringUTF(userPrivileges.c_str()); + jniEnv->CallStaticVoidMethod(interopTcuiClass, showFriendFinderMethodId, activity, currentUserIdString, currentUserPrivileges); + } + + JNI_ERROR_CHECK(jniEnv) + + return task; +} + +pplx::task> +title_callable_ui::show_user_profile_ui( + _In_ const string_t& targetXboxUserId +) +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto activity = interop->get_activity(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + jmethodID showUserProfileMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowUserProfile", "(Landroid/content/Context;Ljava/lang/String;)V"); + if (showUserProfileMethodId != NULL) + { + auto targetXuid = jniEnv->NewStringUTF(targetXboxUserId.c_str()); + jniEnv->CallStaticVoidMethod(interopTcuiClass, showUserProfileMethodId, activity, targetXuid); + } + + JNI_ERROR_CHECK(jniEnv); + + return task; +} + +pplx::task> +title_callable_ui::show_title_hub_ui() +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto activity = interop->get_activity(); + auto titleId = xbox_live_app_config::get_app_config_singleton()->title_id(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + jmethodID showTitleHubMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowTitleHub", "(Landroid/content/Context;Ljava/lang/String;)V"); + if (showTitleHubMethodId != NULL) + { + stringstream_t titleIdStr; + titleIdStr << titleId; + auto jTitleId = jniEnv->NewStringUTF(titleIdStr.str().c_str()); + jniEnv->CallStaticVoidMethod(interopTcuiClass, showTitleHubMethodId, activity, jTitleId); + } + + JNI_ERROR_CHECK(jniEnv); + + return task; +} + +pplx::task> +title_callable_ui::show_title_achievements_ui( + _In_ uint32_t titleId + ) +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + // TODO: Bug 8326148 + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto activity = interop->get_activity(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + jmethodID showTitleAchievementsMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowTitleAchievements", "(Landroid/content/Context;Ljava/lang/String;)V"); + if (showTitleAchievementsMethodId != NULL) + { + stringstream_t titleIdStr; + titleIdStr << titleId; + auto jTitleId = jniEnv->NewStringUTF(titleIdStr.str().c_str()); + jniEnv->CallStaticVoidMethod(interopTcuiClass, showTitleAchievementsMethodId, activity, jTitleId); + } + + JNI_ERROR_CHECK(jniEnv); + + return task; +} + +pplx::task> +title_callable_ui::show_user_settings_ui() +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + // TODO: Bug 8326148 + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto context = interop->get_context_object(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + jmethodID showUserSettingsMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowUserSettings", "(Landroid/content/Context;)V"); + if (showUserSettingsMethodId != NULL) + { + jniEnv->CallStaticVoidMethod(interopTcuiClass, showUserSettingsMethodId, context); + } + + JNI_ERROR_CHECK(jniEnv); + + return task; +} + +pplx::task> +title_callable_ui::show_add_friends_ui() +{ + auto interopResult = tcui_init(); + if (interopResult.err()) + { + return pplx::task_from_result>( + xbox_live_result( + interopResult.err(), + interopResult.err_message() + ) + ); + } + + auto task = pplx::create_task(title_callable_ui_internal::s_tcuiEventCompleted) + .then([](int32_t errorCode) + { + title_callable_ui_internal::s_isTcuiRunning = false; + // TODO: Bug 8326148 + return xbox_live_result(xbox_live_result()); + }); + + auto interop = interopResult.payload(); + auto jvm = interop->get_java_vm(); + JVM_CHECK_RETURN_TASK_RESULT_VOID(jvm, "java interop not initialized properly") + + auto interopTcuiClass = interop->get_tcui_interop_class(); + auto context = interop->get_context_object(); + + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(jvm, jniEnv); + jmethodID showAddFriendsMethodId = jniEnv->GetStaticMethodID(interopTcuiClass, "ShowAddFriends", "(Landroid/content/Context;)V"); + if (showAddFriendsMethodId != NULL) + { + jniEnv->CallStaticVoidMethod(interopTcuiClass, showAddFriendsMethodId, context); + } + + JNI_ERROR_CHECK(jniEnv); + + return task; +} + +pplx::task>> +title_callable_ui::show_player_picker_ui( + _In_ const string_t& promptDisplayText, + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount + ) +{ + return pplx::task_from_result>>(xbox::services::xbox_live_result>(xbox_live_error_code::unsupported)); +} + +pplx::task> +title_callable_ui::show_game_invite_ui( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionReference, + _In_ const string_t& contextStringId + ) +{ + return pplx::task_from_result>(xbox::services::xbox_live_result(xbox_live_error_code::unsupported)); +} + +pplx::task> +title_callable_ui::show_change_friend_relationship_ui( + _In_ const string_t& targetXboxUserId + ) +{ + return pplx::task_from_result>(xbox::services::xbox_live_result(xbox_live_error_code::unsupported)); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_END \ No newline at end of file diff --git a/Source/Services/Misc/Android/title_callable_ui_jni.h b/Source/Services/Misc/Android/title_callable_ui_jni.h new file mode 100644 index 00000000..b3e6e80c --- /dev/null +++ b/Source/Services/Misc/Android/title_callable_ui_jni.h @@ -0,0 +1,11 @@ +#pragma once +namespace xbox { namespace services { namespace system { +class title_callable_ui_internal +{ +public: + static void tcui_completed_callback(JNIEnv *, jclass, int errorCode); + static pplx::task_completion_event s_tcuiEventCompleted; + static bool s_isTcuiRunning; +}; +} } } + diff --git a/Source/Services/Misc/Android/title_callable_ui_static_glue.cpp b/Source/Services/Misc/Android/title_callable_ui_static_glue.cpp new file mode 100644 index 00000000..7272e4a2 --- /dev/null +++ b/Source/Services/Misc/Android/title_callable_ui_static_glue.cpp @@ -0,0 +1,38 @@ +#include "pch.h" +#include "Misc/Android/title_callable_ui_jni.h" +#include +#include "a/jni_utils.h" + +#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "XSAPI.Android", __VA_ARGS__)) +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "XSAPI.Android", __VA_ARGS__)) + +JNINativeMethod tcuiMethods[] = +{ + { + "tcui_completed_callback", + "(I)V", + (void*)&xbox::services::system::title_callable_ui_internal::tcui_completed_callback + }, +}; + +bool title_callable_ui_register_natives(JNIEnv *env, jobject clsLoader, jmethodID loadClass) +{ + jstring clsName = env->NewStringUTF("com/microsoft/xboxtcui/Interop"); + JNI_ERROR_CHECK(env); + jclass cls = (jclass)env->CallObjectMethod(clsLoader, loadClass, clsName); + env->DeleteLocalRef(clsName); + if (cls == NULL) { + LOGE("Failed to load class com/microsoft/xboxtcui/Interop"); + return false; + } + auto size = (sizeof tcuiMethods / sizeof *tcuiMethods); + + if (env->RegisterNatives(cls, tcuiMethods, size) != 0) { + LOGE("Failed to register native tcuiMethods"); + env->DeleteLocalRef(cls); + return false; + } + env->DeleteLocalRef(cls); + LOGD("Successfully registerered HttpCall tcuiMethods"); + return true; +} \ No newline at end of file diff --git a/Source/Services/Misc/UWP/title_callable_ui.cpp b/Source/Services/Misc/UWP/title_callable_ui.cpp new file mode 100644 index 00000000..f31fd043 --- /dev/null +++ b/Source/Services/Misc/UWP/title_callable_ui.cpp @@ -0,0 +1,719 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !UNIT_TEST_SERVICES +#define _APISET_TARGET_VERSION _APISET_TARGET_VERSION_WIN10_RS1 + +#include +#include +#include "xbox_system_factory.h" +#include "xsapi/title_callable_ui.h" + +#define XBOX_APP_PFN _T("Microsoft.XboxApp_8wekyb3d8bbwe") +#define XBOX_DEEPLINK_FRIEND_FINDER _T("xbox-friendfinder:facebook") +#define XBOX_DEEPLINK_TITLE_HUB _T("xbox-gamehub:?titleId=") +#define XBOX_DEEPLINK_USER_SETTINGS _T("xbox-settings:general") +// customize profile isn't implemented yet on win10 +#define XBOX_DEEPLINK_CUSTOMIZE_PROFILE _T("xbox-profile:customize") + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_BEGIN + +class tcui_context +{ +public: + tcui_context() : m_returnCode(S_OK) + { + } + + HRESULT wait() + { + m_event.wait(); + return m_returnCode; + } + + void set( HRESULT hr ) + { + m_returnCode = hr; + m_event.set(); + } + + void set(HRESULT hr, const std::vector& payload) + { + m_payload = payload; + m_returnCode = hr; + m_event.set(); + } + + std::vector payload() + { + return m_payload; + } + +private: + HRESULT m_returnCode; + std::vector m_payload; + +#if TV_API + pplx::details::event_impl m_event; +#else + pplx::event m_event; +#endif +}; + +void WINAPI UICompletionRoutine( + _In_ HRESULT returnCode, + _In_ void* context + ) +{ + tcui_context* uiContext = (tcui_context*)context; + if (uiContext != nullptr) + { + try + { + uiContext->set(returnCode); + } + catch (Platform::Exception^ exception) + { + HRESULT hr = (HRESULT)exception->HResult; + uiContext->set(hr); + } + catch (...) // everything else + { + HRESULT hr = xbox::services::utils::convert_exception_to_hresult(); + uiContext->set(hr); + } + } +} + +VOID WINAPI UIPlayerPickerUICompletionRoutine( + _In_ HRESULT returnCode, + _In_ void* context, + _In_reads_(selectedXuidsCount) const HSTRING* selectedXuids, + _In_ size_t selectedXuidsCount + ) +{ + tcui_context* uiContext = (tcui_context*)context; + if (uiContext != nullptr) + { + try + { + std::vector payload; + for (size_t i = 0; i < selectedXuidsCount; i++) + { + Platform::String^ str = ref new Platform::String(selectedXuids[i]); + payload.push_back(str->Data()); + } + + uiContext->set(returnCode, payload); + } + catch (Platform::Exception^ exception) + { + HRESULT hr = (HRESULT)exception->HResult; + uiContext->set(hr); + } + catch (...) // everything else + { + HRESULT hr = xbox::services::utils::convert_exception_to_hresult(); + uiContext->set(hr); + } + } +} + +pplx::task>> +title_callable_ui::show_player_picker_ui( + _In_ const string_t& promptDisplayText, + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif + ) +{ + auto task = pplx::create_task([ + promptDisplayText, + xboxUserIds, + preselectedXboxUserIds, + minSelectionCount, + maxSelectionCount +#if UWP_API + , user +#endif + ]() + { + tcui_context context; + Platform::String^ strPromptDisplayText = ref new Platform::String(promptDisplayText.c_str()); + std::vector strXboxUserIds; + std::vector strPreselectedXboxUserIds; + std::vector hXboxUserIds; + std::vector hPreselectedXboxUserIds; + + for (const auto& s : xboxUserIds) + { + Platform::String^ str = ref new Platform::String(s.c_str()); + strXboxUserIds.push_back(str); + hXboxUserIds.push_back( reinterpret_cast(str) ); + } + + for (const auto& s : preselectedXboxUserIds) + { + Platform::String^ str = ref new Platform::String(s.c_str()); + strPreselectedXboxUserIds.push_back(str); + hPreselectedXboxUserIds.push_back(reinterpret_cast(str)); + } + + HRESULT hr = S_OK; + if (hXboxUserIds.empty()) + { + hr = E_INVALIDARG; + } + else + { +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = ShowPlayerPickerUIForUser( + userAbi, + reinterpret_cast(strPromptDisplayText), + &hXboxUserIds[0], + hXboxUserIds.size(), + hPreselectedXboxUserIds.empty() ? nullptr : &hPreselectedXboxUserIds[0], + hPreselectedXboxUserIds.size(), + minSelectionCount, + maxSelectionCount, + UIPlayerPickerUICompletionRoutine, + static_cast(&context) + ); + } + else +#endif + { + hr = ShowPlayerPickerUI( + reinterpret_cast(strPromptDisplayText), + &hXboxUserIds[0], + hXboxUserIds.size(), + hPreselectedXboxUserIds.empty() ? nullptr : &hPreselectedXboxUserIds[0], + hPreselectedXboxUserIds.size(), + minSelectionCount, + maxSelectionCount, + UIPlayerPickerUICompletionRoutine, + static_cast(&context) + ); + } + } + if (SUCCEEDED(hr) || hr == E_PENDING) + { + hr = ProcessPendingGameUI(true); + if (SUCCEEDED(hr)) + { + hr = context.wait(); + } + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + + std::vector payload = context.payload(); + return xbox_live_result>(payload, errcode); + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task> +title_callable_ui::show_game_invite_ui( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionReference, + _In_ const string_t& contextStringId +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif + ) +{ + auto task = pplx::create_task([ + sessionReference, + contextStringId +#if UWP_API + , user +#endif + ]() + { + tcui_context context; + + Platform::String^ serviceConfigurationId = ref new Platform::String(sessionReference.service_configuration_id().c_str()); + Platform::String^ sessionTemplateName = ref new Platform::String(sessionReference.session_template_name().c_str()); + Platform::String^ sessionName = ref new Platform::String(sessionReference.session_name().c_str()); + Platform::String^ invitation = ref new Platform::String(contextStringId.c_str()); + + HRESULT hr = S_OK; +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = ShowGameInviteUIForUser( + userAbi, + reinterpret_cast(serviceConfigurationId), + reinterpret_cast(sessionTemplateName), + reinterpret_cast(sessionName), + reinterpret_cast(invitation), + UICompletionRoutine, + static_cast(&context) + ); + } + else +#endif + { + hr = ShowGameInviteUI( + reinterpret_cast(serviceConfigurationId), + reinterpret_cast(sessionTemplateName), + reinterpret_cast(sessionName), + reinterpret_cast(invitation), + UICompletionRoutine, + static_cast(&context) + ); + } + + if (SUCCEEDED(hr) || hr == E_PENDING) + { + hr = ProcessPendingGameUI(true); + if (SUCCEEDED(hr)) + { + hr = context.wait(); + } + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + return xbox_live_result(errcode); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_callable_ui::show_profile_card_ui( + _In_ const string_t& targetXboxUserId +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif +) +{ + auto task = pplx::create_task([targetXboxUserId +#if UWP_API + , user +#endif + ]() + { + tcui_context context; + Platform::String^ strTargetXboxUserId = ref new Platform::String(targetXboxUserId.c_str()); + + HRESULT hr = S_OK; +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = ShowProfileCardUIForUser( + userAbi, + reinterpret_cast(strTargetXboxUserId), + UICompletionRoutine, + static_cast(&context) + ); + } + else +#endif + { + hr = ShowProfileCardUI( + reinterpret_cast(strTargetXboxUserId), + UICompletionRoutine, + static_cast(&context) + ); + } + + if (SUCCEEDED(hr) || hr == E_PENDING) + { + hr = ProcessPendingGameUI(true); + if (SUCCEEDED(hr)) + { + hr = context.wait(); + } + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + return xbox_live_result(errcode); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_callable_ui::show_change_friend_relationship_ui( + _In_ const string_t& targetXboxUserId +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif + ) +{ + auto task = pplx::create_task([targetXboxUserId +#if UWP_API + , user +#endif + ]() + { + tcui_context context; + Platform::String^ strTargetXboxUserId = ref new Platform::String(targetXboxUserId.c_str()); + + HRESULT hr = S_OK; +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = ShowChangeFriendRelationshipUIForUser( + userAbi, + reinterpret_cast(strTargetXboxUserId), + UICompletionRoutine, + static_cast(&context) + ); + } + else +#endif + { + hr = ShowChangeFriendRelationshipUI( + reinterpret_cast(strTargetXboxUserId), + UICompletionRoutine, + static_cast(&context) + ); + } + + if (SUCCEEDED(hr) || hr == E_PENDING) + { + hr = ProcessPendingGameUI(true); + if (SUCCEEDED(hr)) + { + hr = context.wait(); + } + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + return xbox_live_result(errcode); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_callable_ui::show_title_achievements_ui( + _In_ uint32_t titleId +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif + ) +{ + auto task = pplx::create_task([titleId +#if UWP_API + , user +#endif + ]() + { + tcui_context context; + + HRESULT hr = S_OK; +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = ShowTitleAchievementsUIForUser( + userAbi, + titleId, + UICompletionRoutine, + static_cast(&context) + ); + } + else +#endif + { + hr = ShowTitleAchievementsUI( + titleId, + UICompletionRoutine, + static_cast(&context) + ); + } + + if (SUCCEEDED(hr) || hr == E_PENDING) + { + hr = ProcessPendingGameUI(true); + if (SUCCEEDED(hr)) + { + hr = context.wait(); + } + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + return xbox_live_result(errcode); + }); + + return utils::create_exception_free_task( + task + ); +} + +void +title_callable_ui::_Get_gaming_privilege_scope_policy( + _Out_ Platform::String^& scope, + _Out_ Platform::String^& policy + ) +{ + auto localConfig = xbox_system_factory::get_factory()->create_local_config(); + auth_config authConfig = auth_config( + localConfig->sandbox(), + localConfig->environment_prefix(), + localConfig->environment(), + localConfig->use_first_party_token() + ); + + scope = ref new Platform::String(authConfig.rps_ticket_service().c_str()); + policy = ref new Platform::String(authConfig.rps_ticket_policy().c_str()); +} + +xbox::services::xbox_live_result +title_callable_ui::check_gaming_privilege_silently( + _In_ gaming_privilege privilege +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif + ) +{ + Platform::String^ scope; + Platform::String^ policy; + _Get_gaming_privilege_scope_policy(scope, policy); + + BOOL hasPrivilege = FALSE; + + HRESULT hr = S_OK; +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = CheckGamingPrivilegeSilentlyForUser( + userAbi, + static_cast(privilege), + reinterpret_cast(scope), + reinterpret_cast(policy), + &hasPrivilege + ); + } + else +#endif + { + hr = CheckGamingPrivilegeSilently( + static_cast(privilege), + reinterpret_cast(scope), + reinterpret_cast(policy), + &hasPrivilege + ); + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + return xbox_live_result(hasPrivilege == TRUE, errcode); +} + +pplx::task> +title_callable_ui::check_gaming_privilege_with_ui( + _In_ gaming_privilege privilege, + _In_ string_t friendlyMessage +#if UWP_API + , _In_opt_ Windows::System::User^ user +#endif + ) +{ + auto task = pplx::create_task([privilege, friendlyMessage +#if UWP_API + , user +#endif + ]() + { + tcui_context context; + + Platform::String^ scope; + Platform::String^ policy; + _Get_gaming_privilege_scope_policy(scope, policy); + Platform::String^ friendlyMessageStr = ref new Platform::String(friendlyMessage.c_str()); + + BOOL hasPrivilege = FALSE; + HRESULT hr = S_OK; +#if UWP_API + if (user != nullptr) + { + ABI::Windows::System::IUser* userAbi = reinterpret_cast(user); + hr = CheckGamingPrivilegeWithUIForUser( + userAbi, + static_cast(privilege), + reinterpret_cast(scope), + reinterpret_cast(policy), + reinterpret_cast(friendlyMessageStr), + UICompletionRoutine, + static_cast(&context) + ); + } + else +#endif + { + hr = CheckGamingPrivilegeWithUI( + static_cast(privilege), + reinterpret_cast(scope), + reinterpret_cast(policy), + reinterpret_cast(friendlyMessageStr), + UICompletionRoutine, + static_cast(&context) + ); + } + if (SUCCEEDED(hr) || hr == E_PENDING) + { + hr = ProcessPendingGameUI(true); + if (SUCCEEDED(hr)) + { + hr = context.wait(); + if (SUCCEEDED(hr)) + { + hr = CheckGamingPrivilegeSilently( + static_cast(privilege), + reinterpret_cast(scope), + reinterpret_cast(policy), + &hasPrivilege + ); + } + } + } + + std::error_code errcode = std::make_error_code(static_cast(hr)); + return xbox_live_result(hasPrivilege == TRUE, errcode); + }); + + return utils::create_exception_free_task( + task + ); +} + +#if defined(XSAPI_U) +pplx::task> +title_callable_ui::show_friend_finder_ui() +{ + Platform::String^ urlStr = ref new Platform::String(XBOX_DEEPLINK_FRIEND_FINDER); + + Windows::Foundation::Uri^ uri = ref new Windows::Foundation::Uri(urlStr); + + Windows::System::LauncherOptions^ options = ref new Windows::System::LauncherOptions(); + options->TargetApplicationPackageFamilyName = XBOX_APP_PFN; + + auto task = pplx::create_task(Windows::System::Launcher::LaunchUriAsync(uri, options)) + .then([](bool result) + { + if (result) + { + return xbox_live_result(); + } + else + { + return xbox_live_result(xbox_live_error_code::runtime_error, "The Xbox App failed to launch"); + } + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_callable_ui::show_user_profile_ui( + _In_ const string_t& targetXboxUserId + ) +{ + // Show the profile card tcui + return show_profile_card_ui(targetXboxUserId); +} + +pplx::task> +title_callable_ui::show_title_hub_ui() +{ + auto localConfig = xbox_system_factory::get_factory()->create_local_config(); + uint32_t titleId = localConfig->title_id(); + + stringstream_t ss; + ss << XBOX_DEEPLINK_TITLE_HUB; + ss << titleId; + string_t link = ss.str(); + Platform::String^ urlStr = ref new Platform::String(link.c_str()); + + Windows::Foundation::Uri^ uri = ref new Windows::Foundation::Uri(urlStr); + + Windows::System::LauncherOptions^ options = ref new Windows::System::LauncherOptions(); + options->TargetApplicationPackageFamilyName = XBOX_APP_PFN; + + auto task = pplx::create_task(Windows::System::Launcher::LaunchUriAsync(uri, options)) + .then([](bool result) + { + if (result) + { + return xbox_live_result(); + } + else + { + return xbox_live_result(xbox_live_error_code::runtime_error, "The Xbox App failed to launch"); + } + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_callable_ui::show_user_settings_ui() +{ + Platform::String^ urlStr = ref new Platform::String(XBOX_DEEPLINK_USER_SETTINGS); + + Windows::Foundation::Uri^ uri = ref new Windows::Foundation::Uri(urlStr); + + Windows::System::LauncherOptions^ options = ref new Windows::System::LauncherOptions(); + options->TargetApplicationPackageFamilyName = XBOX_APP_PFN; + + auto task = pplx::create_task(Windows::System::Launcher::LaunchUriAsync(uri, options)) + .then([](bool result) + { + if (result) + { + return xbox_live_result(); + } + else + { + return xbox_live_result(xbox_live_error_code::runtime_error, "The Xbox App failed to launch"); + } + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_callable_ui::show_add_friends_ui() +{ + return pplx::task_from_result>(xbox::services::xbox_live_result(xbox_live_error_code::unsupported)); +} +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_END +#endif \ No newline at end of file diff --git a/Source/Services/Misc/Unix/notification_service_android.cpp b/Source/Services/Misc/Unix/notification_service_android.cpp new file mode 100644 index 00000000..c49e6633 --- /dev/null +++ b/Source/Services/Misc/Unix/notification_service_android.cpp @@ -0,0 +1,161 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/system.h" +#include "Misc/notification_service.h" +#include "xbox_system_factory.h" +#include "user_context.h" +#include "user_impl.h" +#include "a/java_interop.h" +#include "a/jni_utils.h" + +using namespace pplx; +using namespace xbox::services::system; + +JNINativeMethod notification_methods[] = +{ + { + "notificiation_registration_callback", + "(Ljava/lang/String;Z)V", + (void *)&xbox::services::notification::notification_service_android::notificiation_registration_callback + } +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_BEGIN + +notification_service_android::notification_service_android() : + m_isInitializing(false) +{ +} + +pplx::task_completion_event notification_service_android::s_notificationRegisterEvent; + +void notification_service_android::notificiation_registration_callback(JNIEnv* jniEnv, jclass, jstring notificationData, jboolean isCached) +{ + auto notiServiceAndroid = std::dynamic_pointer_cast(notification_service::get_notification_service_singleton()); + if (notificationData != NULL || !isCached) + { + auto notificationDataString = jniEnv->GetStringUTFChars(notificationData, 0); + if (!notiServiceAndroid->m_isInitializing) + { + notiServiceAndroid->subscribe_to_notifications_finish( + notificationDataString, + notiServiceAndroid + ); + } + else + { + LOG_WARN("notification registration for non refresh"); + s_notificationRegisterEvent.set(notificationDataString); + } + } + else + { + s_notificationRegisterEvent.set(_T("")); + } + +} + +pplx::task> notification_service_android::subscribe_to_notifications( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + std::shared_ptr interop = java_interop::get_java_interop_singleton(); + interop->register_natives(notification_methods); + + return notification_service::subscribe_to_notifications( + userContext, + xboxLiveContextSettings, + appConfig + ); +} + +pplx::task> +notification_service_android::subscribe_to_notifications() +{ + std::weak_ptr thisWeak = std::dynamic_pointer_cast(shared_from_this()); + return create_task([thisWeak]() + { + std::shared_ptr pThis(thisWeak.lock()); + if (pThis != nullptr) + { + auto javaInteropSingleton = java_interop::get_java_interop_singleton(); + auto javaVM = javaInteropSingleton->get_java_vm(); + if (javaVM == nullptr) + { + LOG_ERROR("java interop not initialized properly"); + return xbox_live_result(xbox_live_error_code::runtime_error, "java interop not initialized properly"); + } + JNIEnv* jniEnv; + JNI_ATTACH_THREAD(javaVM, jniEnv); + + auto marketActivityClass = javaInteropSingleton->get_market_activity_class(); + jmethodID registerWithGNS = jniEnv->GetStaticMethodID(marketActivityClass, "RegisterWithGNS", "(Landroid/content/Context;)V"); + if (registerWithGNS != NULL) + { + s_notificationRegisterEvent = pplx::task_completion_event(); + pThis->m_isInitializing = true; + jniEnv->CallStaticVoidMethod(marketActivityClass, registerWithGNS, javaInteropSingleton->get_context_object()); + if (jniEnv->ExceptionCheck()) + { + LOG_ERROR("error intialization gns"); + return xbox_live_result(xbox_live_error_code::runtime_error, "gns init error"); + } + + return create_task(s_notificationRegisterEvent) + .then([pThis](string_t registrationToken) + { + return pThis->subscribe_to_notifications_finish(registrationToken, pThis); + }).get(); + } + else + { + LOG_ERROR("registerWithGNS method not found"); + } + } + + return xbox_live_result(xbox_live_error_code::runtime_error); + }); +} + +pplx::task> +notification_service_android::subscribe_to_notifications_finish( + _In_ const string_t& registrationToken, + _In_ const std::shared_ptr& pThis + ) +{ + pThis->m_isInitializing = false; + if (registrationToken.empty()) + { + LOG_ERROR("gns registration failed or was already cached"); + return pplx::task_from_result>(xbox_live_result(xbox_live_error_code::runtime_error, "gns registration failed or was already cached")); + } + + auto endpointIdCache = xbox_system_factory::get_factory()->create_local_config()->get_value_from_local_storage(pThis->ENDPOINT_ID_CACHE_NAME); + if (!endpointIdCache.empty()) + { + pThis->m_endpointId = endpointIdCache; + pThis->unsubscribe_from_notifications(endpointIdCache).get(); + } + + std::vector notificationFilterList = { { notification_filter_source_type::multiplayer, 1 } }; + return pThis->subscribe_to_notifications_helper( + utils::create_guid(true), + registrationToken, + _T("Android"), + _T("AndroidDevice"), + _T("XSAPI_A"), + notificationFilterList + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_END \ No newline at end of file diff --git a/Source/Services/Misc/Unix/notification_service_i.mm b/Source/Services/Misc/Unix/notification_service_i.mm new file mode 100644 index 00000000..db1378f3 --- /dev/null +++ b/Source/Services/Misc/Unix/notification_service_i.mm @@ -0,0 +1,62 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/system.h" +#include "notification_service.h" +#include "xbox_system_factory.h" +#include "user_context.h" +#include "user_impl.h" +#import "XBLiOSGlobalState.h" + +using namespace pplx; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_BEGIN + +pplx::task> +notification_service_ios::subscribe_to_notifications() +{ + string_t endpointIdCache = xbox_system_factory::get_factory()->create_local_config()->get_value_from_local_storage(ENDPOINT_ID_CACHE_NAME); + if (!endpointIdCache.empty()) + { + unsubscribe_from_notifications(endpointIdCache).get(); + } + string_t registrationToken = [XBLiOSGlobalState notificationRegistrationToken]; + if(registrationToken.empty()) + { + LOG_INFO("No APNS device token"); + return pplx::task_from_result(xbox_live_result(xbox_live_error_code::runtime_error, "No APNS device token")); + } + std::weak_ptr thisWeak = std::dynamic_pointer_cast(shared_from_this()); + return create_task([thisWeak, registrationToken]() + { + std::shared_ptr pThis = thisWeak.lock(); + if (pThis != nullptr) + { + std::vector notificationFilterList; + notification_filter notificationFilter = { notification_filter_source_type::multiplayer, 1 }; + notificationFilterList.push_back(notificationFilter); + + return pThis->subscribe_to_notifications_helper(utils::create_guid(true), + registrationToken, + _T("iOS"), + _T("iOSDevice"), + _T("XSAPI_I"), + notificationFilterList + ).get(); + } + else + { + return xbox_live_result(xbox_live_error_code::runtime_error); + } + }); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.cpp new file mode 100644 index 00000000..37c5ee45 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.cpp @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchBroadcast_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchBroadcast::ContextualSearchBroadcast( + _In_ xbox::services::contextual_search::contextual_search_broadcast cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_currentStats = ref new Platform::Collections::Map(); + for (const auto& stat : m_cppObj.current_stats()) + { + m_currentStats->Insert(ref new Platform::String(stat.first.c_str()), ref new Platform::String(stat.second.c_str())); + } +} + +Windows::Foundation::Collections::IMapView^ +ContextualSearchBroadcast::CurrentStats::get() +{ + return m_currentStats->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.h new file mode 100644 index 00000000..9a04488e --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchBroadcast_WinRT.h @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Contains information about a contextual search broadcast. +public ref class ContextualSearchBroadcast sealed +{ +public: + /// + /// The Xbox user ID of the player. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// Returns the broadcast provider, for example "Twitch". + /// This is leveraged to enable differing logic to handle content from different providers + /// + DEFINE_PROP_GET_STR_OBJ(Provider, provider); + + /// + /// The identifier of the broadcaster on the provider. This is leveraged to created deeplinks to the broadcast. + /// In the example of Twitch, this is the Twitch user id. + /// + DEFINE_PROP_GET_STR_OBJ(BroadcasterIdFromProvider, broadcaster_id_from_provider); + + /// + /// The current number of viewers in the broadcast, per the last update from Presence. + /// + DEFINE_PROP_GET_OBJ(Viewers, viewers, uint64); + + /// + /// The date value of when the broadcast started + /// + DEFINE_PROP_GET_DATETIME_OBJ(StartedDate, started_date); + + /// + /// The current stats the title has configured for Contextual Search and what their current values are. + /// Additional information on how to surface the information is contained in the configuration handler. + /// + property Windows::Foundation::Collections::IMapView^ CurrentStats + { + Windows::Foundation::Collections::IMapView^ get(); + } + +internal: + ContextualSearchBroadcast( + _In_ xbox::services::contextual_search::contextual_search_broadcast cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_broadcast m_cppObj; + Platform::Collections::Map^ m_currentStats; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.cpp new file mode 100644 index 00000000..5ef59dfb --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.cpp @@ -0,0 +1,42 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchConfiguredStat_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchConfiguredStat::ContextualSearchConfiguredStat( + _In_ xbox::services::contextual_search::contextual_search_configured_stat cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_valueToDisplayName = ref new Platform::Collections::Map(); + for (const auto& value : m_cppObj.value_to_display_name_map()) + { + m_valueToDisplayName->Insert(ref new Platform::String(value.first.c_str()), ref new Platform::String(value.second.c_str())); + } +} + +Windows::Foundation::Collections::IMapView^ +ContextualSearchConfiguredStat::ValueToDisplayName::get() +{ + return m_valueToDisplayName->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END + diff --git a/Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.h new file mode 100644 index 00000000..66cde278 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchConfiguredStat_WinRT.h @@ -0,0 +1,84 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "ContextualSearchStatVisibility_WinRT.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Contains information about a contextual search stat. +public ref class ContextualSearchConfiguredStat sealed +{ +public: + /// + /// The actual name of the configured stat. This is what you will use as a parameter in the search API. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + + /// + /// The data type of the stat. It should align with the values you are passing for the stat into the Search API. + /// + DEFINE_PROP_GET_STR_OBJ(DataType, data_type); + + /// + /// The visibility of the stat + /// + DEFINE_PROP_GET_ENUM_OBJ(Visibility, visibility, ContextualSearchStatVisibility); + + /// + /// This is the localizable string exposed to the end user. Depending on the language / culture you + /// pass up in the header, you will get a localized version of this string. + /// + DEFINE_PROP_GET_STR_OBJ(DisplayName, display_name); + + /// + /// Boolean on whether you can use this stat in a filter + /// + DEFINE_PROP_GET_OBJ(CanBeFiltered, can_be_filtered, bool); + + /// + /// Boolean on whether you can make sort queries + /// + DEFINE_PROP_GET_OBJ(CanBeSorted, can_be_sorted, bool); + + /// + /// How this Stat should be represented, as either a Set, Defined Range, or Undefined Range + /// + DEFINE_PROP_GET_ENUM_OBJ(DisplayType, display_type, ContextualSearchStatVisibility); + + /// + /// If the representation type is set, this contains a map to convert values to display names + /// + property Windows::Foundation::Collections::IMapView^ ValueToDisplayName + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// If the representation type is defined range, this is the min range + /// + DEFINE_PROP_GET_OBJ(RangeMin, range_min, uint64); + + /// + /// If the representation type is defined range, this is the max range + /// + DEFINE_PROP_GET_OBJ(RangeMax, range_max, uint64); + +internal: + ContextualSearchConfiguredStat( + _In_ xbox::services::contextual_search::contextual_search_configured_stat cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_configured_stat m_cppObj; + Platform::Collections::Map^ m_valueToDisplayName; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchFilterOperator_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchFilterOperator_WinRT.h new file mode 100644 index 00000000..3e1075cc --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchFilterOperator_WinRT.h @@ -0,0 +1,37 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Enumerates the operators of a contextual search filter. +public enum class ContextualSearchFilterOperator +{ + /// Matches if filter name is equals to filter value. + Equal = xbox::services::contextual_search::contextual_search_filter_operator::equal, + + /// Matches if filter name is not equal to filter value. + NotEqual = xbox::services::contextual_search::contextual_search_filter_operator::not_equal, + + /// Matches if filter name is greater than filter value. + GreaterThan = xbox::services::contextual_search::contextual_search_filter_operator::greater_than, + + /// Matches if filter name is greater than or equal to filter value. + GreaterThanOrEqual = xbox::services::contextual_search::contextual_search_filter_operator::greater_than_or_equal, + + /// Matches if filter name is less than filter value. + LessThan = xbox::services::contextual_search::contextual_search_filter_operator::less_than, + + /// Matches if filter name is less than or equal to filter value. + LessThanOrEqual = xbox::services::contextual_search::contextual_search_filter_operator::less_than_or_equal +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.cpp new file mode 100644 index 00000000..7092f5bb --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchGameClipStat_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchGameClipStat::ContextualSearchGameClipStat( + _In_ xbox::services::contextual_search::contextual_search_game_clip_stat cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.h new file mode 100644 index 00000000..77c748b4 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipStat_WinRT.h @@ -0,0 +1,57 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Contains information about a contextual search game clip stat. +public ref class ContextualSearchGameClipStat sealed +{ +public: + /// + /// Name of the stat + /// + DEFINE_PROP_GET_STR_OBJ(Name, stat_name); + + /// + /// Value of the stat for string stats and integer stats representing a set value. + /// If the stat changed during the clip, the field will have multiple values separated by a comma. + /// If the "value" field is present, "min", "max" and "delta" fields will not be present. + /// + DEFINE_PROP_GET_STR_OBJ(Value, value); + + /// + /// The minimum value the stat had during the recording of the game clip. + /// If the "min" field is present, the "value" field will not be present. + /// + DEFINE_PROP_GET_STR_OBJ(MinValue, min_value); + + /// + /// The maximum value the stat had during the recording of the game clip. + /// If the "max" field is present, the "value" field will not be present. + /// + DEFINE_PROP_GET_STR_OBJ(MaxValue, max_value); + + /// + /// "max"–"min". If the delta field is present, the "value" field will not be present. + /// + DEFINE_PROP_GET_STR_OBJ(DeltaValue, delta_value); + +internal: + ContextualSearchGameClipStat( + _In_ xbox::services::contextual_search::contextual_search_game_clip_stat cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_game_clip_stat m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.cpp new file mode 100644 index 00000000..57883015 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchGameClipThumbnail_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchGameClipThumbnail::ContextualSearchGameClipThumbnail( + _In_ xbox::services::contextual_search::contextual_search_game_clip_thumbnail cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.h new file mode 100644 index 00000000..3b485733 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipThumbnail_WinRT.h @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Describes the type of thumbnail +public enum class ContextualSearchGameClipThumbnailType +{ + /// Thumbnail type is not specified. This is an invalid value in most cases. + None = xbox::services::contextual_search::contextual_search_game_clip_thumbnail_type::none, + + /// Specifies a small thumbnail. Small is 370 pixels in height by 208 pixels in width. + SmallThumbnail = xbox::services::contextual_search::contextual_search_game_clip_thumbnail_type::small_thumbnail, + + /// Specifies a large thumbnail. Large is 754 pixels in height by 424 pixels in width. + LargeThumbnail = xbox::services::contextual_search::contextual_search_game_clip_thumbnail_type::large_thumbnail +}; + +/// Contains information about a contextual search game clip thumbnail. +public ref class ContextualSearchGameClipThumbnail sealed +{ +public: + /// + /// The URI for the thumbnail image. + /// + DEFINE_PROP_GET_URI_OBJ(Url, url); + + /// + /// The total file size of the thumbnail image. + /// + DEFINE_PROP_GET_OBJ(FileSize, file_size, uint64); + + /// + /// The type of thumbnail image. + /// + DEFINE_PROP_GET_ENUM_OBJ(ThumbnailType, thumbnail_type, Microsoft::Xbox::Services::ContextualSearch::ContextualSearchGameClipThumbnailType); + +internal: + ContextualSearchGameClipThumbnail( + _In_ xbox::services::contextual_search::contextual_search_game_clip_thumbnail cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_game_clip_thumbnail m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.cpp new file mode 100644 index 00000000..b95bfd53 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchGameClipUriInfo_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchGameClipUriInfo::ContextualSearchGameClipUriInfo( + _In_ xbox::services::contextual_search::contextual_search_game_clip_uri_info cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.h new file mode 100644 index 00000000..b30acc53 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipUriInfo_WinRT.h @@ -0,0 +1,68 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Describes the type of game clip URI. +public enum class ContextualSearchGameClipUriType +{ + /// Game clip URI type is not known or not set. + None = xbox::services::contextual_search::contextual_search_game_clip_uri_type::none, + + /// Game clip URI is the location of the original game clip in unprocessed form. + Original = xbox::services::contextual_search::contextual_search_game_clip_uri_type::original, + + /// Game clip URI is the location of the clip available for download. + Download = xbox::services::contextual_search::contextual_search_game_clip_uri_type::download, + + /// Game clip URI is the IIS Smooth Streaming URL(manifest pointer). + SmoothStreaming = xbox::services::contextual_search::contextual_search_game_clip_uri_type::smooth_streaming, + + /// Game clip URI is the Apple HTTP Live Streaming URL. + HttpLiveStreaming = xbox::services::contextual_search::contextual_search_game_clip_uri_type::http_live_streaming +}; + +/// Contains information about a contextual search game clips uri info. +public ref class ContextualSearchGameClipUriInfo sealed +{ +public: + /// + /// The URI to the location of the video asset. + /// + DEFINE_PROP_GET_URI_OBJ(Url, url); + + /// + /// The file size at the location of the URL for formats that are downloaded + /// This is 0 for streaming formats + /// + DEFINE_PROP_GET_OBJ(FileSize, file_size, uint64); + + /// + /// Specifies the type of the URI. + /// + DEFINE_PROP_GET_ENUM_OBJ(UriType, uri_type, Microsoft::Xbox::Services::ContextualSearch::ContextualSearchGameClipUriType); + + /// + /// The expiration time of the URI that is included in this response. + /// + DEFINE_PROP_GET_DATETIME_OBJ(Expiration, expiration); + +internal: + ContextualSearchGameClipUriInfo( + _In_ xbox::services::contextual_search::contextual_search_game_clip_uri_info cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_game_clip_uri_info m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.cpp new file mode 100644 index 00000000..796b7296 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.cpp @@ -0,0 +1,52 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchGameClip_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchGameClip::ContextualSearchGameClip( + _In_ xbox::services::contextual_search::contextual_search_game_clip cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_thumbnails = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.thumbnails()); + m_uriInfos = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.game_clip_uris()); + m_stats = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.stats()); +} + +Windows::Foundation::Collections::IVectorView^ +ContextualSearchGameClip::GameClipUris::get() +{ + return m_uriInfos->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +ContextualSearchGameClip::Thumbnails::get() +{ + return m_thumbnails->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +ContextualSearchGameClip::Stats::get() +{ + return m_stats->GetView(); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.h new file mode 100644 index 00000000..42a9f6f6 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClip_WinRT.h @@ -0,0 +1,102 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" +#include "ContextualSearchGameClipThumbnail_WinRT.h" +#include "ContextualSearchGameClipUriInfo_WinRT.h" +#include "ContextualSearchGameClipStat_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Describes the type of game clip +public enum class ContextualSearchGameClipType +{ + /// Game clip type is unknown or not set. (not valid for upload or queries) + None = xbox::services::contextual_search::contextual_search_game_clip_type::none, + + /// Game clip is initiated by a developer / title + DeveloperInitiated = xbox::services::contextual_search::contextual_search_game_clip_type::developer_initiated, + + /// Game clip is an achievement type + Achievement = xbox::services::contextual_search::contextual_search_game_clip_type::achievement, + + /// Game clip is a user-generated type + UserGenerated = xbox::services::contextual_search::contextual_search_game_clip_type::user_generated +}; + +/// Contains information about a contextual search game clip. +public ref class ContextualSearchGameClip sealed +{ +public: + /// + /// The localized version of the clip’s name based on the input locale of the request as looked up from the title management system. + /// + DEFINE_PROP_GET_STR_OBJ(ClipName, clip_name); + + /// + /// Specifies the duration of the game clip in seconds. + /// + DEFINE_PROP_GET_OBJ(DurationInSeconds, duration_in_seconds, uint64); + + /// + /// The ID assigned to the game clip. + /// + DEFINE_PROP_GET_STR_OBJ(GameClipId, game_clip_id); + + /// + /// the locale the game clip was created under. + /// + DEFINE_PROP_GET_STR_OBJ(GameClipLocale, game_clip_locale); + + /// + /// Array of playback options for this clip. + /// + property Windows::Foundation::Collections::IVectorView^ GameClipUris { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// Array of thumbnails for this clip. + /// + property Windows::Foundation::Collections::IVectorView^ Thumbnails { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The type of clip. Can be multiple values and if so will be comma delimited. + /// + DEFINE_PROP_GET_ENUM_OBJ(GameClipType, game_clip_type, Microsoft::Xbox::Services::ContextualSearch::ContextualSearchGameClipType); + + /// + /// The number of views associated with a game clip. + /// + DEFINE_PROP_GET_OBJ(Views, views, uint64); + + /// + /// The XUID of the owner of the game clip + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// Stats associated with the game clip. + /// This contains the initial values of stats at the start of the game clip and any new value a stat had during the recording of the game clip. + /// Note that these are only the stats configured for intermedia in the title configuration. + /// + property Windows::Foundation::Collections::IVectorView^ Stats { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + ContextualSearchGameClip( + _In_ xbox::services::contextual_search::contextual_search_game_clip cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_game_clip m_cppObj; + Windows::Foundation::Collections::IVector^ m_thumbnails; + Windows::Foundation::Collections::IVector^ m_uriInfos; + Windows::Foundation::Collections::IVector^ m_stats; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.cpp new file mode 100644 index 00000000..e3d44ed5 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.cpp @@ -0,0 +1,53 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchGameClipsResult_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchGameClipsResult::ContextualSearchGameClipsResult( + _In_ xbox::services::contextual_search::contextual_search_game_clips_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_items = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.items()); +} + +Windows::Foundation::Collections::IVectorView^ +ContextualSearchGameClipsResult::Items::get() +{ + return m_items->GetView(); +} + +IAsyncOperation^ +ContextualSearchGameClipsResult::GetNextAsync( + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new ContextualSearchGameClipsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.h new file mode 100644 index 00000000..a4b60c66 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchGameClipsResult_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" +#include "ContextualSearchGameClip_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Contains information about a contextual search game clips result. +public ref class ContextualSearchGameClipsResult sealed +{ +public: + /// + /// Returns the next page of game clips. + /// + /// The maximum number of game clips the result can contain. Pass 0 to attempt to retrieve the top 100 items. + Windows::Foundation::IAsyncOperation^ GetNextAsync( + _In_ uint32 maxItems + ); + + /// + /// Array of game clips returned. + /// + property Windows::Foundation::Collections::IVectorView^ Items { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + ContextualSearchGameClipsResult( + _In_ xbox::services::contextual_search::contextual_search_game_clips_result cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_game_clips_result m_cppObj; + Windows::Foundation::Collections::IVector^ m_items; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchService_WinRT.cpp b/Source/Services/Misc/WinRT/ContextualSearchService_WinRT.cpp new file mode 100644 index 00000000..24b113f7 --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchService_WinRT.cpp @@ -0,0 +1,186 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ContextualSearchConfiguredStat_WinRT.h" +#include "ContextualSearchBroadcast_WinRT.h" +#include "ContextualSearchService_WinRT.h" + +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace pplx; +using namespace xbox::services; +using namespace xbox::services::contextual_search; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +ContextualSearchService::ContextualSearchService( + _In_ xbox::services::contextual_search::contextual_search_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::IAsyncOperation^>^ +ContextualSearchService::GetConfigurationAsync( + _In_ uint32 titleId + ) +{ + auto task = m_cppObj.get_configuration( + titleId + ) + .then([](xbox_live_result> cppResult) + { + THROW_IF_ERR(cppResult); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(cppResult.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^>^ +ContextualSearchService::GetBroadcastsAsync( + _In_ uint32 titleId + ) +{ + auto task = m_cppObj.get_broadcasts( + titleId + ) + .then([](xbox_live_result> cppResult) + { + THROW_IF_ERR(cppResult); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(cppResult.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^>^ +ContextualSearchService::GetBroadcastsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ searchQuery + ) +{ + auto task = m_cppObj.get_broadcasts( + titleId, + skipItems, + maxItems, + STRING_T_FROM_PLATFORM_STRING(orderByStatName), + orderAscending, + STRING_T_FROM_PLATFORM_STRING(searchQuery) + ) + .then([](xbox_live_result> cppResult) + { + THROW_IF_ERR(cppResult); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(cppResult.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^>^ +ContextualSearchService::GetBroadcastsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ filterStatName, + _In_ ContextualSearchFilterOperator filterOperator, + _In_ Platform::String^ filterStatValue + ) +{ + auto task = m_cppObj.get_broadcasts( + titleId, + skipItems, + maxItems, + STRING_T_FROM_PLATFORM_STRING(orderByStatName), + orderAscending, + STRING_T_FROM_PLATFORM_STRING(filterStatName), + static_cast(filterOperator), + STRING_T_FROM_PLATFORM_STRING(filterStatValue) + ) + .then([](xbox_live_result> cppResult) + { + THROW_IF_ERR(cppResult); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(cppResult.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +ContextualSearchService::GetGameClipsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ filterStatName, + _In_ ContextualSearchFilterOperator filterOperator, + _In_ Platform::String^ filterStatValue + ) +{ + auto task = m_cppObj.get_game_clips( + titleId, + skipItems, + maxItems, + STRING_T_FROM_PLATFORM_STRING(orderByStatName), + orderAscending, + STRING_T_FROM_PLATFORM_STRING(filterStatName), + static_cast(filterOperator), + STRING_T_FROM_PLATFORM_STRING(filterStatValue) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new ContextualSearchGameClipsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +ContextualSearchService::GetGameClipsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ searchQuery + ) +{ + auto task = m_cppObj.get_game_clips( + titleId, + skipItems, + maxItems, + STRING_T_FROM_PLATFORM_STRING(orderByStatName), + orderAscending, + STRING_T_FROM_PLATFORM_STRING(searchQuery) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new ContextualSearchGameClipsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END + + diff --git a/Source/Services/Misc/WinRT/ContextualSearchService_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchService_WinRT.h new file mode 100644 index 00000000..f38732ed --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchService_WinRT.h @@ -0,0 +1,187 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/contextual_search_service.h" +#include "ContextualSearchConfiguredStat_WinRT.h" +#include "ContextualSearchFilterOperator_WinRT.h" +#include "ContextualSearchStatDisplayType_WinRT.h" +#include "ContextualSearchStatVisibility_WinRT.h" +#include "ContextualSearchGameClip_WinRT.h" +#include "ContextualSearchGameClipsResult_WinRT.h" +#include "ContextualSearchGameClipStat_WinRT.h" +#include "ContextualSearchGameClipUriInfo_WinRT.h" +#include "ContextualSearchGameClipThumbnail_WinRT.h" +#include "ContextualSearchBroadcast_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// +/// Provides methods to perform Xbox Live contextual search. +/// +public ref class ContextualSearchService sealed +{ +public: + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast + /// + /// The title ID. + /// + /// The result contains information to hydrate a UI. + /// + /// Calls V1 GET /titles/{titleid}/configuration + Windows::Foundation::IAsyncOperation^>^ GetConfigurationAsync( + _In_ uint32 titleId + ); + + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast. Defaults to the top 100 broadcasts ordered by viewers descending with no filter + /// + /// The title ID. + /// + /// The result is a contextual_search_broadcasts_result object which contains information about broadcasts. + /// + /// Calls V1 GET /titles/{titleId}/broadcasts + Windows::Foundation::IAsyncOperation^>^ GetBroadcastsAsync( + _In_ uint32 titleId + ); + + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast + /// + /// The title ID. + /// The number of broadcasts to skip. + /// The maximum number of broadcasts the result can contain. Pass 0 to attempt to retrieve the top 100 items. + /// This specifies a stat to sort the broadcasts by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// This specifies a OData Filter Expressions string that specifies the stats to filter on. + /// For example "stats:maptype eq 1" means filtering by the stat "maptype" to the value 1. + /// + /// The result is a contextual_search_broadcasts_result object which contains information about broadcasts. + /// + /// Calls V1 GET /titles/{titleId}/broadcasts + Windows::Foundation::IAsyncOperation^>^ GetBroadcastsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ searchQuery + ); + + /// + /// Get information to hydrate a UI for the end user to choose what data from a game they want to use + /// to filter or sort the broadcast + /// + /// The title ID. + /// The number of broadcasts to skip. + /// The maximum number of broadcasts the result can contain. Pass 0 to attempt to retrieve the top 100 items. + /// This specifies a stat to sort the broadcasts by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// This specifies the stat to filter on. Pass empty string for no filter + /// This specifies operator to apply for the filter. + /// This specifies the value to filter on. Pass empty string for no filter + /// + /// The result is a contextual_search_broadcasts_result object which contains information about broadcasts. + /// + /// Calls V1 GET /titles/{titleId}/broadcasts + Windows::Foundation::IAsyncOperation^>^ GetBroadcastsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ filterStatName, + _In_ ContextualSearchFilterOperator filterOperator, + _In_ Platform::String^ filterStatValue + ); + + /// + /// Get information to hydrate a UI that allows end users to filter or sort game clips + /// + /// The title ID. + /// The number of game clips to skip. + /// The maximum number of game clips the result can contain. Pass 0 to attempt to retrieve the top 100 items. + /// This specifies a stat to sort the game clips by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// This specifies the stat to filter on. Pass empty string for no filter. For example, "gametype.value". + /// The "value" property is only available for string stats and integer stats. + /// The "min", "max" and "delta" properties are only available for double stats and integer stats. + /// + /// This specifies operator to apply for the filter. + /// This specifies the value to filter on. The stat properties that can be used to search with are 'value', 'min', 'max', and 'delta'. Pass empty string for no filter + /// + /// The result is an object which contains information about game clips. + /// + /// Calls V1 GET /titles/{titleId}/gameclips + Windows::Foundation::IAsyncOperation^ GetGameClipsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ filterStatName, + _In_ ContextualSearchFilterOperator filterOperator, + _In_ Platform::String^ filterStatValue + ); + + /// + /// Get information to hydrate a UI that allows end users to filter or sort game clips + /// + /// The title ID. + /// The number of game clips to skip. + /// The maximum number of game clips the result can contain. Pass 0 to attempt to retrieve the top 100 items. + /// This specifies a stat to sort the game clips by. Pass empty string to default to ordering by viewers descending + /// Pass true to order ascending, false to order descending + /// + /// The search query. + /// The query syntax is an OData like syntax with only the following operators supported EQ, NE, GE, GT, LE and LT along with the logical operators of AND and OR. You can also use grouping operator ‘()’. The stat properties that can be used to search with are "value", "min", "max", and "delta". + /// + /// Example 1: + /// To search for game clips during which the "gametype" stat had a value of 1 use + /// "stats:gametype.value eq 1" + /// + /// Example 2: + /// To search for game clips during which the "rank" stat jumped more than 2. + /// "stats:rank.value gt 2" + /// + /// Example 3: + /// To search for game clips during which the "rank" stat jumped more than 2 and the "gametype" stat had a value of 1 use + /// "stats:rank.value gt 2 and stat:gametype.value eq 1" + /// + /// Note: + /// - The "value" property is only available for string stats and integer stats that are used with a Set. + /// - The "min", "max" and "delta" properties are only available for double stats and integer stats that are not used with a Set. + /// + /// + /// The result is an object which contains information about game clips. + /// + /// Calls V1 GET /titles/{titleId}/gameclips + Windows::Foundation::IAsyncOperation^ GetGameClipsAsync( + _In_ uint32 titleId, + _In_ uint32 skipItems, + _In_ uint32 maxItems, + _In_ Platform::String^ orderByStatName, + _In_ bool orderAscending, + _In_ Platform::String^ searchQuery + ); + +internal: + ContextualSearchService( + _In_ xbox::services::contextual_search::contextual_search_service cppObj + ); + +private: + xbox::services::contextual_search::contextual_search_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchStatDisplayType_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchStatDisplayType_WinRT.h new file mode 100644 index 00000000..bfda0f5c --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchStatDisplayType_WinRT.h @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Enumerates the display type of a contextual search statistic. +public enum class ContextualSearchStatDisplayType +{ + /// Unknown type. + Unknown = xbox::services::contextual_search::contextual_search_stat_display_type::unknown, + + /// This stat should be displayed as a undefined range. + UndefinedRange = xbox::services::contextual_search::contextual_search_stat_display_type::undefined_range, + + /// This stat should be displayed as a defined range. + DefinedRange = xbox::services::contextual_search::contextual_search_stat_display_type::defined_range, + + /// This stat should be displayed using the value_to_display_name_map. + Set = xbox::services::contextual_search::contextual_search_stat_display_type::set +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/ContextualSearchStatVisibility_WinRT.h b/Source/Services/Misc/WinRT/ContextualSearchStatVisibility_WinRT.h new file mode 100644 index 00000000..de4a40bc --- /dev/null +++ b/Source/Services/Misc/WinRT/ContextualSearchStatVisibility_WinRT.h @@ -0,0 +1,29 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_BEGIN + +/// Enumerates the visibility of a contextual search statistic. +public enum class ContextualSearchStatVisibility +{ + /// Unknown visibility. + Unknown = xbox::services::contextual_search::contextual_search_stat_visibility::unknown, + + /// This is important, as third party applications like Twitch will only be able to view OPEN stats. + PublicVisibility = xbox::services::contextual_search::contextual_search_stat_visibility::public_visibility, + + /// If a stat is private, only the title itself, or a companion application that has special privileges, can access this information. + PrivateVisibility = xbox::services::contextual_search::contextual_search_stat_visibility::private_visibility +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_END diff --git a/Source/Services/Misc/WinRT/StringService_WinRT.cpp b/Source/Services/Misc/WinRT/StringService_WinRT.cpp new file mode 100644 index 00000000..48509e1e --- /dev/null +++ b/Source/Services/Misc/WinRT/StringService_WinRT.cpp @@ -0,0 +1,73 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "StringService_WinRT.h" +#include "VerifyStringResult_WinRT.h" +#include "Utils_WinRT.h" + +using namespace pplx; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace Platform::Collections; +using namespace xbox::services::system; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_BEGIN + +IAsyncOperation^ +StringService::VerifyStringAsync( + _In_ Platform::String^ stringToVerify + ) +{ + auto task = m_cppObj.verify_string( + STRING_T_FROM_PLATFORM_STRING(stringToVerify) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + return ref new VerifyStringResult(result.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +StringService::VerifyStringsAsync( + _In_ IVectorView^ stringsToVerify +) +{ + auto task = m_cppObj.verify_strings( + UtilsWinRT::CovertVectorViewToStdVectorString(stringsToVerify) + ) + .then([](xbox_live_result> results) + { + THROW_IF_ERR(results); + auto responseVector = ref new Vector(); + for (const auto& result : results.payload()) + { + responseVector->Append(ref new VerifyStringResult(result)); + } + return responseVector->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + + +StringService::StringService( + xbox::services::system::string_service cppObj + ): + m_cppObj(std::move(cppObj)) +{ +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_END diff --git a/Source/Services/Misc/WinRT/StringService_WinRT.h b/Source/Services/Misc/WinRT/StringService_WinRT.h new file mode 100644 index 00000000..7fc86c3a --- /dev/null +++ b/Source/Services/Misc/WinRT/StringService_WinRT.h @@ -0,0 +1,58 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/system.h" +#include "VerifyStringResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_BEGIN + +/// +/// Provides methods to validate a string for use with Xbox Live. +/// +public ref class StringService sealed +{ +public: + /// + /// Verifies if a string contains acceptable text for use with Xbox Live. + /// + /// The string to verify. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The result is a VerifyStringResult object which indicates if the string contains unacceptable text. + /// + /// Calls V2 GET /system/strings/validate + Windows::Foundation::IAsyncOperation^ VerifyStringAsync( + _In_ Platform::String^ stringToVerify + ); + + /// + /// Verifies a collection of strings to see if each string contains acceptable text for use with Xbox Live. + /// + /// The collection of strings to verify. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The result is a collection of VerifyStringResult objects which indicate if the strings contain unacceptable text. + /// + /// Calls V2 GET /system/strings/validate + Windows::Foundation::IAsyncOperation^>^ VerifyStringsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ stringsToVerify + ); + +internal: + StringService( + xbox::services::system::string_service cppObj + ); + +private: + xbox::services::system::string_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_END diff --git a/Source/Services/Misc/WinRT/TitleCallableUI_WinRT.cpp b/Source/Services/Misc/WinRT/TitleCallableUI_WinRT.cpp new file mode 100644 index 00000000..15e474d4 --- /dev/null +++ b/Source/Services/Misc/WinRT/TitleCallableUI_WinRT.cpp @@ -0,0 +1,302 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !UNIT_TEST_SERVICES +#include "xsapi/title_callable_ui.h" +#include "xsapi/multiplayer.h" +#include "TitleCallableUI_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" + +using namespace pplx; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace Platform::Collections; +using namespace xbox::services::system; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_BEGIN + +Windows::Foundation::IAsyncOperation^>^ +TitleCallableUI::ShowPlayerPickerUI( + _In_ Platform::String^ promptDisplayText, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Windows::Foundation::Collections::IVectorView^ preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(xboxUserIds); + THROW_INVALIDARGUMENT_IF_NULL(preselectedXboxUserIds); + + auto task = title_callable_ui::show_player_picker_ui( + STRING_T_FROM_PLATFORM_STRING(promptDisplayText), + UtilsWinRT::CovertVectorViewToStdVectorString(xboxUserIds), + UtilsWinRT::CovertVectorViewToStdVectorString(preselectedXboxUserIds), + minSelectionCount, + maxSelectionCount + ) + .then([](xbox_live_result> result) + { + THROW_IF_ERR(result); + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(result.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowGameInviteUIAsync( + _In_ Xbox::Services::Multiplayer::MultiplayerSessionReference^ sessionReference, + _In_ Platform::String^ contextStringId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(sessionReference); + + auto task = title_callable_ui::show_game_invite_ui( + sessionReference->GetCppObj(), + STRING_T_FROM_PLATFORM_STRING(contextStringId) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowProfileCardUIAsync( + _In_ Platform::String^ targetXboxUserId + ) +{ + auto task = title_callable_ui::show_profile_card_ui( + STRING_T_FROM_PLATFORM_STRING(targetXboxUserId) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowChangeFriendRelationshipUIAsync( + _In_ Platform::String^ targetXboxUserId + ) +{ + auto task = title_callable_ui::show_change_friend_relationship_ui( + STRING_T_FROM_PLATFORM_STRING(targetXboxUserId) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowTitleAchievementsUIAsync( + _In_ uint32_t titleId + ) +{ + auto task = title_callable_ui::show_title_achievements_ui( + titleId + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +bool +TitleCallableUI::CheckGamingPrivilegeSilently( + _In_ GamingPrivilege privilege + ) +{ + auto result = title_callable_ui::check_gaming_privilege_silently( + static_cast(privilege) + ); + + THROW_ON_ERR_CODE(result.err()); + return result.payload(); +} + +Windows::Foundation::IAsyncOperation^ +TitleCallableUI::CheckGamingPrivilegeWithUI( + _In_ GamingPrivilege privilege, + _In_opt_ Platform::String^ friendlyMessage + ) +{ + auto task = title_callable_ui::check_gaming_privilege_with_ui( + static_cast(privilege), + STRING_T_FROM_PLATFORM_STRING(friendlyMessage) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + return result.payload(); + }); + + return ASYNC_FROM_TASK(task); +} + + +#if UWP_API +Windows::Foundation::IAsyncOperation^>^ +TitleCallableUI::ShowPlayerPickerUIForUser( + _In_ Platform::String^ promptDisplayText, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Windows::Foundation::Collections::IVectorView^ preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount, + _In_ Windows::System::User^ user + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(xboxUserIds); + THROW_INVALIDARGUMENT_IF_NULL(preselectedXboxUserIds); + + auto task = title_callable_ui::show_player_picker_ui( + STRING_T_FROM_PLATFORM_STRING(promptDisplayText), + UtilsWinRT::CovertVectorViewToStdVectorString(xboxUserIds), + UtilsWinRT::CovertVectorViewToStdVectorString(preselectedXboxUserIds), + minSelectionCount, + maxSelectionCount, + user + ) + .then([](xbox_live_result> result) + { + THROW_IF_ERR(result); + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(result.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowGameInviteUIForUserAsync( + _In_ Xbox::Services::Multiplayer::MultiplayerSessionReference^ sessionReference, + _In_ Platform::String^ contextStringId, + _In_ Windows::System::User^ user + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(sessionReference); + + auto task = title_callable_ui::show_game_invite_ui( + sessionReference->GetCppObj(), + STRING_T_FROM_PLATFORM_STRING(contextStringId), + user + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowProfileCardUIForUserAsync( + _In_ Platform::String^ targetXboxUserId, + _In_ Windows::System::User^ user + ) +{ + auto task = title_callable_ui::show_profile_card_ui( + STRING_T_FROM_PLATFORM_STRING(targetXboxUserId), + user + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowChangeFriendRelationshipUIForUserAsync( + _In_ Platform::String^ targetXboxUserId, + _In_ Windows::System::User^ user + ) +{ + auto task = title_callable_ui::show_change_friend_relationship_ui( + STRING_T_FROM_PLATFORM_STRING(targetXboxUserId), + user + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleCallableUI::ShowTitleAchievementsUIForUserAsync( + _In_ uint32_t titleId, + _In_ Windows::System::User^ user + ) +{ + auto task = title_callable_ui::show_title_achievements_ui( + titleId, + user + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +bool +TitleCallableUI::CheckGamingPrivilegeSilentlyForUser( + _In_ GamingPrivilege privilege, + _In_ Windows::System::User^ user + ) +{ + auto result = title_callable_ui::check_gaming_privilege_silently( + static_cast(privilege), + user + ); + + THROW_ON_ERR_CODE(result.err()); + return result.payload(); +} + +Windows::Foundation::IAsyncOperation^ +TitleCallableUI::CheckGamingPrivilegeWithUIForUser( + _In_ GamingPrivilege privilege, + _In_opt_ Platform::String^ friendlyMessage, + _In_ Windows::System::User^ user + ) +{ + auto task = title_callable_ui::check_gaming_privilege_with_ui( + static_cast(privilege), + STRING_T_FROM_PLATFORM_STRING(friendlyMessage), + user + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + return result.payload(); + }); + + return ASYNC_FROM_TASK(task); +} + +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_END +#endif \ No newline at end of file diff --git a/Source/Services/Misc/WinRT/TitleCallableUI_WinRT.h b/Source/Services/Misc/WinRT/TitleCallableUI_WinRT.h new file mode 100644 index 00000000..e27d1fab --- /dev/null +++ b/Source/Services/Misc/WinRT/TitleCallableUI_WinRT.h @@ -0,0 +1,328 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/system.h" +#include "xsapi/title_callable_ui.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_BEGIN + +/// List of gaming privilege that a user can have. +public enum class GamingPrivilege sealed +{ + /// The user can broadcast live gameplay. + Broadcast = xbox::services::system::gaming_privilege::broadcast, + + /// The user can view other user's friends list if this privilege is present. + ViewFriendsList = xbox::services::system::gaming_privilege::view_friends_list, + + /// The user can upload recorded in-game videos to the cloud if this privilege is present. Viewing GameDVRs is subject to privacy controls. + GameDVR = xbox::services::system::gaming_privilege::game_dvr, + + /// Kinect recorded content can be uploaded to the cloud for the user and made accessible to anyone if this privilege is present. Viewing other user's Kinect content is subject to a privacy setting. + ShareKinectContent = xbox::services::system::gaming_privilege::share_kinect_content, + + /// The user can join a party session if this privilege is present + MultiplayerParties = xbox::services::system::gaming_privilege::multiplayer_parties, + + /// The user can participate in voice chat during parties and multiplayer game sessions if this privilege is present. Communicating with other users is subject to additional privacy permission checks + CommunicationVoiceIngame = xbox::services::system::gaming_privilege::communication_voice_ingame, + + /// The user can use voice communication with Skype on Xbox One if this privilege is present + CommunicationVoiceSkype = xbox::services::system::gaming_privilege::communication_voice_skype, + + /// The user can allocate a cloud compute cluster and manage a cloud compute cluster for a hosted game session if this privilege is present + CloudGamingManageSession = xbox::services::system::gaming_privilege::cloud_gaming_manage_session, + + /// The user can join a cloud compute session if this privilege is present + CloudGamingJoinSession = xbox::services::system::gaming_privilege::cloud_gaming_join_session, + + /// The user can save games in cloud title storage if this privilege is present + CloudSavedGames = xbox::services::system::gaming_privilege::cloud_saved_games, + + /// The user can share content with others if this privilege is present + ShareContent = xbox::services::system::gaming_privilege::share_content, + + /// The user can purchase, download and launch premium content available with the Xbox LIVE Gold subscription if this privilege is present + PremiumContent = xbox::services::system::gaming_privilege::premium_content, + + /// The user can purchase and download premium subscription content and use premium subscription features when this privilege is present + SubscriptionContent = xbox::services::system::gaming_privilege::subscription_content, + + /// The user is allowed to share progress information on social networks when this privilege is present + SocialNetworkSharing = xbox::services::system::gaming_privilege::social_network_sharing, + + /// The user can access premium video services if this privilege is present + PremiumVideo = xbox::services::system::gaming_privilege::premium_video, + + /// The user can use video communication with Skype or other providers when this privilege is present. Communicating with other users is subject to additional privacy permission checks + VideoCommunications = xbox::services::system::gaming_privilege::video_communications, + + /// The user is authorized to purchase content when this privilege is present + PurchaseContent = xbox::services::system::gaming_privilege::purchase_content, + + /// The user is authorized to download and view online user created content when this privilege is present. + UserCreatedContent = xbox::services::system::gaming_privilege::user_created_content, + + /// The user is authorized to view other user's profiles when this privilege is present. Viewing other user's profiles is subject to additional privacy checks + ProfileViewing = xbox::services::system::gaming_privilege::profile_viewing, + + /// The user can use asynchronous text messaging with anyone when this privilege is present. Extra privacy permissions checks are required to determine who the user is authorized to communicate with. Communicating with other users is subject to additional privacy permission checks + Communications = xbox::services::system::gaming_privilege::communications, + + /// The user can join a multiplayer sessions for a game when this privilege is present. + MultiplayerSessions = xbox::services::system::gaming_privilege::multiplayer_sessions, + + /// The user can follow other Xbox LIVE users and add Xbox LIVE friends when this privilege is present. + AddFriend = xbox::services::system::gaming_privilege::add_friend +}; + +/// +/// Represents a class that contains static functions used for displaying stock UI during a game such as showing a people picker. +/// +public ref class TitleCallableUI sealed +{ +public: + + /// + /// Shows a picker UI that allows a person playing the game to select players + /// from a presented list of other people. + /// After the operation is complete, the list of selected Xbox User IDs is returned to the calling app. + /// + /// The prompt display text. + /// A list of Xbox User IDs which the user can select from. + /// A list of Xbox User IDs which will be pre-selected. + /// The minimum number of people the user must select. + /// The maximum number of people the user can select. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// The result contains the list of users that were selected by the player. + /// + static Windows::Foundation::IAsyncOperation^>^ + ShowPlayerPickerUI( + _In_ Platform::String^ promptDisplayText, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Windows::Foundation::Collections::IVectorView^ preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount + ); + + /// + /// Shows a picker UI populated from the selected user's friend list and suggested friend list. + /// After selection, the user can send an invitation to play a game and/or party chat for a + /// specified game session to the selected people. + /// + /// A reference to the multiplayer session to invite people to. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with "///". Pass an empty string if + /// you don't want a custom string added to the invite. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowGameInviteUIAsync( + _In_ Xbox::Services::Multiplayer::MultiplayerSessionReference^ sessionReference, + _In_ Platform::String^ contextStringId + ); + + /// + /// Shows UI displaying the profile card for a specified user. + /// + /// The Xbox User ID to show information about. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowProfileCardUIAsync( + _In_ Platform::String^ targetXboxUserId + ); + + /// + /// Shows UI for adding or removing a specified person to or from the requesting user's friend list. + /// + /// The Xbox User ID to show information about. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowChangeFriendRelationshipUIAsync( + _In_ Platform::String^ targetXboxUserId + ); + + /// + /// Shows UI presenting the requesting user's achievements for the specified title. + /// + /// The Xbox titleId to show information about. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowTitleAchievementsUIAsync( + _In_ uint32_t titleId + ); + + /// + /// Checks if the current user has a specific privilege + /// + /// The privilege to check. + /// + /// A boolean which is true if the current user has the privilege. + /// + static bool CheckGamingPrivilegeSilently( + _In_ GamingPrivilege privilege + ); + + /// + /// Checks if the current user has a specific privilege and if it doesn't, it shows UI + /// + /// The privilege to check. + /// Text to display in addition to the stock text about the privilege + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// A boolean which is true if the current user has the privilege. + /// + static Windows::Foundation::IAsyncOperation^ + CheckGamingPrivilegeWithUI( + _In_ GamingPrivilege privilege, + _In_opt_ Platform::String^ friendlyMessage + ); + +#if UWP_API + /// + /// Shows a picker UI that allows a person playing the game to select players + /// from a presented list of other people. + /// After the operation is complete, the list of selected Xbox User IDs is returned to the calling app. + /// + /// The prompt display text. + /// A list of Xbox User IDs which the user can select from. + /// A list of Xbox User IDs which will be pre-selected. + /// The minimum number of people the user must select. + /// The maximum number of people the user can select. + /// System user that identifies the user to show the UI on behalf of + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// The result contains the list of users that were selected by the player. + /// + static Windows::Foundation::IAsyncOperation^>^ + ShowPlayerPickerUIForUser( + _In_ Platform::String^ promptDisplayText, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Windows::Foundation::Collections::IVectorView^ preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount, + _In_ Windows::System::User^ user + ); + + /// + /// Shows a picker UI populated from the selected user's friend list and suggested friend list. + /// After selection, the user can send an invitation to play a game and/or party chat for a + /// specified game session to the selected people. + /// + /// A reference to the multiplayer session to invite people to. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with "///". Pass an empty string if + /// you don't want a custom string added to the invite. + /// System user that identifies which user is sending the invite + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowGameInviteUIForUserAsync( + _In_ Xbox::Services::Multiplayer::MultiplayerSessionReference^ sessionReference, + _In_ Platform::String^ contextStringId, + _In_ Windows::System::User^ user + ); + + /// + /// Shows UI displaying the profile card for a specified user. + /// + /// The Xbox User ID to show information about. + /// System user that identifies the user to show the UI on behalf of + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowProfileCardUIForUserAsync( + _In_ Platform::String^ targetXboxUserId, + _In_ Windows::System::User^ user + ); + + /// + /// Shows UI for adding or removing a specified person to or from the requesting user's friend list. + /// + /// The Xbox User ID to show information about. + /// System user that identifies the user to show the UI on behalf of + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowChangeFriendRelationshipUIForUserAsync( + _In_ Platform::String^ targetXboxUserId, + _In_ Windows::System::User^ user + ); + + /// + /// Shows UI presenting the requesting user's achievements for the specified title. + /// + /// The Xbox titleId to show information about. + /// System user that identifies the user to show the UI on behalf of + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// + static Windows::Foundation::IAsyncAction^ ShowTitleAchievementsUIForUserAsync( + _In_ uint32_t titleId, + _In_ Windows::System::User^ user + ); + + /// + /// Checks if the current user has a specific privilege + /// + /// The privilege to check. + /// System user that identifies the user to check the privilege on behalf of + /// + /// A boolean which is true if the current user has the privilege. + /// + static bool CheckGamingPrivilegeSilentlyForUser( + _In_ GamingPrivilege privilege, + _In_ Windows::System::User^ user + ); + + /// + /// Checks if the current user has a specific privilege and if it doesn't, it shows UI + /// + /// The privilege to check. + /// Text to display in addition to the stock text about the privilege + /// System user that identifies the user to show the UI on behalf of + /// + /// An interface for tracking the progress of the asynchronous call. + /// The operation completes when the UI is closed. + /// A boolean which is true if the current user has the privilege. + /// + static Windows::Foundation::IAsyncOperation^ + CheckGamingPrivilegeWithUIForUser( + _In_ GamingPrivilege privilege, + _In_opt_ Platform::String^ friendlyMessage, + _In_ Windows::System::User^ user + ); +#endif + +internal: + TitleCallableUI(); +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_END diff --git a/Source/Services/Misc/WinRT/VerifyStringResultCode_WinRT.h b/Source/Services/Misc/WinRT/VerifyStringResultCode_WinRT.h new file mode 100644 index 00000000..e431585f --- /dev/null +++ b/Source/Services/Misc/WinRT/VerifyStringResultCode_WinRT.h @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/system.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_BEGIN + +/// Enumeration values that indicate the result code from string verification. +public enum class VerifyStringResultCode +{ + /// No issues were found with the string. + Success = xbox::services::system::verify_string_result_code::success, + + /// The string contains offensive content. + Offensive = xbox::services::system::verify_string_result_code::offensive, + + /// The string is too long to verify. + TooLong = xbox::services::system::verify_string_result_code::too_long, + + /// An unknown error was encountered during string verification. + UnknownError = xbox::services::system::verify_string_result_code::unknown_error +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_END diff --git a/Source/Services/Misc/WinRT/VerifyStringResult_WinRT.h b/Source/Services/Misc/WinRT/VerifyStringResult_WinRT.h new file mode 100644 index 00000000..b44ae1b6 --- /dev/null +++ b/Source/Services/Misc/WinRT/VerifyStringResult_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/system.h" +#include "VerifyStringResultCode_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_BEGIN + +/// +/// Contains information about the results of a string verification. +/// +public ref class VerifyStringResult sealed +{ +public: + /// + /// The result code for the string verification. + /// + DEFINE_PROP_GET_ENUM_OBJ(ResultCode, result_code, VerifyStringResultCode); + + /// + /// FirstOffendingSubstring contains the first offending substring found if the + /// result code is VerifyStringResultCode::Offensive. + /// + DEFINE_PROP_GET_STR_OBJ(FirstOffendingSubstring, first_offending_substring); + +internal: + VerifyStringResult( + _In_ xbox::services::system::verify_string_result cppObj + ): + m_cppObj(std::move(cppObj)) + {} + +private: + xbox::services::system::verify_string_result m_cppObj; + +}; +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_END diff --git a/Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.cpp b/Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.cpp new file mode 100644 index 00000000..c2c2eaf1 --- /dev/null +++ b/Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.cpp @@ -0,0 +1,202 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/services.h" +#include "XboxLiveContext_WinRT.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#if !(TV_API | XBOX_UWP) +#include "User_WinRT.h" +#endif +#include "xsapi/profile.h" +#include "xsapi/http_call.h" +#include "XboxLiveHttpCall_WinRT.h" + +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_BEGIN + +XboxLiveHttpCallResponse::XboxLiveHttpCallResponse( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + m_headersMap = ref new Platform::Collections::Map(); + for (const auto& header : m_cppObj->response_headers()) + { + m_headersMap->Insert(ref new Platform::String(header.first.c_str()), ref new Platform::String(header.second.c_str())); + } + + std::vector cppVec = m_cppObj->response_body_vector(); + if( cppVec.size() > 0 ) + { + m_vec = ref new Platform::Array(&cppVec[0], static_cast(cppVec.size())); + } + else + { + m_vec = ref new Platform::Array(nullptr, 0); + } +} + +Platform::String^ XboxLiveHttpCallResponse::ResponseBodyJson::get() +{ + return ref new Platform::String( m_cppObj->response_body_json().serialize().c_str() ); +} + +Platform::Array^ XboxLiveHttpCallResponse::ResponseBodyVector::get() +{ + return m_vec; +} + +int XboxLiveHttpCallResponse::ErrorCode::get() +{ + return m_cppObj->err_code().value(); +} + +Platform::String^ XboxLiveHttpCallResponse::ErrorMessage::get() +{ + return ref new Platform::String(utility::conversions::to_utf16string(m_cppObj->err_message()).c_str()); +} + +int64_t XboxLiveHttpCallResponse::RetryAfterInSeconds::get() +{ + return m_cppObj->retry_after().count(); +} + +Windows::Foundation::Collections::IMapView^ XboxLiveHttpCallResponse::Headers::get() +{ + return m_headersMap->GetView(); +} + +XboxLiveHttpCall::XboxLiveHttpCall( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ +} + +XboxLiveHttpCall^ XboxLiveHttpCall::CreateXboxLiveHttpCall( + _In_ Microsoft::Xbox::Services::XboxLiveContextSettings^ settings, + _In_ Platform::String^ httpMethod, + _In_ Platform::String^ serverName, + _In_ Platform::String^ pathQueryFragment + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(httpMethod); + THROW_INVALIDARGUMENT_IF_NULL(serverName); + THROW_INVALIDARGUMENT_IF_NULL(pathQueryFragment); + + CONVERT_STD_EXCEPTION( + auto cppObj = create_xbox_live_http_call( + settings->GetCppObj(), + httpMethod->Data(), + serverName->Data(), + web::uri(pathQueryFragment->Data()) + ); + + return ref new XboxLiveHttpCall(cppObj); + ); +} + +Windows::Foundation::IAsyncOperation^ +XboxLiveHttpCall::GetResponseWithAuth( +#if TV_API | XBOX_UWP + _In_ Windows::Xbox::System::User^ user, +#else + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user, +#endif + _In_ HttpCallResponseBodyType httpCallResponseBodyType + ) +{ + CONVERT_STD_EXCEPTION( + std::shared_ptr userContext = std::make_shared(user); + http_call_response_body_type bodyType = static_cast(httpCallResponseBodyType); + + auto task = m_cppObj->get_response_with_auth(userContext, bodyType) + .then([](pplx::task< std::shared_ptr > t) + { + CONVERT_STD_EXCEPTION( + return ref new XboxLiveHttpCallResponse(t.get()); + ); + }); + + return ASYNC_FROM_TASK(task); + ); +} + +Windows::Foundation::IAsyncOperation^ +XboxLiveHttpCall::GetResponseWithoutAuth( + _In_ HttpCallResponseBodyType httpCallResponseBodyType + ) +{ + CONVERT_STD_EXCEPTION( + http_call_response_body_type bodyType = static_cast(httpCallResponseBodyType); + + auto task = m_cppObj->get_response(bodyType) + .then([](pplx::task> t) + { + CONVERT_STD_EXCEPTION( + return ref new XboxLiveHttpCallResponse(t.get()); + ); + }); + + return ASYNC_FROM_TASK(task); + ); +} + +void XboxLiveHttpCall::SetRequestBody( + _In_ Platform::String^ value + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(value); + + CONVERT_STD_EXCEPTION( + return m_cppObj->set_request_body(STRING_T_FROM_PLATFORM_STRING(value)); + ); +} + +void XboxLiveHttpCall::SetRequestBodyArray( + _In_ const Platform::Array^ requestBodyArray + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(requestBodyArray); + + CONVERT_STD_EXCEPTION( + byte* bufferBytes = requestBodyArray->Data; + std::vector requestBody(bufferBytes, bufferBytes + requestBodyArray->Length); + return m_cppObj->set_request_body(requestBody); + ); +} + +void XboxLiveHttpCall::SetCustomHeader( + _In_ Platform::String^ headerName, + _In_opt_ Platform::String^ headerValue + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(headerName); + + CONVERT_STD_EXCEPTION( + m_cppObj->set_custom_header(headerName->Data(), headerValue->Data()); + ); +} + +Platform::String^ XboxLiveHttpCall::PathQueryFragment::get() +{ + CONVERT_STD_EXCEPTION( + return ref new Platform::String( + m_cppObj->path_query_fragment().to_string().c_str() + ); + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_END + diff --git a/Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.h b/Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.h new file mode 100644 index 00000000..4698bc27 --- /dev/null +++ b/Source/Services/Misc/WinRT/XboxLiveHttpCall_WinRT.h @@ -0,0 +1,181 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "http_call_impl.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_BEGIN + +public enum class HttpCallResponseBodyType +{ + StringBody = xbox::services::http_call_response_body_type::string_body, + VectorBody = xbox::services::http_call_response_body_type::vector_body, + JsonBody = xbox::services::http_call_response_body_type::json_body +}; + +public ref class XboxLiveHttpCallResponse sealed +{ +public: + /// + /// Gets the body type of the response. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(BodyType, body_type, HttpCallResponseBodyType); + + /// + /// Gets the response body of the response as a string. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ResponseBodyString, response_body_string); + + /// + /// Gets the response body of the response as a JSON value. + /// + property Platform::String^ ResponseBodyJson { Platform::String^ get(); } + + /// + /// Gets the response body of the response as a byte vector. + /// + property Platform::Array^ ResponseBodyVector { Platform::Array^ get(); } + + /// + /// Gets the http headers of the response. + /// + property Windows::Foundation::Collections::IMapView^ Headers + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// Gets the http status of the response. + /// + DEFINE_PTR_PROP_GET_OBJ(HttpStatus, http_status, int); + + /// + /// Gets the error code of the response. + /// + property int ErrorCode { int get(); } + + /// + /// Gets the error message of the response. + /// + property Platform::String^ ErrorMessage { Platform::String^ get(); } + + /// + /// Gets the eTag of the response. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ETag, e_tag); + + /// + /// Gets the response date of the response. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ResponseDate, response_date); + + /// + /// Gets the "retry after" value found in the response. + /// + property int64_t RetryAfterInSeconds { int64_t get(); } + +internal: + XboxLiveHttpCallResponse( + _In_ std::shared_ptr cppObj + ); + +private: + Platform::Collections::Map^ m_headersMap; + Platform::Array^ m_vec; + std::shared_ptr m_cppObj; +}; + + +/// +/// Defines methods used to retrieve objects that in turn provide access to different Xbox Live service components. +/// +public ref class XboxLiveHttpCall sealed +{ +public: + static XboxLiveHttpCall^ CreateXboxLiveHttpCall( + _In_ Microsoft::Xbox::Services::XboxLiveContextSettings^ settings, + _In_ Platform::String^ httpMethod, + _In_ Platform::String^ serverName, + _In_ Platform::String^ pathQueryFragment + ); + + /// + /// Attach the Xbox Live token, sign the request, send the request to the service, and return the response. + /// + Windows::Foundation::IAsyncOperation^ GetResponseWithAuth( +#if TV_API | XBOX_UWP + _In_ Windows::Xbox::System::User^ user, +#else + _In_ Microsoft::Xbox::Services::System::XboxLiveUser^ user, +#endif + _In_ HttpCallResponseBodyType httpCallResponseBodyType + ); + + /// + /// Send the request to the service, and return the response without an Xbox Live token + /// + Windows::Foundation::IAsyncOperation^ GetResponseWithoutAuth( + _In_ HttpCallResponseBodyType httpCallResponseBodyType + ); + + /// + /// Sets the request body using a string. + /// + void SetRequestBody(_In_ Platform::String^ value); + + /// + /// Sets the request body using a byte array value. + /// + void SetRequestBodyArray(_In_ const Platform::Array^ requestBodyArray); + + /// + /// Sets a custom header. + /// + void SetCustomHeader(_In_ Platform::String^ headerName, _In_opt_ Platform::String^ headerValue); + + /// + /// Sets if retry is allowed during this call. + /// + DEFINE_PTR_PROP_GETSET_OBJ(RetryAllowed, retry_allowed, bool); + + /// + /// Get if retry is allowed during this call. + /// + DEFINE_PTR_PROP_GETSET_STR_OBJ(ContentTypeHeaderValue, content_type_header_value); + + /// + /// Sets the content type header value for this call. + /// + DEFINE_PTR_PROP_GETSET_STR_OBJ(ContractVersionHeaderValue, xbox_contract_version_header_value); + + /// + /// Gets the server name for this call. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ServerName, server_name); + + /// + /// Gets the path for this call. + /// + property Platform::String^ PathQueryFragment { Platform::String^ get(); } + + /// + /// Gets the http method for this call. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(HttpMethod, http_method); + +internal: + XboxLiveHttpCall( + _In_ std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_END diff --git a/Source/Services/Misc/Windows/notification_service_windows.cpp b/Source/Services/Misc/Windows/notification_service_windows.cpp new file mode 100644 index 00000000..00aa9c69 --- /dev/null +++ b/Source/Services/Misc/Windows/notification_service_windows.cpp @@ -0,0 +1,157 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !UNIT_TEST_SERVICES +#include "notification_service.h" +#include "xbox_system_factory.h" +#include "user_context.h" +#include "user_impl.h" + +using namespace pplx; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_BEGIN + +pplx::task> +notification_service_windows::subscribe_to_notifications( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + { + std::lock_guard guard(s_notificationSingletonLock); + if (m_userContexts.find(userContext->xbox_user_id()) == m_userContexts.end()) + { + m_userContexts.emplace(std::make_pair(userContext->xbox_user_id(), userContext)); + } + else + { + return pplx::task>(); + } + } + + auto asyncOp = Windows::Networking::PushNotifications::PushNotificationChannelManager::CreatePushNotificationChannelForApplicationAsync(); + + std::weak_ptr thisShared = std::dynamic_pointer_cast(shared_from_this()); + + create_task(asyncOp) + .then([thisShared, userContext, xboxLiveContextSettings, appConfig](task t) + { + try + { + auto channel = t.get(); + channel->PushNotificationReceived += ref new Windows::Foundation::TypedEventHandler( + [thisShared](Windows::Networking::PushNotifications::PushNotificationChannel ^ channel, Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs^ args) + { + std::shared_ptr pThis(thisShared.lock()); + if (pThis != nullptr) + { + try + { + pThis->on_push_notification_recieved(channel, args); + } + catch (...) + { + LOG_ERROR("on_push_notification_recieved error"); + } + } + }); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + xboxLiveContextSettings, + _T("POST"), + L"https://notify.xboxlive.com/", + L"system/notifications/endpoints", + xbox_live_api::subscribe_to_notifications + ); + + auto applicationInstanceId = utils::create_guid(true); + auto family = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily; + auto form = Windows::System::Profile::AnalyticsInfo::DeviceForm; + auto version = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamilyVersion; + string_t platform; + if (family == "Windows.Mobile") + { + platform = _T("WindowsOneCoreMobile"); + } + else if (family == "Windows.Xbox") + { + platform = _T("Durango"); + } + else + { + platform = _T("WindowsOneCore"); + } + + web::json::value payload; + payload[_T("systemId")] = web::json::value::string(applicationInstanceId); + payload[_T("endpointUri")] = web::json::value::string(channel->Uri->Data()); + payload[_T("platform")] = web::json::value::string(platform); + payload[_T("platformVersion")] = web::json::value::string(_T("10")); + payload[_T("locale")] = web::json::value::string(utils::get_locales()); + payload[_T("titleId")] = web::json::value::string(std::to_wstring(appConfig->title_id())); + + httpCall->set_request_body(payload.serialize()); + httpCall->get_response_with_auth(userContext).get(); + + } + catch (...) + { + LOG_ERROR("Failed to successfully register with notification service"); + } + }, pplx::task_continuation_context::use_arbitrary()); + + return pplx::task>(); +} + +pplx::task> notification_service_windows::subscribe_to_notifications() +{ + return pplx::task_from_result>(xbox_live_result(xbox_live_error_code::logic_error, "Not valid notification code path")); +} + +void +notification_service_windows::on_push_notification_recieved( + _In_ Windows::Networking::PushNotifications::PushNotificationChannel ^sender, + _In_ Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs ^args + ) +{ + std::error_code errc; + if (args && args->RawNotification && args->RawNotification->Content) + { + auto parsedJson = web::json::value::parse(args->RawNotification->Content->Data(), errc); + auto xboxLiveNotificationJson = utils::extract_json_field(parsedJson, _T("xboxLiveNotification"), errc, false); + auto notificationTypeString = utils::extract_json_string(xboxLiveNotificationJson, _T("notificationType"), errc); + auto xuid = utils::extract_json_string(xboxLiveNotificationJson, _T("userXuid"), errc); + + if (!errc && utils::str_icmp(notificationTypeString, _T("spop")) == 0) + { + auto contextItor = m_userContexts.find(xuid); + if (contextItor != m_userContexts.end() && contextItor->second != nullptr && contextItor->second->user() != nullptr) + { + auto user = contextItor->second->user(); +#if XSAPI_CPP + user->_User_impl()->sign_in_impl( + false, + true + ); +#else + user->GetUserImpl()->sign_in_impl( + false, + true + ); +#endif + } + } + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_END +#endif \ No newline at end of file diff --git a/Source/Services/Misc/contextual_config_result.cpp b/Source/Services/Misc/contextual_config_result.cpp new file mode 100644 index 00000000..e4b64274 --- /dev/null +++ b/Source/Services/Misc/contextual_config_result.cpp @@ -0,0 +1,375 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" +#include "contextual_config_result.h" +#include "xbox_system_factory.h" + +using namespace pplx; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_config_result_stat::contextual_config_result_stat() : + m_visibility(contextual_search_stat_visibility::unknown) +{ +} + +contextual_config_result_stat::contextual_config_result_stat( + _In_ string_t name, + _In_ string_t type, + _In_ contextual_search_stat_visibility visibility + ) : + m_name(std::move(name)), + m_type(std::move(type)), + m_visibility(visibility) +{ +} + +xbox_live_result +contextual_config_result_stat::_Deserialize( + _In_ const web::json::value& inputJson + ) +{ + std::error_code errc = xbox_live_error_code::no_error; + contextual_config_result_stat val( + utils::extract_json_string(inputJson, _T("name"), errc, false), + utils::extract_json_string(inputJson, _T("type"), errc, false), + convert_string_to_visibility(utils::extract_json_string(inputJson, _T("visibility"), errc, false)) + ); + + return xbox_live_result(val, errc); +} + +contextual_search_stat_visibility +contextual_config_result_stat::convert_string_to_visibility( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("Private")) == 0) + { + return contextual_search_stat_visibility::private_visibility; + } + else if (utils::str_icmp(value, _T("Public")) == 0) + { + return contextual_search_stat_visibility::public_visibility; + } + + return contextual_search_stat_visibility::unknown; +} + +const string_t& contextual_config_result_stat::name() const +{ + return m_name; +} + +const string_t& contextual_config_result_stat::type() const +{ + return m_type; +} + +contextual_search_stat_visibility contextual_config_result_stat::visibility() const +{ + return m_visibility; +} + +contextual_config_result_metadata::contextual_config_result_metadata() : + m_filter(false), + m_sort(false), + m_type(contextual_search_stat_display_type::unknown), + m_rangeMin(0), + m_rangeMax(0) +{ +} + +contextual_config_result_metadata::contextual_config_result_metadata( + _In_ string_t name, + _In_ string_t displayName, + _In_ bool filter, + _In_ bool sort, + _In_ contextual_search_stat_display_type type, + _In_ string_t setName, + _In_ uint64_t rangeMin, + _In_ uint64_t rangeMax + ) : + m_name(std::move(name)), + m_displayName(std::move(displayName)), + m_filter(filter), + m_sort(sort), + m_type(type), + m_setName(std::move(setName)), + m_rangeMin(rangeMin), + m_rangeMax(rangeMax) +{ +} + +xbox_live_result +contextual_config_result_metadata::_Deserialize(_In_ const web::json::value& inputJson) +{ + std::error_code errc = xbox_live_error_code::no_error; + web::json::value rangeValues(utils::extract_json_field(inputJson, _T("rangeValues"), errc, false)); + + contextual_config_result_metadata val( + utils::extract_json_string(inputJson, _T("name"), errc, false), + utils::extract_json_string(inputJson, _T("displayName"), errc, false), + utils::extract_json_bool(inputJson, _T("filter"), errc, false), + utils::extract_json_bool(inputJson, _T("sort"), errc, false), + convert_string_to_display_type(utils::extract_json_string(inputJson, _T("type"), errc, false)), + utils::extract_json_string(inputJson, _T("setName"), errc, false), + utils::extract_json_int(rangeValues, _T("min"), errc, false, 0), + utils::extract_json_int(rangeValues, _T("max"), errc, false, 0) + ); + return xbox_live_result(val, errc); +} + +contextual_search_stat_display_type +contextual_config_result_metadata::convert_string_to_display_type( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("Range")) == 0) + { + return contextual_search_stat_display_type::defined_range; + } + else if (utils::str_icmp(value, _T("Set")) == 0) + { + return contextual_search_stat_display_type::set; + } + else if (utils::str_icmp(value, _T("UndefinedRange")) == 0) + { + return contextual_search_stat_display_type::undefined_range; + } + + return contextual_search_stat_display_type::unknown; +} + +const string_t& contextual_config_result_metadata::name() const +{ + return m_name; +} + +const string_t& contextual_config_result_metadata::display_name() const +{ + return m_displayName; +} + +bool contextual_config_result_metadata::filter() const +{ + return m_filter; +} + +bool contextual_config_result_metadata::sort() const +{ + return m_sort; +} + +contextual_search_stat_display_type contextual_config_result_metadata::type() const +{ + return m_type; +} + +const string_t& contextual_config_result_metadata::setname() const +{ + return m_setName; +} + +uint64_t contextual_config_result_metadata::range_min() const +{ + return m_rangeMin; +} + +uint64_t contextual_config_result_metadata::range_max() const +{ + return m_rangeMax; +} + +contextual_config_result_set_pair::contextual_config_result_set_pair() +{ +} + +contextual_config_result_set_pair::contextual_config_result_set_pair( + _In_ string_t statValue, + _In_ string_t displayName + ) : + m_statValue(std::move(statValue)), + m_displayName(std::move(displayName)) +{ +} + +xbox_live_result contextual_config_result_set_pair::_Deserialize( + _In_ const web::json::value& inputJson + ) +{ + std::error_code errc = xbox_live_error_code::no_error; + + contextual_config_result_set_pair val( + utils::extract_json_string(inputJson, _T("memberStatValue"), errc, false), + utils::extract_json_string(inputJson, _T("memberDisplayName"), errc, false) + ); + return xbox_live_result(val, errc); +} + +const string_t& contextual_config_result_set_pair::stat_value() const +{ + return m_statValue; +} + +const string_t& contextual_config_result_set_pair::display_name() const +{ + return m_displayName; +} + +contextual_config_result_set::contextual_config_result_set() +{ +} + +contextual_config_result_set::contextual_config_result_set( + _In_ string_t name, + _In_ std::unordered_map values + ) : + m_name(std::move(name)), + m_values(std::move(values)) +{ +} + +const string_t& contextual_config_result_set::name() const +{ + return m_name; +} + +const std::unordered_map& contextual_config_result_set::values() const +{ + return m_values; +} + +xbox_live_result contextual_config_result_set::_Deserialize(_In_ const web::json::value& inputJson) +{ + std::error_code errc = xbox_live_error_code::no_error; + auto pairs = utils::extract_json_vector( + contextual_config_result_set_pair::_Deserialize, + inputJson, + _T("values"), + errc, + true + ); + + std::unordered_map valueMap; + for (const auto& pair : pairs) + { + if (!pair.display_name().empty() && !pair.stat_value().empty()) + { + valueMap[pair.stat_value()] = pair.display_name(); + } + } + + contextual_config_result_set val( + utils::extract_json_string(inputJson, _T("name"), errc, false), + valueMap + ); + + return xbox_live_result(val, errc); +} + +contextual_config_result::contextual_config_result() +{ +} + +contextual_config_result::contextual_config_result( + _In_ std::vector stats, + _In_ std::vector metadataSet, + _In_ std::vector sets + ) : + m_stats(std::move(stats)), + m_metadataSet(std::move(metadataSet)), + m_sets(std::move(sets)) +{ +} + +xbox_live_result contextual_config_result::_Deserialize( + _In_ const web::json::value& inputJson + ) +{ + string_t jsTxt = inputJson.serialize(); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value metadataStats(utils::extract_json_field(inputJson, _T("metadata"), errc, false)); + + auto vecStats = utils::extract_json_vector(contextual_config_result_stat::_Deserialize, inputJson, _T("stats"), errc, false); + + contextual_config_result val( + vecStats, + utils::extract_json_vector(contextual_config_result_metadata::_Deserialize, metadataStats, _T("stats"), errc, false), + utils::extract_json_vector(contextual_config_result_set::_Deserialize, inputJson, _T("sets"), errc, false) + ); + + return xbox_live_result(val, errc); +} + +const std::vector& contextual_config_result::stats() const +{ + return m_stats; +} + +const std::vector& contextual_config_result::metadata_set() const +{ + return m_metadataSet; +} + +const std::vector& contextual_config_result::sets() const +{ + return m_sets; +} + +std::vector contextual_config_result::get_contextual_search_configured_stats() +{ + std::vector configuredStats; + + for (const auto& stat : m_stats) + { + contextual_config_result_metadata matchingMetaData; + for (const auto& metadata : m_metadataSet) + { + if (metadata.name() == stat.name()) + { + matchingMetaData = metadata; + break; + } + } + + contextual_config_result_set matchingSet; + for (const auto& set : m_sets) + { + if (set.name() == stat.name()) + { + matchingSet = set; + break; + } + } + + contextual_search_configured_stat configuredStat( + stat.name(), + stat.type(), + stat.visibility(), + matchingMetaData.display_name(), + matchingMetaData.filter(), + matchingMetaData.sort(), + matchingMetaData.type(), + matchingSet.values(), + matchingMetaData.range_min(), + matchingMetaData.range_max() + ); + + configuredStats.push_back(configuredStat); + } + + return configuredStats; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_config_result.h b/Source/Services/Misc/contextual_config_result.h new file mode 100644 index 00000000..87f2145a --- /dev/null +++ b/Source/Services/Misc/contextual_config_result.h @@ -0,0 +1,143 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +class contextual_config_result_stat +{ +public: + contextual_config_result_stat(); + contextual_config_result_stat( + _In_ string_t name, + _In_ string_t type, + _In_ xbox::services::contextual_search::contextual_search_stat_visibility visibility + ); + + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + + const string_t& name() const; + const string_t& type() const; + xbox::services::contextual_search::contextual_search_stat_visibility visibility() const; + +private: + static xbox::services::contextual_search::contextual_search_stat_visibility convert_string_to_visibility( + _In_ const string_t& value + ); + + string_t m_name; + string_t m_type; + xbox::services::contextual_search::contextual_search_stat_visibility m_visibility; +}; + +class contextual_config_result_metadata +{ +public: + contextual_config_result_metadata(); + contextual_config_result_metadata( + _In_ string_t name, + _In_ string_t displayName, + _In_ bool filter, + _In_ bool sort, + _In_ contextual_search_stat_display_type type, + _In_ string_t setName, + _In_ uint64_t rangeMin, + _In_ uint64_t rangeMax + ); + + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + + const string_t& name() const; + const string_t& display_name() const; + bool filter() const; + bool sort() const; + contextual_search_stat_display_type type() const; + const string_t& setname() const; + uint64_t range_min() const; + uint64_t range_max() const; + +private: + static contextual_search_stat_display_type convert_string_to_display_type( + _In_ const string_t& value + ); + + string_t m_name; + string_t m_displayName; + bool m_filter; + bool m_sort; + contextual_search_stat_display_type m_type; + string_t m_setName; + uint64_t m_rangeMin; + uint64_t m_rangeMax; +}; + +class contextual_config_result_set_pair +{ +public: + contextual_config_result_set_pair(); + contextual_config_result_set_pair( + _In_ string_t statValue, + _In_ string_t displayName + ); + + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + + const string_t& stat_value() const; + const string_t& display_name() const; + +private: + string_t m_statValue; + string_t m_displayName; +}; + +class contextual_config_result_set +{ +public: + contextual_config_result_set(); + contextual_config_result_set( + _In_ string_t name, + _In_ std::unordered_map values + ); + + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + + const string_t& name() const; + const std::unordered_map& values() const; + +private: + string_t m_name; + std::unordered_map m_values; +}; + +class contextual_config_result +{ +public: + contextual_config_result(); + contextual_config_result( + _In_ std::vector stats, + _In_ std::vector metadataSet, + _In_ std::vector sets + ); + + static xbox_live_result _Deserialize(_In_ const web::json::value& inputJson); + + std::vector get_contextual_search_configured_stats(); + + const std::vector& stats() const; + const std::vector& metadata_set() const; + const std::vector& sets() const; + +private: + std::vector m_stats; + std::vector m_metadataSet; + std::vector m_sets; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_broadcast.cpp b/Source/Services/Misc/contextual_search_broadcast.cpp new file mode 100644 index 00000000..f2e612c2 --- /dev/null +++ b/Source/Services/Misc/contextual_search_broadcast.cpp @@ -0,0 +1,97 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_broadcast::contextual_search_broadcast() : + m_viewers(0) +{ +} + +contextual_search_broadcast::contextual_search_broadcast( + _In_ string_t xboxUserId, + _In_ string_t provider, + _In_ string_t broadcasterIdFromProvider, + _In_ uint64_t viewers, + _In_ utility::datetime startedDate, + _In_ std::unordered_map currentStats + ) : + m_xboxUserId(std::move(xboxUserId)), + m_provider(std::move(provider)), + m_broadcasterIdFromProvider(std::move(broadcasterIdFromProvider)), + m_viewers(viewers), + m_startedDate(std::move(startedDate)), + m_currentStats(std::move(currentStats)) +{ +} + +const string_t& contextual_search_broadcast::xbox_user_id() const +{ + return m_xboxUserId; +} + +const string_t& contextual_search_broadcast::provider() const +{ + return m_provider; +} + +const string_t& contextual_search_broadcast::broadcaster_id_from_provider() const +{ + return m_broadcasterIdFromProvider; +} + +uint64_t contextual_search_broadcast::viewers() const +{ + return m_viewers; +} + +const utility::datetime& contextual_search_broadcast::started_date() const +{ + return m_startedDate; +} + +const std::unordered_map& contextual_search_broadcast::current_stats() const +{ + return m_currentStats; +} + +xbox_live_result +contextual_search_broadcast::_Deserialize(_In_ const web::json::value& inputJson) +{ + if (inputJson.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + // Pull out all the key/value pairs in the "stats" field and add them to currentStats object + web::json::object statsField(utils::extract_json_field(inputJson, _T("stats"), errc, false).as_object()); + std::unordered_map currentStats; + for (const auto& stat : statsField) + { + if(!stat.first.empty() && stat.second.is_string() && !stat.second.as_string().empty()) + { + currentStats[stat.first] = stat.second.as_string(); + } + } + + contextual_search_broadcast broadcastsResult( + utils::extract_json_string(inputJson, _T("xuid"), errc, false), + utils::extract_json_string(inputJson, _T("provider"), errc, false), + utils::extract_json_string(inputJson, _T("id"), errc, false), + utils::extract_json_int(inputJson, _T("viewers"), errc, false), + utils::extract_json_time(inputJson, _T("started"), errc, false), + currentStats + ); + + return xbox_live_result(broadcastsResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_configured_stat.cpp b/Source/Services/Misc/contextual_search_configured_stat.cpp new file mode 100644 index 00000000..8d8d1a9f --- /dev/null +++ b/Source/Services/Misc/contextual_search_configured_stat.cpp @@ -0,0 +1,100 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_configured_stat::contextual_search_configured_stat() : + m_visibility(contextual_search_stat_visibility::public_visibility), + m_canBeFiltered(false), + m_canBeSorted(false), + m_displayType(contextual_search_stat_display_type::defined_range), + m_rangeMin(0), + m_rangeMax(0) +{ +} + +contextual_search_configured_stat::contextual_search_configured_stat( + _In_ string_t name, + _In_ string_t dataType, + _In_ contextual_search_stat_visibility visibility, + _In_ string_t displayName, + _In_ bool canBeFiltered, + _In_ bool canBeSorted, + _In_ contextual_search_stat_display_type displayType, + _In_ std::unordered_map valueToDisplayNameMap, + _In_ uint64_t rangeMin, + _In_ uint64_t rangeMax + ) : + m_name(std::move(name)), + m_dataType(std::move(dataType)), + m_visibility(visibility), + m_displayName(std::move(displayName)), + m_canBeFiltered(canBeFiltered), + m_canBeSorted(canBeSorted), + m_displayType(displayType), + m_valueToDisplayNameMap(std::move(valueToDisplayNameMap)), + m_rangeMin(rangeMin), + m_rangeMax(rangeMax) +{ +} + +const string_t& contextual_search_configured_stat::name() const +{ + return m_name; +} + +const string_t& contextual_search_configured_stat::data_type() const +{ + return m_dataType; +} + +contextual_search_stat_visibility contextual_search_configured_stat::visibility() const +{ + return m_visibility; +} + +const string_t& contextual_search_configured_stat::display_name() const +{ + return m_displayName; +} + +bool contextual_search_configured_stat::can_be_filtered() const +{ + return m_canBeFiltered; +} + +bool contextual_search_configured_stat::can_be_sorted() const +{ + return m_canBeSorted; +} + +contextual_search_stat_display_type contextual_search_configured_stat::display_type() const +{ + return m_displayType; +} + +const std::unordered_map& contextual_search_configured_stat::value_to_display_name_map() const +{ + return m_valueToDisplayNameMap; +} + +uint64_t contextual_search_configured_stat::range_min() const +{ + return m_rangeMin; +} + +uint64_t contextual_search_configured_stat::range_max() const +{ + return m_rangeMax; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_game_clip.cpp b/Source/Services/Misc/contextual_search_game_clip.cpp new file mode 100644 index 00000000..afb6476b --- /dev/null +++ b/Source/Services/Misc/contextual_search_game_clip.cpp @@ -0,0 +1,151 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_game_clip::contextual_search_game_clip() : + m_durationInSeconds(0), + m_gameClipType(contextual_search_game_clip_type::none), + m_views(0) +{ +} + +contextual_search_game_clip::contextual_search_game_clip( + _In_ string_t clipName, + _In_ uint64_t durationInSeconds, + _In_ string_t gameClipId, + _In_ string_t gameClipLocale, + _In_ std::vector gameClipUris, + _In_ std::vector thumbnails, + _In_ contextual_search_game_clip_type gameClipType, + _In_ uint64_t views, + _In_ string_t xboxUserId, + _In_ std::vector stats + ) : + m_clipName(std::move(clipName)), + m_durationInSeconds(durationInSeconds), + m_gameClipId(std::move(gameClipId)), + m_gameClipLocale(std::move(gameClipLocale)), + m_gameClipUris(std::move(gameClipUris)), + m_thumbnails(std::move(thumbnails)), + m_gameClipType(gameClipType), + m_views(views), + m_xboxUserId(std::move(xboxUserId)), + m_stats(std::move(stats)) +{ +} + +string_t +contextual_search_game_clip::convert_xuid_to_string( + _In_ uint64_t xuid, + _In_ string_t xuidName +) +{ + if (!xuidName.empty()) return xuidName; + stringstream_t ss; + ss << xuid; + return ss.str(); +} + +contextual_search_game_clip_type +contextual_search_game_clip::convert_string_to_clip_type(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("Achievement")) == 0) + { + return contextual_search_game_clip_type::achievement; + } + else if (utils::str_icmp(value, _T("DeveloperInitiated")) == 0) + { + return contextual_search_game_clip_type::developer_initiated; + } + else if (utils::str_icmp(value, _T("UserGenerated")) == 0) + { + return contextual_search_game_clip_type::user_generated; + } + + return contextual_search_game_clip_type::none; +} + +xbox_live_result +contextual_search_game_clip::_Deserialize(_In_ const web::json::value& inputJson) +{ + if (inputJson.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + contextual_search_game_clip result( + utils::extract_json_string(inputJson, _T("clipName"), errc, false), + utils::extract_json_uint52(inputJson, _T("durationInSeconds"), errc, false), + utils::extract_json_string(inputJson, _T("gameClipId"), errc, false), + utils::extract_json_string(inputJson, _T("gameClipLocale"), errc, false), + utils::extract_json_vector(contextual_search_game_clip_uri_info::_Deserialize, inputJson, _T("gameClipUris"), errc, false), + utils::extract_json_vector(contextual_search_game_clip_thumbnail::_Deserialize, inputJson, _T("thumbnails"), errc, false), + convert_string_to_clip_type(utils::extract_json_string(inputJson, _T("type"), false)), + utils::extract_json_uint52(inputJson, _T("views"), errc, false), + convert_xuid_to_string(utils::extract_json_uint52(inputJson, _T("xuid"), errc, false), utils::extract_json_string(inputJson, _T("xboxUserId"), errc, false)), + utils::extract_json_vector(contextual_search_game_clip_stat::_Deserialize, inputJson, _T("stats"), errc, false) + ); + + return xbox_live_result(result, errc); +} + +const string_t& contextual_search_game_clip::clip_name() const +{ + return m_clipName; +} + +uint64_t contextual_search_game_clip::duration_in_seconds() const +{ + return m_durationInSeconds; +} + +const string_t& contextual_search_game_clip::game_clip_id() const +{ + return m_gameClipId; +} + +const string_t& contextual_search_game_clip::game_clip_locale() const +{ + return m_gameClipLocale; +} + +const std::vector& contextual_search_game_clip::game_clip_uris() const +{ + return m_gameClipUris; +} + +const std::vector& contextual_search_game_clip::thumbnails() const +{ + return m_thumbnails; +} + +contextual_search_game_clip_type contextual_search_game_clip::game_clip_type() const +{ + return m_gameClipType; +} + +uint64_t contextual_search_game_clip::views() const +{ + return m_views; +} + +const string_t& contextual_search_game_clip::xbox_user_id() const +{ + return m_xboxUserId; +} + +const std::vector& contextual_search_game_clip::stats() const +{ + return m_stats; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_game_clip_stat.cpp b/Source/Services/Misc/contextual_search_game_clip_stat.cpp new file mode 100644 index 00000000..76791a3c --- /dev/null +++ b/Source/Services/Misc/contextual_search_game_clip_stat.cpp @@ -0,0 +1,78 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_game_clip_stat::contextual_search_game_clip_stat() +{ +} + +contextual_search_game_clip_stat::contextual_search_game_clip_stat( + _In_ string_t statName, + _In_ string_t value, + _In_ string_t minValue, + _In_ string_t maxValue, + _In_ string_t deltaValue + ) : + m_statName(std::move(statName)), + m_value(std::move(value)), + m_minValue(std::move(minValue)), + m_maxValue(std::move(maxValue)), + m_deltaValue(std::move(deltaValue)) +{ +} + +xbox_live_result +contextual_search_game_clip_stat::_Deserialize(_In_ const web::json::value& inputJson) +{ + if (inputJson.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + contextual_search_game_clip_stat result( + utils::extract_json_string(inputJson, _T("statName"), errc, false), + utils::extract_json_string(inputJson, _T("value"), errc, false), + utils::extract_json_string(inputJson, _T("min"), errc, false), + utils::extract_json_string(inputJson, _T("max"), errc, false), + utils::extract_json_string(inputJson, _T("delta"), errc, false) + ); + + return xbox_live_result(result, errc); +} + +const string_t& contextual_search_game_clip_stat::stat_name() const +{ + return m_statName; +} + +const string_t& contextual_search_game_clip_stat::value() const +{ + return m_value; +} + +const string_t& contextual_search_game_clip_stat::min_value() const +{ + return m_minValue; +} + +const string_t& contextual_search_game_clip_stat::max_value() const +{ + return m_maxValue; +} + +const string_t& contextual_search_game_clip_stat::delta_value() const +{ + return m_deltaValue; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_game_clip_thumbnail.cpp b/Source/Services/Misc/contextual_search_game_clip_thumbnail.cpp new file mode 100644 index 00000000..8e873381 --- /dev/null +++ b/Source/Services/Misc/contextual_search_game_clip_thumbnail.cpp @@ -0,0 +1,76 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_game_clip_thumbnail::contextual_search_game_clip_thumbnail() +{ +} + +contextual_search_game_clip_thumbnail::contextual_search_game_clip_thumbnail( + _In_ web::uri url, + _In_ uint64_t fileSize, + _In_ contextual_search_game_clip_thumbnail_type thumbnailType + ) : + m_url(std::move(url)), + m_fileSize(fileSize), + m_thumbnailType(thumbnailType) +{ +} + +contextual_search_game_clip_thumbnail_type +contextual_search_game_clip_thumbnail::convert_string_to_thumbnail_type(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("Large")) == 0) + { + return contextual_search_game_clip_thumbnail_type::large_thumbnail; + } + else if (utils::str_icmp(value, _T("Small")) == 0) + { + return contextual_search_game_clip_thumbnail_type::small_thumbnail; + } + + return contextual_search_game_clip_thumbnail_type::none; +} + +xbox_live_result +contextual_search_game_clip_thumbnail::_Deserialize(_In_ const web::json::value& inputJson) +{ + if (inputJson.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + contextual_search_game_clip_thumbnail result( + utils::extract_json_string(inputJson, _T("Uri"), errc, false), + utils::extract_json_uint52(inputJson, _T("FileSize"), errc, false), + convert_string_to_thumbnail_type(utils::extract_json_string(inputJson, _T("ThumbnailType"), errc, false)) + ); + + return xbox_live_result(result, errc); +} + +const web::uri& contextual_search_game_clip_thumbnail::url() const +{ + return m_url; +} + +uint64_t contextual_search_game_clip_thumbnail::file_size() const +{ + return m_fileSize; +} + +contextual_search_game_clip_thumbnail_type contextual_search_game_clip_thumbnail::thumbnail_type() const +{ + return m_thumbnailType; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_game_clip_uri_info.cpp b/Source/Services/Misc/contextual_search_game_clip_uri_info.cpp new file mode 100644 index 00000000..e2dcd6ee --- /dev/null +++ b/Source/Services/Misc/contextual_search_game_clip_uri_info.cpp @@ -0,0 +1,95 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_game_clip_uri_info::contextual_search_game_clip_uri_info() : + m_fileSize(0), + m_uriType(contextual_search_game_clip_uri_type::none) +{ +} + +contextual_search_game_clip_uri_info::contextual_search_game_clip_uri_info( + _In_ web::uri url, + _In_ uint64_t fileSize, + _In_ contextual_search_game_clip_uri_type uriType, + _In_ utility::datetime expiration + ) : + m_url(std::move(url)), + m_fileSize(fileSize), + m_uriType(uriType), + m_expiration(std::move(expiration)) +{ +} + +contextual_search_game_clip_uri_type +contextual_search_game_clip_uri_info::convert_string_to_clip_uri_type(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("Original")) == 0) + { + return contextual_search_game_clip_uri_type::original; + } + else if (utils::str_icmp(value, _T("Download")) == 0) + { + return contextual_search_game_clip_uri_type::download; + } + else if (utils::str_icmp(value, _T("Ahls")) == 0) + { + return contextual_search_game_clip_uri_type::http_live_streaming; + } + else if (utils::str_icmp(value, _T("SmoothStreaming")) == 0) + { + return contextual_search_game_clip_uri_type::smooth_streaming; + } + + return contextual_search_game_clip_uri_type::none; +} + +xbox_live_result +contextual_search_game_clip_uri_info::_Deserialize(_In_ const web::json::value& inputJson) +{ + if (inputJson.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + contextual_search_game_clip_uri_info result( + utils::extract_json_string(inputJson, _T("Uri"), errc, false), + utils::extract_json_uint52(inputJson, _T("FileSize"), errc, false), + convert_string_to_clip_uri_type(utils::extract_json_string(inputJson, _T("UriType"), errc, false)), + utils::extract_json_time(inputJson, _T("Expiration"), errc, false) + ); + + return xbox_live_result(result, errc); +} + + +const web::uri& contextual_search_game_clip_uri_info::url() const +{ + return m_url; +} + +uint64_t contextual_search_game_clip_uri_info::file_size() const +{ + return m_fileSize; +} + +contextual_search_game_clip_uri_type contextual_search_game_clip_uri_info::uri_type() const +{ + return m_uriType; +} + +const utility::datetime& contextual_search_game_clip_uri_info::expiration() const +{ + return m_expiration; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_game_clips_result.cpp b/Source/Services/Misc/contextual_search_game_clips_result.cpp new file mode 100644 index 00000000..41a17b19 --- /dev/null +++ b/Source/Services/Misc/contextual_search_game_clips_result.cpp @@ -0,0 +1,79 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_game_clips_result::contextual_search_game_clips_result() +{ +} + +contextual_search_game_clips_result::contextual_search_game_clips_result( + _In_ std::vector clips + ) : + m_clips(std::move(clips)), + m_skipItems(0) +{ +} + +xbox_live_result +contextual_search_game_clips_result::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errCode = xbox_live_error_code::no_error; + + auto result = contextual_search_game_clips_result( + utils::extract_json_vector(contextual_search_game_clip::_Deserialize, json, _T("value"), errCode, false) + ); + + return xbox_live_result(result, errCode); +} + +void contextual_search_game_clips_result::_Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ uint32_t titleId, + _In_ uint32_t skipItems + ) +{ + m_userContext = std::move(userContext); + m_xboxLiveContextSettings = std::move(xboxLiveContextSettings); + m_appConfig = appConfig; + m_titleId = titleId; + m_skipItems = skipItems; +} + +pplx::task> +contextual_search_game_clips_result::get_next( + _In_ uint32_t maxItems + ) +{ + contextual_search_service service(m_userContext, m_xboxLiveContextSettings, m_appConfig); + + return service.get_game_clips_internal( + m_titleId, + m_skipItems, + maxItems, + _T(""), + false, + _T("") + ); +} + +const std::vector& contextual_search_game_clips_result::items() const +{ + return m_clips; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/contextual_search_service.cpp b/Source/Services/Misc/contextual_search_service.cpp new file mode 100644 index 00000000..13c83650 --- /dev/null +++ b/Source/Services/Misc/contextual_search_service.cpp @@ -0,0 +1,393 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/contextual_search_service.h" +#include "contextual_config_result.h" +#include "xbox_system_factory.h" + +using namespace pplx; +using namespace xbox::services; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_BEGIN + +contextual_search_service::contextual_search_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr settings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_settings(std::move(settings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task>> +contextual_search_service::get_configuration( + _In_ uint32_t titleId + ) +{ + stringstream_t pathAndQuery; + pathAndQuery << _T("/titles/"); + pathAndQuery << titleId; + pathAndQuery << _T("/configuration"); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_settings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("contextualsearch"), m_appConfig), + pathAndQuery.str(), + xbox_live_api::get_configuration + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result>( + contextual_search_service::deserialize_configuration_result(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +xbox_live_result> +contextual_search_service::deserialize_configuration_result(_In_ const web::json::value& inputJson) +{ + std::error_code errCode = xbox_live_error_code::no_error; + auto internalSet = utils::extract_json_vector( + contextual_config_result::_Deserialize, + inputJson, + _T("serviceconfigs"), + errCode, + true); + if (internalSet.size() == 0) + { + return std::vector(); + } + + auto& firstItem = internalSet[0]; // Only grabbing first item in array since there should only be one when calling this endpoint + return firstItem.get_contextual_search_configured_stats(); +} + +pplx::task>> +contextual_search_service::get_broadcasts( + _In_ uint32_t titleId + ) +{ + return get_broadcasts( + titleId, + 0, + 0, + string_t(), + false, + string_t()); +} + +pplx::task>> +contextual_search_service::get_broadcasts( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ) +{ + auto pathAndQuery = create_broadcasts_url(titleId, skipItems, maxItems, orderByStatName, orderAscending, searchQuery); + RETURN_TASK_CPP_IF_ERR(pathAndQuery, std::vector); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_settings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("contextualsearch"), m_appConfig), + pathAndQuery.payload(), + xbox_live_api::get_broadcasts + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result>( + contextual_search_service::deserialize_broadcasts_result(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +string_t contextual_search_service::convert_operator_to_string( + _In_ contextual_search_filter_operator filterOperator + ) +{ + switch (filterOperator) + { + case contextual_search_filter_operator::greater_than: return _T("gt"); + case contextual_search_filter_operator::greater_than_or_equal: return _T("ge"); + case contextual_search_filter_operator::less_than: return _T("lt"); + case contextual_search_filter_operator::less_than_or_equal: return _T("le"); + case contextual_search_filter_operator::not_equal: return _T("ne"); + case contextual_search_filter_operator::equal: + default: return _T("eq"); + } +} + +pplx::task>> +contextual_search_service::get_broadcasts( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filterStatName, + _In_ contextual_search_filter_operator filterOperator, + _In_ const string_t& filterStatValue + ) +{ + stringstream_t filter; + if( !filterStatName.empty() && !filterStatValue.empty() ) + { + filter << _T("stats:"); + filter << filterStatName; + filter << _T(" "); + filter << convert_operator_to_string(filterOperator); + filter << _T(" '"); + filter << utils::replace_sub_string(filterStatValue, _T("'"), _T("''")); + filter << _T("'"); + } + + return get_broadcasts(titleId, skipItems, maxItems, orderByStatName, orderAscending, filter.str()); +} + +pplx::task> +contextual_search_service::get_game_clips_internal( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ) +{ + auto pathAndQuery = create_game_clips_url(titleId, skipItems, maxItems, orderByStatName, orderAscending, searchQuery); + RETURN_TASK_CPP_IF_ERR(pathAndQuery, contextual_search_game_clips_result); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_settings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("contextualsearch"), m_appConfig), + pathAndQuery.payload(), + xbox_live_api::get_game_clips + ); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_settings; + auto appConfig = m_appConfig; + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([userContext, xboxLiveContextSettings, appConfig, skipItems, titleId](std::shared_ptr response) + { + auto gameClipsResult = contextual_search_game_clips_result::_Deserialize(response->response_body_json()); + auto& result = gameClipsResult.payload(); + + uint32_t itemSize = static_cast(result.items().size()); + uint32_t continuationSkip = skipItems + itemSize; + + // Initialize the request params for get_next() + result._Initialize( + userContext, + xboxLiveContextSettings, + appConfig, + titleId, + continuationSkip + ); + + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +contextual_search_service::get_game_clips( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ) +{ + return get_game_clips_internal( + titleId, + skipItems, + maxItems, + orderByStatName, + orderAscending, + searchQuery + ); +} + + +pplx::task> +contextual_search_service::get_game_clips( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filterStatName, + _In_ contextual_search_filter_operator filterOperator, + _In_ const string_t& filterStatValue + ) +{ + stringstream_t filter; + if (!filterStatName.empty() && !filterStatValue.empty()) + { + filter << _T("stats:"); + filter << filterStatName; + filter << _T(" "); + filter << convert_operator_to_string(filterOperator); + filter << _T(" '"); + filter << utils::replace_sub_string(filterStatValue, _T("'"), _T("''")); + filter << _T("'"); + } + + return get_game_clips_internal( + titleId, + skipItems, + maxItems, + orderByStatName, + orderAscending, + filter.str() + ); +} + +xbox_live_result> +contextual_search_service::deserialize_broadcasts_result(_In_ const web::json::value& inputJson) +{ + if (inputJson.is_null()) return xbox_live_result>(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = utils::extract_json_vector( + contextual_search_broadcast::_Deserialize, + inputJson, + _T("value"), + errc, + true); + + return xbox_live_result>(result, errc); +} + + +xbox_live_result +contextual_search_service::create_broadcasts_url( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& filter + ) +{ + web::uri_builder builder; + + stringstream_t path; + path << _T("/titles/"); + path << titleId; + path << _T("/broadcasts"); + builder.set_path(path.str()); + + if (skipItems > 0) + { + builder.append_query(_T("$skip"), skipItems); + } + + if (maxItems > 0) + { + builder.append_query(_T("$top"), maxItems); + } + + if (!orderByStatName.empty()) + { + stringstream_t queryValue; + queryValue << _T("stats:"); + queryValue << orderByStatName; + queryValue << _T(" "); + queryValue << (orderAscending ? _T("asc") : _T("desc")); + builder.append_query(_T("$orderby"), queryValue.str()); + } + + if (!filter.empty()) + { + builder.append_query(_T("$filter"), filter); + } + + return xbox_live_result(builder.to_string()); +} + +xbox_live_result +contextual_search_service::create_game_clips_url( + _In_ uint32_t titleId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& orderByStatName, + _In_ bool orderAscending, + _In_ const string_t& searchQuery + ) +{ + web::uri_builder builder; + + stringstream_t path; + path << _T("/titles/"); + path << titleId; + path << _T("/gameclips"); + builder.set_path(path.str()); + + if (maxItems > 0) + { + builder.append_query(_T("$top"), maxItems); + } + + if (skipItems > 0) + { + builder.append_query(_T("$skip"), skipItems); + } + + if (!orderByStatName.empty()) + { + stringstream_t queryValue; + queryValue << _T("stats:"); + queryValue << orderByStatName; + queryValue << _T(" "); + queryValue << (orderAscending ? _T("asc") : _T("desc")); + builder.append_query(_T("$orderby"), queryValue.str()); + } + + if (!searchQuery.empty()) + { + builder.append_query(_T("$filter"), searchQuery); + } + + return xbox_live_result(builder.to_string()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CONTEXTUAL_SEARCH_CPP_END diff --git a/Source/Services/Misc/iOS/notification_helper.mm b/Source/Services/Misc/iOS/notification_helper.mm new file mode 100644 index 00000000..ee16cebd --- /dev/null +++ b/Source/Services/Misc/iOS/notification_helper.mm @@ -0,0 +1,105 @@ +#include "pch.h" +#include "notification_helper.h" +#include "utils.h" + + +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +#if XSAPI_I + +xbox_live_result parse_notification(NSDictionary* notificationInfo) +{ + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:notificationInfo + options:0 + error:&error]; + + if (error == nil) + { + return xbox_live_result(xbox_live_error_code::json_error, _T("Error parsing the notification payload!")); + } + else + { + xbox_live_notification result; + string_t notificationStr([[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] UTF8String]); + std::error_code errc; + web::json::value payload = web::json::value::parse(notificationStr, errc); + + if(!errc) + { + string_t title; + string_t body; + + web::json::value aps = utils::extract_json_field(payload, "aps", errc, true); + web::json::value data = utils::extract_json_field(payload, "data", errc, true); + + string_t type = utils::extract_json_string(data, "type", errc, true); + web::json::value xblInfo = utils::extract_json_field(data, "xbl", errc, true); + + web::json::value alert = utils::extract_json_field(aps, "alert", errc, true); + + if(utils::str_icmp(type, _T("xbox_live_game_invite")) == 0) + { + result.type = xbox_live_notification_type::game_invite; + + web::json::value locArgs= utils::extract_json_field(alert, "loc-args", errc, true); + string_t locKey = utils::extract_json_string(alert, "loc-key", errc, true); + string_t titleLocKey = utils::extract_json_string(alert, "title-loc-key", errc, true); + + web::json::array args = utils::extract_json_as_array(locArgs, errc); + std::vector bodyArgs; + + for(auto iter = args.cbegin(); iter != args.cend(); ++iter) + { + bodyArgs.push_back(utils::extract_json_as_string(*iter, errc)); + } + + NSString* titleLocStr = NSLocalizedString([NSString stringWithUTF8String:titleLocKey.c_str()], nil); + NSString* bodyLocStr = NSLocalizedString([NSString stringWithUTF8String:locKey.c_str()], nil); + + //The below snippet formats the localization string one parameter at a time. + stringstream_t ss; + NSArray *items = [bodyLocStr componentsSeparatedByString:@"%"]; + uint32_t index = 0; + for (NSString* item in items) + { + if(item.length > 0) + { + NSString *format = @"%"; + format = [format stringByAppendingString:item]; + ss << [[NSString stringWithFormat:format, [NSString stringWithUTF8String:bodyArgs[index].c_str()]] UTF8String]; + index = MIN(bodyArgs.size(), index + 1); + } + } + + title = [titleLocStr UTF8String]; + body = ss.str(); + } + else if(utils::str_icmp(type, _T("xbox_live_achievement_unlock")) == 0) + { + result.type = xbox_live_notification_type::achievement_unlocked; + + title = utils::extract_json_string(alert, "title", errc, true); + body = utils::extract_json_string(alert, "body", errc, true); + } + else + { + result.type = xbox_live_notification_type::unknown; + } + + result.title = title; + result.body = body; + result.data = xblInfo.serialize(); + + return xbox_live_result(result, errc); + } + + + return xbox_live_result(result, errc); + } +} +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Services/Misc/iOS/title_callable_ui.mm b/Source/Services/Misc/iOS/title_callable_ui.mm new file mode 100644 index 00000000..7d4da6fa --- /dev/null +++ b/Source/Services/Misc/iOS/title_callable_ui.mm @@ -0,0 +1,191 @@ +// +// title_callable_ui.m +// XboxLiveServices +// +// Created by Yun Zhang on 4/12/16. +// Copyright © 2016 Microsoft Corporation. All rights reserved. +// +#include "xsapi/system.h" +#include "xsapi/title_callable_ui.h" +#import "XBLServiceManager.h" +#import +#import "user_impl_ios.h" +#import +#import "XLSCll.h" +#import "UTCIDPNames.h" + +static NSString *const XboxAppStoreLink = @"itms-apps://itunes.apple.com/app/xbox-one-smartglass/id736179781?mt=8"; +using namespace pplx; +using namespace xbox::services; +using namespace xbox::services::system; + +pplx::task> +title_callable_ui::show_profile_card_ui( + _In_ const string_t& targetXboxUserId + ) +{ + auto completionEvent = pplx::task_completion_event>(); + XBLServiceManager *manager = [[XBLServiceManager alloc] init]; + [TCUIManager displayProfileCard:manager.userXuid youXuid:[NSString stringWithUTF8String:targetXboxUserId.c_str()] canAddFriend: manager.privilegeForAddFriend completionBlock:^{ + completionEvent.set(xbox_live_result()); + }]; + + return create_task(completionEvent); +} + +pplx::task> +title_callable_ui::show_friend_finder_ui() +{ + auto completionEvent = pplx::task_completion_event>(); + [TCUIManager displayFriendFinderWithCompletionBlock:^{ + completionEvent.set(xbox_live_result()); + }]; + return create_task(completionEvent); +} + +pplx::task> +title_callable_ui::show_user_profile_ui(_In_ const string_t& targetXboxUserId) +{ + auto completionEvent = pplx::task_completion_event>(); + auto task = create_task(completionEvent); + XLSCll *telemetry = [XLSCll sharedTelemetryManager]; + + NSString *deeplink = [NSString stringWithFormat:@"smartglass://profile?xuid=%@&deepLinkId=%@&deepLinkCaller=%@", [NSString stringWithUTF8String:targetXboxUserId.c_str()], [telemetry getAppSessionId], [telemetry getAppBundleName]]; + + if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:deeplink]]) + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_UserProfile withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"targetXUID" : [NSString stringWithFormat:@"x:%@",[NSString stringWithUTF8String:targetXboxUserId.c_str()]]}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:deeplink]]; + } + else + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_SendToStore withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"intendedAction" : IDP_PageAction_DeepLink_UserProfile}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:XboxAppStoreLink]]; + } + completionEvent.set(xbox_live_result()); + return task; +} + +pplx::task> +title_callable_ui::show_title_hub_ui() +{ + auto completionEvent = pplx::task_completion_event>(); + auto task = create_task(completionEvent); + auto titleId = xbox_live_app_config::get_app_config_singleton()->title_id(); + XLSCll *telemetry = [XLSCll sharedTelemetryManager]; + + NSString *deeplink = [NSString stringWithFormat:@"smartglass://game?titleid=%u&deepLinkId=%@&deepLinkCaller=%@", titleId, [telemetry getAppSessionId], [telemetry getAppBundleName]]; + + if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:deeplink]]) + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_TitleHub withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"targetTitleId" : [NSNumber numberWithInt:titleId]}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:deeplink]]; + + } + else + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_SendToStore withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"intendedAction" : IDP_PageAction_DeepLink_TitleHub}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:XboxAppStoreLink]]; + } + + completionEvent.set(xbox_live_result()); + return task; +} + +pplx::task> +title_callable_ui::show_title_achievements_ui(_In_ uint32_t titleId) +{ + auto completionEvent = pplx::task_completion_event>(); + auto task = create_task(completionEvent); + XLSCll *telemetry = [XLSCll sharedTelemetryManager]; + + NSString *deeplink = [NSString stringWithFormat:@"smartglass://achievement?titleid=%u&deepLinkId=%@&deepLinkCaller=%@", titleId, [telemetry getAppSessionId], [telemetry getAppBundleName]]; + + if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:deeplink]]) + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_TitleAchievements withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"targetTitleId" : [NSNumber numberWithInt:titleId]}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:deeplink]]; + } + else + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_SendToStore withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"intendedAction" : IDP_PageAction_DeepLink_TitleAchievements}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:XboxAppStoreLink]]; + } + + completionEvent.set(xbox_live_result()); + return task; +} + +pplx::task> +title_callable_ui::show_user_settings_ui() +{ + auto completionEvent = pplx::task_completion_event>(); + auto task = create_task(completionEvent); + XLSCll *telemetry = [XLSCll sharedTelemetryManager]; + + NSString *deeplink = [NSString stringWithFormat:@"smartglass://settings?deepLinkId=%@&deepLinkCaller=%@", [telemetry getAppSessionId], [telemetry getAppBundleName]]; + + if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:deeplink]]) + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_UserSettings withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName]}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:deeplink]]; + } + else + { + [telemetry pageActionEvent:IDP_PageAction_DeepLink_SendToStore withData:@{@"deepLinkId" : [telemetry getAppSessionId], + @"deepLinkCaller" : [telemetry getAppBundleName], + @"intendedAction" : IDP_PageAction_DeepLink_UserSettings}]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:XboxAppStoreLink]]; + } + + completionEvent.set(xbox_live_result()); + return task; +} + +pplx::task> +title_callable_ui::show_add_friends_ui() +{ + return pplx::task_from_result>(xbox::services::xbox_live_result(xbox_live_error_code::unsupported)); +} + +pplx::task>> +title_callable_ui::show_player_picker_ui( + _In_ const string_t& promptDisplayText, + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& preselectedXboxUserIds, + _In_ uint32_t minSelectionCount, + _In_ uint32_t maxSelectionCount + ) +{ + return pplx::task_from_result>>(xbox::services::xbox_live_result>(xbox_live_error_code::unsupported)); +} + +pplx::task> +title_callable_ui::show_game_invite_ui( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionReference, + _In_ const string_t& contextStringId + ) +{ + return pplx::task_from_result>(xbox::services::xbox_live_result(xbox_live_error_code::unsupported)); +} + +pplx::task> +title_callable_ui::show_change_friend_relationship_ui( + _In_ const string_t& targetXboxUserId + ) +{ + return pplx::task_from_result>(xbox::services::xbox_live_result(xbox_live_error_code::unsupported)); +} \ No newline at end of file diff --git a/Source/Services/Misc/notification_service.cpp b/Source/Services/Misc/notification_service.cpp new file mode 100644 index 00000000..0724e4f0 --- /dev/null +++ b/Source/Services/Misc/notification_service.cpp @@ -0,0 +1,249 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !UNIT_TEST_SERVICES +#include "notification_service.h" +#include "xbox_system_factory.h" +#include "user_context.h" +#include "user_impl.h" + +using namespace pplx; +using namespace xbox::services::system; + +static const std::chrono::milliseconds RETRY_LENGTH(60 * 1000); +static const int32_t NUM_RETRY_TIMES = 10; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_BEGIN + +std::mutex notification_service::s_notificationSingletonLock; +std::shared_ptr notification_service::s_notificationSingleton; + +std::shared_ptr +notification_service::get_notification_service_singleton() +{ + std::lock_guard guard(s_notificationSingletonLock); + if (s_notificationSingleton == nullptr) + { +#if XSAPI_A + s_notificationSingleton = std::make_shared(); +#elif XSAPI_I + s_notificationSingleton = std::make_shared(); +#elif _WIN32 + s_notificationSingleton = std::make_shared(); +#endif + } + return s_notificationSingleton; +} + +pplx::task> +notification_service::subscribe_to_notifications( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + if (m_isInitialized) + { + return pplx::task_from_result>(xbox_live_result(xbox_live_error_code::logic_error, "already is initialized")); + } + + m_isInitialized = true; + XSAPI_ASSERT(userContext != nullptr); + XSAPI_ASSERT(xboxLiveContextSettings != nullptr); + XSAPI_ASSERT(appConfig != nullptr); + + m_userContext = std::move(userContext); + m_xboxLiveContextSettings = std::move(xboxLiveContextSettings); + m_appConfig = std::move(appConfig); + + return subscribe_to_notifications(); +} + +pplx::task> +notification_service::unsubscribe_from_notifications() +{ + if (m_endpointId.empty()) + { + return pplx::task_from_result>(xbox_live_result(xbox_live_error_code::logic_error, "endpointId is empty")); + } + return unsubscribe_from_notifications_helper(m_endpointId); +} + +pplx::task> +notification_service::unsubscribe_from_notifications(_In_ const string_t& endpointId) +{ + if (endpointId.empty()) + { + LOG_WARN("unsubscribe failed. endpoint ID empty"); + return pplx::task_from_result>(xbox_live_result(xbox_live_error_code::invalid_argument, "endpointId is an invalid argument")); + } + return unsubscribe_from_notifications_helper(endpointId); +} + +pplx::task> +notification_service::unsubscribe_from_notifications_helper( + _In_ const string_t& endpointId + ) +{ + m_isInitialized = false; + auto subpath = _T("/system/notifications/endpoints/") + endpointId; + auto endpoint = utils::create_xboxlive_endpoint(_T("notify"), m_appConfig); + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("DELETE"), + endpoint, + subpath, + xbox_live_api::subscribe_to_notifications + ); + + std::weak_ptr thisWeakPtr = shared_from_this(); + return httpCall->get_response_with_auth(m_userContext, http_call_response_body_type::json_body) + .then([thisWeakPtr](std::shared_ptr t) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + + if (pThis != nullptr) + { + if (t->err_code()) + { + LOGS_ERROR << _T("notification service attempt failed\n"); + LOGS_ERROR << _T("http status code: "); + LOGS_ERROR << t->http_status(); + LOGS_ERROR << t->err_message().c_str(); + + return xbox_live_result(t->err_code(), t->err_message()); + } + + pThis->m_endpointId = _T(""); + return xbox_live_result(); + } + + return xbox_live_result(xbox_live_error_code::runtime_error, "pThis was null after trying to get auth"); + }); +} + +pplx::task> +notification_service::subscribe_to_notifications_helper( + _In_ const string_t& applicationInstanceId, + _In_ const string_t& uriData, + _In_ const string_t& platform, + _In_ const string_t& deviceName, + _In_ const string_t& platformVersion, + _In_ const std::vector notificationFilterEnum + ) +{ + m_isInitialized = true; + stringstream_t str; + str << xbox_live_app_config::get_app_config_singleton()->title_id(); + string_t titleId = str.str(); + web::json::value payload; + payload[_T("systemId")] = web::json::value::string(applicationInstanceId); + payload[_T("endpointUri")] = web::json::value::string(uriData); + payload[_T("platform")] = web::json::value::string(platform); + payload[_T("platformVersion")] = web::json::value::string(platformVersion); +#if XSAPI_I + payload[_T("transport")] = web::json::value::string(_T("NotiHub")); + payload[_T("transportPath")] = web::json::value::string(xbox_live_app_config::get_app_config_singleton()->_Apns_Environment()); +#endif + if (!deviceName.empty()) + { + payload[_T("deviceName")] = web::json::value::string(deviceName); + } + payload[_T("locale")] = web::json::value::string(utils::get_locales()); + payload[_T("titleId")] = web::json::value::string(titleId); + + web::json::value filterJson; + uint32_t i = 0; + for (auto& notificationFilter : notificationFilterEnum) + { + web::json::value filterObj; + filterObj[_T("action")] = web::json::value::string(_T("Include")); + filterObj[_T("source")] = web::json::value(notificationFilter.sourceType); + filterObj[_T("type")] = web::json::value(notificationFilter.type); + filterJson[i] = filterObj; + ++i; + } + + payload[_T("filters")] = filterJson; + auto endpoint = utils::create_xboxlive_endpoint(_T("notify"), m_appConfig); + + std::weak_ptr thisWeakPtr = shared_from_this(); + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto task = pplx::create_task([thisWeakPtr, userContext, endpoint, xboxLiveContextSettings, payload]() + { + int32_t numRetryTime = NUM_RETRY_TIMES; + std::error_code xboxLiveResultCode; + do + { + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + xboxLiveContextSettings, + _T("POST"), + endpoint, + _T("/system/notifications/endpoints"), + xbox_live_api::subscribe_to_notifications + ); + + httpCall->set_request_body(payload.serialize()); + + auto result = httpCall->get_response_with_auth(userContext, http_call_response_body_type::json_body) + .then([thisWeakPtr](pplx::task> t0) + { + auto t = t0.get(); + std::shared_ptr pThis(thisWeakPtr.lock()); + + if (pThis == nullptr) + { + return xbox_live_result(xbox_live_error_code::runtime_error, "pThis is null after trying to get auth"); + } + + auto responseJson = t->response_body_json(); + std::error_code errc; + pThis->m_endpointId = utils::extract_json_string(responseJson, _T("endpointId"), errc); + auto localConfig = xbox_system_factory::get_factory()->create_local_config(); + auto localConfigResult = localConfig->write_value_to_local_storage(pThis->ENDPOINT_ID_CACHE_NAME, pThis->m_endpointId); + if (localConfigResult.err()) + { + LOG_ERROR("Writing endpoint id to local config failed"); + } + if (t->err_code() || errc) + { + stringstream_t str; + str << _T("http status code: "); + str << t->http_status(); + str << t->err_message().c_str(); + return xbox_live_result(errc); + } + + return xbox_live_result(); + }).get(); + xboxLiveResultCode = result.err(); + + --numRetryTime; + if (xboxLiveResultCode != xbox_live_error_code::no_error) + { + LOG_WARN("retrying notification"); + std::this_thread::sleep_for(std::chrono::duration_cast(RETRY_LENGTH)); + } + else + { + numRetryTime = 0; + } + + } while (numRetryTime > 0); + + return xbox_live_result(xboxLiveResultCode); + }); + + return task; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_NOTIFICATION_CPP_END +#endif \ No newline at end of file diff --git a/Source/Services/Misc/notification_service.h b/Source/Services/Misc/notification_service.h new file mode 100644 index 00000000..04a59f16 --- /dev/null +++ b/Source/Services/Misc/notification_service.h @@ -0,0 +1,134 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/types.h" +#include "xsapi/system.h" + +namespace xbox { namespace services { namespace notification { + +enum notification_filter_source_type +{ + media_presence = 1, + presence_online, + broadcast, + message, + party_invite_360, + multiplayer +}; + +struct notification_filter +{ + notification_filter_source_type sourceType; + uint32_t type; +}; + +class notification_service : public std::enable_shared_from_this +{ +public: + static std::shared_ptr get_notification_service_singleton(); + + virtual pplx::task> subscribe_to_notifications( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + virtual pplx::task> unsubscribe_from_notifications(); + virtual pplx::task> unsubscribe_from_notifications(_In_ const string_t& endpointId); + +protected: + notification_service() = default; + virtual pplx::task> subscribe_to_notifications() = 0; + virtual pplx::task> subscribe_to_notifications_helper( + _In_ const string_t& applicationInstanceId, + _In_ const string_t& uriData, + _In_ const string_t& platform, + _In_ const string_t& deviceName, + _In_ const string_t& platformVersion, + _In_ const std::vector notificationFilterEnum + ); + + pplx::task> unsubscribe_from_notifications_helper( + _In_ const string_t& endpointId + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::unordered_map> m_userContexts; + + const string_t ENDPOINT_ID_CACHE_NAME = _T("endpointId"); + bool m_isInitialized = false; + string_t m_endpointId; + + static std::mutex s_notificationSingletonLock; + static std::shared_ptr s_notificationSingleton; +}; + +#ifdef _WIN32 +class notification_service_windows : public notification_service +{ +public: + notification_service_windows() = default; + + pplx::task> subscribe_to_notifications( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) override; + +protected: + pplx::task> subscribe_to_notifications() override; + +private: + void on_push_notification_recieved( + _In_ Windows::Networking::PushNotifications::PushNotificationChannel ^sender, + _In_ Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs ^args + ); +}; +#elif XSAPI_A +class notification_service_android : public notification_service +{ +public: + static void notificiation_registration_callback(JNIEnv*, jclass, jstring notificationData, jboolean isCached); + + notification_service_android(); + + pplx::task> subscribe_to_notifications( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) override; + +protected: + pplx::task> subscribe_to_notifications() override; + +private: + bool m_isInitializing; + + pplx::task> subscribe_to_notifications_finish( + _In_ const string_t& registrationToken, + _In_ const std::shared_ptr& pThis + ); + + static pplx::task_completion_event s_notificationRegisterEvent; +}; +#elif XSAPI_I +class notification_service_ios : public notification_service +{ +public: + notification_service_ios() = default; +protected: + pplx::task> subscribe_to_notifications() override; + static pplx::task_completion_event s_notificationRegisterEvent; +}; +#endif + +}}} \ No newline at end of file diff --git a/Source/Services/Misc/string_service.cpp b/Source/Services/Misc/string_service.cpp new file mode 100644 index 00000000..704cc1b0 --- /dev/null +++ b/Source/Services/Misc/string_service.cpp @@ -0,0 +1,103 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xbox_system_factory.h" +#include "xsapi/system.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_BEGIN + +string_service::string_service() +{ +} + +string_service::string_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +string_service::verify_string(_In_ const string_t& stringToVerify) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(stringToVerify, verify_string_result, "stringToVerify is empty"); + + std::vector stringsToVerify; + stringsToVerify.push_back(stringToVerify); + return verify_strings(std::vector(stringsToVerify)) + .then([](xbox_live_result> results) + { + auto& stringResult = results.payload(); + if (stringResult.empty() && results.err() == xbox_live_error_condition::generic_error) + { + return xbox_live_result(xbox_live_error_code::json_error, "string validation result not fond"); + } + else if (stringResult.empty()) + { + return xbox_live_result(results.err(), results.err_message()); + } + + return xbox_live_result( + stringResult[0], + results.err(), + results.err_message() + ); + }); +} + +pplx::task>> +string_service::verify_strings(_In_ const std::vector& stringsToVerify) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(stringsToVerify, std::vector, "stringsToVerify is empty"); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("client-strings"), m_appConfig), + _T("/system/strings/validate"), + xbox_live_api::verify_strings + ); + + auto request = web::json::value::object(); + auto& stringsJson = request[_T("stringstoVerify")]; + int i = 0; + for (const auto& stringToVerify : stringsToVerify) + { + stringsJson[i++] = web::json::value::string(stringToVerify); + } + + httpCall->set_request_body(request.serialize()); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + return httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto result = utils::extract_xbox_live_result_json_vector( + verify_string_result::_Deserialize, + response->response_body_json(), + _T("verifyStringResult"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + result, + response + ); + }); + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_END diff --git a/Source/Services/Misc/verify_string_result.cpp b/Source/Services/Misc/verify_string_result.cpp new file mode 100644 index 00000000..3a1bcf9d --- /dev/null +++ b/Source/Services/Misc/verify_string_result.cpp @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/system.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_BEGIN + +verify_string_result::verify_string_result() +{ +} + +verify_string_result::verify_string_result( + verify_string_result_code resultCode, + string_t firstOffendingSubstring + ): + m_resultCode(resultCode), + m_firstOffendingSubstring(std::move(firstOffendingSubstring)) +{ +} + +verify_string_result_code +verify_string_result::result_code() const +{ + return m_resultCode; +} + +const string_t& +verify_string_result::first_offending_substring() const +{ + return m_firstOffendingSubstring; +} + +xbox_live_result +verify_string_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = verify_string_result( + static_cast(utils::extract_json_int(json, _T("resultCode"), errc)), + utils::extract_json_string(json, _T("offendingString"), errc) + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_END diff --git a/Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.cpp new file mode 100644 index 00000000..0d64eb28 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "FindMatchCompletedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +FindMatchCompletedEventArgs::FindMatchCompletedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +FindMatchCompletedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.h new file mode 100644 index 00000000..b585b74d --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/FindMatchCompletedEventArgs_WinRT.h @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "MatchStatus_WinRT.h" +#include "MultiplayerMeasurementFailure_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Contains information for an event that indicates when a multiplayer match is found. +/// +public ref class FindMatchCompletedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// Provides the current matchmaking status. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(MatchStatus, match_status, Microsoft::Xbox::Services::Multiplayer::Manager::MatchStatus); + + /// + /// The cause of why the initialization failed, or MultiplayerMeasurementFailure::None if there was no failure. + /// Set when transitioning out of the "joining" or "measuring" stage if this member doesn't pass. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(InitializationFailureCause, initialization_failure_cause, Microsoft::Xbox::Services::Multiplayer::MultiplayerMeasurementFailure); + +internal: + FindMatchCompletedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.cpp new file mode 100644 index 00000000..bcf0d4c0 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "HostChangedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +HostChangedEventArgs::HostChangedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +HostChangedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +MultiplayerMember^ +HostChangedEventArgs::HostMember::get() +{ + return ref new MultiplayerMember(m_cppObj->host_member()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.h new file mode 100644 index 00000000..400478bb --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/HostChangedEventArgs_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "MultiplayerMember_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a new host member has been set. +/// +public ref class HostChangedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// The new host member. If an existing host leaves, the HostMember will be nullptr. + /// + property MultiplayerMember^ HostMember + { + MultiplayerMember^ get(); + } + +internal: + HostChangedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/JoinInProgressState_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/JoinInProgressState_WinRT.h new file mode 100644 index 00000000..456f0ff4 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/JoinInProgressState_WinRT.h @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Defines values used to indicate join in progress state on who can join your game. +/// +public enum class Joinability +{ + /// + /// Joinability not set or no lobby exists yet. + /// + None = xbox::services::multiplayer::manager::joinability::none, + + /// + /// Default value. The lobby is joinable by users who are followed by an existing member of the session. + /// + JoinableByFriends = xbox::services::multiplayer::manager::joinability::joinable_by_friends, + + /// + /// The lobby is joinable only via an invite. + /// + InviteOnly = xbox::services::multiplayer::manager::joinability::invite_only, + + /// + /// This option will close the lobby only when a game is in progress. All other times, + /// it will keep the lobby open for invite_only so invitees can join when no game is in progress. + /// + DisableWhileGameInProgress = xbox::services::multiplayer::manager::joinability::disable_while_game_in_progress, + + /// + /// This option will close the lobby immediately. + /// + Closed = xbox::services::multiplayer::manager::joinability::closed +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.cpp new file mode 100644 index 00000000..779736b7 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "JoinLobbyCompletedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +JoinLobbyCompletedEventArgs::JoinLobbyCompletedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +JoinLobbyCompletedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.h new file mode 100644 index 00000000..1ead316a --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/JoinLobbyCompletedEventArgs_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when the client joins a lobby. Once join succeeds, the member is now +/// part of the lobby session, and can use data in the session to connect to other lobby members. +/// To join a friend lobby, call join_lobby() operation using the handleId you back get from +/// multiplayer_service::get_activities_for_social_group. If the user accepts an invite or joined a friends game via a shell UI, +/// the title will get a protocol activation. If the invited user is not added +/// via local_member_manager::add_local_user(), then join_lobby() will fail and provide the invited_xbox_user_id() +/// that the invite was sent for as part of the join_lobby_completed_event_args() +/// +public ref class JoinLobbyCompletedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// Invited Xbox User ID of the member that. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(InvitedXboxUserId, invited_xbox_user_id); + +internal: + JoinLobbyCompletedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MatchStatus_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MatchStatus_WinRT.h new file mode 100644 index 00000000..2ba93a14 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MatchStatus_WinRT.h @@ -0,0 +1,110 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Defines values used to indicate status for the matchmaking stages. +/// +public enum class MatchStatus +{ + /// + /// Indicates no matchmaking search has been started. + /// + None = xbox::services::multiplayer::manager::match_status::none, + + /// + /// Indicates that a match ticket was submitted for matchmaking. + /// + SubmittingMatchTicket = xbox::services::multiplayer::manager::match_status::submitting_match_ticket, + + /// + /// Indicates the matchmaking is still searching. + /// + Searching = xbox::services::multiplayer::manager::match_status::searching, + + /// + /// Indicates the matchmaking search has found a match. + /// + Found = xbox::services::multiplayer::manager::match_status::found, + + /// + /// Joining initialization stage. + /// Matchmaking creates the game session and adds users to it. + /// The client has up to the joining timeout to join the session during this phase. + /// + Joining = xbox::services::multiplayer::manager::match_status::joining, + + /// + /// Waiting for remote clients to join the game session. + /// The client has up to the joining timeout to join the session during this phase. + /// + WaitingForRemoteClientsToJoin = xbox::services::multiplayer::manager::match_status::waiting_for_remote_clients_to_join, + + /// + /// Measuring initialization stage. + /// Stage where QoS measurement happens. + /// The client has up to the measurement timeout to upload qos measurements to the service during this phase. + /// + Measuring = xbox::services::multiplayer::manager::match_status::measuring, + + /// + /// Uploading QoS measurement results to the service. + /// The client has up to the measurement timeout to upload qos measurements to the service during this phase. + /// + UploadingQosMeasurements = xbox::services::multiplayer::manager::match_status::uploading_qos_measurements, + + /// + /// Waiting for remote clients to upload QoS measurement results to the service. + /// The client has up to the measurement timeout to upload qos measurements to the service during this phase. + /// + WaitingForRemoteClientsToUploadQos = xbox::services::multiplayer::manager::match_status::waiting_for_remote_clients_to_upload_qos, + + /// + /// Evaluating initialization stage. + /// If auto evaluate is true, then this stage is skipped. + /// Otherwise the title will do its own evaluation. + /// + Evaluating = xbox::services::multiplayer::manager::match_status::evaluating, + + /// + /// Match was found and QoS measurement was successful. + /// + Completed = xbox::services::multiplayer::manager::match_status::completed, + + /// + /// If the match that was found was not successful and is resubmitting. + /// + Resubmitting = xbox::services::multiplayer::manager::match_status::resubmitting, + + /// + /// Indicates the matchmaking search has expired. + /// + Expired = xbox::services::multiplayer::manager::match_status::expired, + + /// + /// Indicates that matchmaking is in the process of canceling the search. + /// + Canceling = xbox::services::multiplayer::manager::match_status::canceling, + + /// + /// Indicates the matchmaking search has been canceled. + /// + Canceled = xbox::services::multiplayer::manager::match_status::canceled, + + /// + /// Failed initialization stage. + /// The initialization failed. + /// + Failed = xbox::services::multiplayer::manager::match_status::failed, +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.cpp new file mode 100644 index 00000000..e180f46d --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.cpp @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "MemberJoinedEventArgs_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MemberJoinedEventArgs::MemberJoinedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +MemberJoinedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +IVectorView^ +MemberJoinedEventArgs::Members::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->members())->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.h new file mode 100644 index 00000000..64149570 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MemberJoinedEventArgs_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "MultiplayerMember_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a new game member joins the game. +/// +public ref class MemberJoinedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// A list of members that joined the game. + /// + property Windows::Foundation::Collections::IVectorView^ Members + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + MemberJoinedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.cpp new file mode 100644 index 00000000..f755bb8a --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.cpp @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "MemberLeftEventArgs_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MemberLeftEventArgs::MemberLeftEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +MemberLeftEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +IVectorView^ +MemberLeftEventArgs::Members::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->members())->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.h new file mode 100644 index 00000000..41900f36 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MemberLeftEventArgs_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "MultiplayerMember_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a new game member joins the game. +/// +public ref class MemberLeftEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// A list of members that joined the game. + /// + property Windows::Foundation::Collections::IVectorView^ Members + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + MemberLeftEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.cpp new file mode 100644 index 00000000..d475e84c --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "MemberPropertyChangedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MemberPropertyChangedEventArgs::MemberPropertyChangedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +MemberPropertyChangedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +MultiplayerMember^ +MemberPropertyChangedEventArgs::Member::get() +{ + return ref new MultiplayerMember(m_cppObj->member()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.h new file mode 100644 index 00000000..27c4c48b --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MemberPropertyChangedEventArgs_WinRT.h @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "MultiplayerMember_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a game member property has been added or modified. +/// +public ref class MemberPropertyChangedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// The member whose property changed. + /// + property MultiplayerMember^ Member + { + MultiplayerMember^ get(); + } + + /// + /// The JSON of the property that changed. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(Properties, properties); + +internal: + MemberPropertyChangedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventArgs_WinRT.h new file mode 100644 index 00000000..a6b3a1e9 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventArgs_WinRT.h @@ -0,0 +1,18 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer_manager.h" +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +public interface class MultiplayerEventArgs +{ +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventType_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventType_WinRT.h new file mode 100644 index 00000000..3dabefe3 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEventType_WinRT.h @@ -0,0 +1,161 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Defines values used to indicate change types for a multiplayer game. +/// +public enum class MultiplayerEventType +{ + /// + /// Indicates the user was added. + /// + UserAdded = xbox::services::multiplayer::manager::multiplayer_event_type::user_added, + + /// + /// Indicates the user was removed. + /// + UserRemoved = xbox::services::multiplayer::manager::multiplayer_event_type::user_removed, + + /// + /// Indicates a new member has joined. + /// + MemberJoined = xbox::services::multiplayer::manager::multiplayer_event_type::member_joined, + + /// + /// Indicates a member has left. + /// + MemberLeft = xbox::services::multiplayer::manager::multiplayer_event_type::member_left, + + /// + /// Indicates a member property has changed. + /// + MemberPropertyChanged = xbox::services::multiplayer::manager::multiplayer_event_type::member_property_changed, + + /// + /// Indicates that the set_local_member_properties() or delete_local_member_properties() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write local member properties by calling the set_local_member_properties() operation. + /// + LocalMemberPropertyWriteCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::local_member_property_write_completed, + + /// + /// Indicates that the set_local_member_connection_address() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write local member properties by calling the set_local_member_connection_address() operation. + /// + LocalMemberConnectionAddressWriteCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::local_member_connection_address_write_completed, + + /// + /// Indicates a game property has changed. + /// + SessionPropertyChanged = xbox::services::multiplayer::manager::multiplayer_event_type::session_property_changed, + + /// + /// Indicates that the set_synchronized_properties() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write synchronized properties by calling the set_properties() operation. + /// + SessionPropertyWriteCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::session_property_write_completed, + + /// + /// Indicates that the set_synchronized_properties() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write synchronized properties by calling the set_synchronized_properties() operation. + /// + SessionSynchronizedPropertyWriteCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::session_synchronized_property_write_completed, + + /// + /// Indicates host has changed. + /// + HostChanged = xbox::services::multiplayer::manager::multiplayer_event_type::host_changed, + + /// + /// Indicates that the set_synchronized_host() operation has completed. + /// Upon completion, the game can view the err() to see if the write succeeded. + /// A game can be write synchronized host by calling the set_synchronized_host() operation. + /// + SynchronizedHostWriteCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::synchronized_host_write_completed, + + /// + /// Indicates that the joinability value has changed. + /// A game can be change the state by calling the set_joinability() operation. + /// + JoinabilityStateChanged = xbox::services::multiplayer::manager::multiplayer_event_type::joinability_state_changed, + + /// + /// Fired when a match has been found, and the client has joined the target game session. + /// When this event occurs, title should provide qos measurement results between itself and a list of remote clients. + /// Note: If your title does not require QoS (based on the session template), this event will not be triggered. + /// + PerformQosMeasurements = xbox::services::multiplayer::manager::multiplayer_event_type::perform_qos_measurements, + + /// + /// Indicates the find_match() operation has completed. + /// + FindMatchCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::find_match_completed, + + /// + /// Indicates that the join_game() operation has completed. Once the join succeeds, + /// the member is now part of the game session, and can use data in the session + // to connect to other game members. + /// A game can be joined by calling the join_game() operation. + /// + JoinGameCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::join_game_completed, + + /// + /// Indicates that the leave_game() operation has completed. After recieving this event, + /// the game session object will be set to null. You can join another game by calling + /// join_game() or join_game_from_lobby(). + /// + LeaveGameCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::leave_game_completed, + + /// + /// Indicates that the join_lobby() operation has completed. Once the join succeeds, + /// the member is now part of the lobby session, and can use data in the session + // to connect to other lobby members. + /// + JoinLobbyCompleted = xbox::services::multiplayer::manager::multiplayer_event_type::join_lobby_completed, + + /// + /// Fired when the title's connection to MPSD using the real-time activity service is lost. + /// When this event occurs, the title should shut down the multiplayer. + /// + ClientDisconnectedFromMultiplayerService = xbox::services::multiplayer::manager::multiplayer_event_type::client_disconnected_from_multiplayer_service, + + /// + /// Indicates that the invite API operation has been completed. + /// + InviteSent = xbox::services::multiplayer::manager::multiplayer_event_type::invite_sent, + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Triggered when the tournament's team registration state changes. The event_args object + /// should be cast to a tournament_registration_state_changed_event_args object for more information. + /// + TournamentRegistrationStateChanged = xbox::services::multiplayer::manager::multiplayer_event_type::tournament_registration_state_changed, + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Triggered when a new game has been scheduled. The event_args object + /// should be cast to a tournament_game_session_ready_event_args object for more information. + /// + TournamentGameSessionReady = xbox::services::multiplayer::manager::multiplayer_event_type::tournament_game_session_ready, + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Triggered when arbitration is complete and game results have been written to the game session. + /// + ArbitrationComplete = xbox::services::multiplayer::manager::multiplayer_event_type::arbitration_complete +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.cpp new file mode 100644 index 00000000..c7ad12f3 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.cpp @@ -0,0 +1,170 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "MultiplayerEvent_WinRT.h" +#include "UserAddedEventArgs_WinRT.h" +#include "UserRemovedEventArgs_WinRT.h" +#include "MemberJoinedEventArgs_WinRT.h" +#include "MemberLeftEventArgs_WinRT.h" +#include "MemberPropertyChangedEventArgs_WinRT.h" +#include "SessionPropertyChangedEventArgs_WinRT.h" +#include "HostChangedEventArgs_WinRT.h" +#include "JoinLobbyCompletedEventArgs_WinRT.h" +#include "FindMatchCompletedEventArgs_WinRT.h" +#include "PerformQosMeasurementsEventArgs_WinRT.h" +#include "TournamentRegistrationStateChangedEventArgs_WinRT.h" +#include "TournamentGameSessionReadyEventArgs_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MultiplayerEvent::MultiplayerEvent( + _In_ multiplayer_event cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + if (m_cppObj.err()) + { + m_errorCode = ref new Platform::Exception(xbox::services::utils::convert_xbox_live_error_code_to_hresult(m_cppObj.err())); + } + + m_errorMessage = ref new Platform::String(utility::conversions::utf8_to_utf16(m_cppObj.err_message()).c_str()); + m_context = m_cppObj.context(); +} + +const multiplayer_event& +MultiplayerEvent::GetCppObj() const +{ + return m_cppObj; +} + +int +MultiplayerEvent::ErrorCode::get() +{ + if (m_errorCode == nullptr) + { + return 0; + } + + return m_errorCode->HResult; +} + +Platform::String^ +MultiplayerEvent::ErrorMessage::get() +{ + return m_errorMessage; +} + +context_t +MultiplayerEvent::Context::get() +{ + return m_context; +} + +MultiplayerEventArgs^ +MultiplayerEvent::EventArgs::get() +{ + switch (m_cppObj.event_type()) + { + case multiplayer_event_type::user_added: + { + return ref new UserAddedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::user_removed: + { + return ref new UserRemovedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::member_joined: + { + return ref new MemberJoinedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::member_left: + { + return ref new MemberLeftEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::member_property_changed: + { + return ref new MemberPropertyChangedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::session_property_changed: + { + return ref new SessionPropertyChangedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::host_changed: + { + return ref new HostChangedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::join_lobby_completed: + { + return ref new JoinLobbyCompletedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::find_match_completed: + { + return ref new FindMatchCompletedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::perform_qos_measurements: + { + return ref new PerformQosMeasurementsEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::tournament_registration_state_changed: + { + return ref new TournamentRegistrationStateChangedEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + case multiplayer_event_type::tournament_game_session_ready: + { + return ref new TournamentGameSessionReadyEventArgs( + std::dynamic_pointer_cast(m_cppObj.event_args()) + ); + } + + default: + { + return nullptr; + } + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.h new file mode 100644 index 00000000..70cc627f --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerEvent_WinRT.h @@ -0,0 +1,82 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer_manager.h" +#include "MultiplayerEventType_WinRT.h" +#include "MultiplayerSessionType_WinRT.h" +#include "MultiplayerEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Represents a multiplayer event. +/// +public ref class MultiplayerEvent sealed +{ +public: + /// + /// The error code indicating the result of the operation. + /// + property int ErrorCode + { + int get(); + }; + + /// + /// Returns call specific debug information if join fails + /// It is not localized, so only use for debugging purposes. + /// + property Platform::String^ ErrorMessage + { + Platform::String^ get(); + }; + + /// + /// A pointer to the application-defined data passed into the set_ methods. + /// + property context_t Context + { + context_t get(); + }; + + /// + /// Type of the event triggered. + /// + DEFINE_PROP_GET_ENUM_OBJ(EventType, event_type, Microsoft::Xbox::Services::Multiplayer::Manager::MultiplayerEventType); + + /// + /// You need to cast this to one of the event arg classes to retrieve the data for that particular event. + /// + property MultiplayerEventArgs^ EventArgs + { + MultiplayerEventArgs^ get(); + } + + /// + /// The multiplayer session type this event was triggered for. Depending upon the session type, + /// you can then retrieve the latest lobby or game session from the multiplayer_manager class. + /// + DEFINE_PROP_GET_ENUM_OBJ(SessionType, session_type, Microsoft::Xbox::Services::Multiplayer::Manager::MultiplayerSessionType); + +internal: + MultiplayerEvent( + _In_ xbox::services::multiplayer::manager::multiplayer_event cppObj + ); + + const xbox::services::multiplayer::manager::multiplayer_event& GetCppObj() const; + +private: + xbox::services::multiplayer::manager::multiplayer_event m_cppObj; + Platform::Exception^ m_errorCode; + Platform::String^ m_errorMessage; + context_t m_context; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.cpp new file mode 100644 index 00000000..dd00fe1f --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.cpp @@ -0,0 +1,150 @@ +////********************************************************* +//// +//// Copyright (c) Microsoft. All rights reserved. +//// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +//// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +//// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +//// +////********************************************************* + +#include "pch.h" +#include "MultiplayerGameSession_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Multiplayer; +using namespace Microsoft::Xbox::Services::Tournaments; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MultiplayerGameSession::MultiplayerGameSession( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); + UpdateCppObj(cppObj); +} + +MultiplayerSessionReference^ +MultiplayerGameSession::SessionReference::get() +{ + return m_sessionReference; +} + +MultiplayerMember^ +MultiplayerGameSession::Host::get() +{ + if (m_cppObj->host() == nullptr) + { + return nullptr; + } + + return ref new MultiplayerMember(m_cppObj->host()); +} + +IVectorView^ +MultiplayerGameSession::Members::get() +{ + return m_members->GetView(); + +} + +MultiplayerSessionConstants^ +MultiplayerGameSession::SessionConstants::get() +{ + return m_sessionConstants; +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerGameSession::TournamentTeams::get() +{ + return m_teams->GetView(); +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerGameSession::TournamentTeamResults::get() +{ + return m_tournamentTeamResults->GetView(); +} + +std::shared_ptr +MultiplayerGameSession::GetCppObj() const +{ + return m_cppObj; +} + +void +MultiplayerGameSession::UpdateCppObj( + _In_ std::shared_ptr cppObj + ) +{ + m_cppObj = cppObj; + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj->session_reference()); + m_sessionConstants = ref new MultiplayerSessionConstants(m_cppObj->session_constants()); + m_teams = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj->tournament_teams()); + m_tournamentTeamResults = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj->tournament_team_results()); + m_members = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->members()); +} + +bool +MultiplayerGameSession::IsHost( + _In_ Platform::String^ xboxUserId + ) +{ + return m_cppObj->is_host(STRING_T_FROM_PLATFORM_STRING(xboxUserId)); +} + +void +MultiplayerGameSession::SetProperties( + _In_ Platform::String^ name, + _In_ Platform::String^ valueJson, + _In_opt_ context_t context + ) +{ + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + auto result = m_cppObj->set_properties( + STRING_T_FROM_PLATFORM_STRING(name), + valueJsonString, + context + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerGameSession::SetSynchronizedProperties( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ) +{ + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + auto result = m_cppObj->set_synchronized_properties( + STRING_T_FROM_PLATFORM_STRING(name), + valueJsonString, + context + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerGameSession::SetSynchronizedHost( + _In_ MultiplayerMember^ gameHost, + _In_opt_ context_t context + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(gameHost); + + auto result = m_cppObj->set_synchronized_host(gameHost->GetCppObj(), context); + THROW_IF_ERR(result); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.h new file mode 100644 index 00000000..df6671b4 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerGameSession_WinRT.h @@ -0,0 +1,157 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/multiplayer_manager.h" +#include "MultiplayerMember_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MultiplayerSessionRestriction_WinRT.h" +#include "MultiplayerSessionConstants_WinRT.h" +#include "TournamentTeamResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Manager for managing members that are local to this device. +/// +public ref class MultiplayerGameSession sealed +{ +public: + /// + /// A unique ID to the session used to query trace logs for entries that relate to the session. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(CorrelationId, correlation_id); + + /// + /// Object containing identifying information for the session. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ SessionReference + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ get(); + } + + /// + /// A collection of members that are in the lobby. When a friend accepts a game invite, + /// members will be added to the lobby. + /// + property Windows::Foundation::Collections::IVectorView^ Members + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// Returns the host member for the game. + /// There could be multiple hosts if there are multiple users on the same host device. + /// This returns user with the lowest index for that host device. + /// + property MultiplayerMember^ Host { MultiplayerMember^ get(); } + + /// + /// JSON string that specify the custom properties for the game. These can be changed anytime. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(Properties, properties); + + /// + /// A set of constants associated with this session. These can only be set through the session template. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionConstants^ SessionConstants + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionConstants^ get(); + } + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Teams currently participating in this tournament game. + /// + property Windows::Foundation::Collections::IMapView^ TournamentTeams + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Tournament team results for the game. + /// + property Windows::Foundation::Collections::IMapView^ TournamentTeamResults + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// Whether or not the Xbox User ID is the host. + /// + /// The Xbox User ID of the user + bool IsHost( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Set a custom game property to the specified JSON string. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + void SetProperties( + _In_ Platform::String^ name, + _In_ Platform::String^ valueJson, + _In_opt_ context_t context + ); + + /// + /// Sets a custom property to the specified JSON string using multiplayer_session_write_mode::synchronized_update. + /// Use this method to resolve any conflicts between devices while trying to set properties to a shared portion that other + /// devices can also modify. It ensures that updates to the session are atomic. If writing to non-sharable properties, use set_properties() instead. + /// The service may reject your request if a race condition occurred (due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type write_synchronized_properties_completed through do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + void SetSynchronizedProperties( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ); + + /// + /// Sets the host for the game using multiplayer_session_write_mode::synchronized_update. Use this method to resolve + /// any conflicts between devices trying to set the host at the same time. It ensures that updates to the session are atomic. + /// The service may reject your request if a race condition occurred(due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type write_synchronized_host_completed through do_work(). + /// + /// The host member. + void SetSynchronizedHost( + _In_ MultiplayerMember^ gameHost, + _In_opt_ context_t context + ); + +internal: + MultiplayerGameSession( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + + void UpdateCppObj( + _In_ std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; + Windows::Foundation::Collections::IVector^ m_members; + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ m_sessionReference; + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionConstants^ m_sessionConstants; + Platform::Collections::Map^ m_teams; + Platform::Collections::Map^ m_tournamentTeamResults; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.cpp new file mode 100644 index 00000000..51a369a3 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.cpp @@ -0,0 +1,288 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "MultiplayerLobbySession_WinRT.h" +#include "XboxLiveContext_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Multiplayer; +using namespace Microsoft::Xbox::Services::Tournaments; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MultiplayerLobbySession::MultiplayerLobbySession( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); + + m_localMembers = ref new Platform::Collections::Vector(); + m_lobbyMembers = ref new Platform::Collections::Vector(); +} + +IVectorView^ +MultiplayerLobbySession::LocalMembers::get() +{ + return m_localMembers->GetView(); +} + +IVectorView^ +MultiplayerLobbySession::Members::get() +{ + return m_lobbyMembers->GetView(); +} + +MultiplayerSessionReference^ +MultiplayerLobbySession::SessionReference::get() +{ + return m_sessionReference; +} + +MultiplayerMember^ +MultiplayerLobbySession::Host::get() +{ + if (m_cppObj->host() == nullptr) + { + return nullptr; + } + + return ref new MultiplayerMember(m_cppObj->host()); +} + +MultiplayerSessionConstants^ +MultiplayerLobbySession::SessionConstants::get() +{ + return m_sessionConstants; +} + +TournamentTeamResult^ +MultiplayerLobbySession::LastTournamentTeamResult::get() +{ + return m_lastTournamentTeamResult; +} + +std::shared_ptr +MultiplayerLobbySession::GetCppObj() const +{ + return m_cppObj; +} + +void +MultiplayerLobbySession::UpdateCppObj( + _In_ std::shared_ptr cppObj + ) +{ + if (m_cppObj->_Change_number() != cppObj->_Change_number()) + { + m_cppObj = cppObj; + if (m_cppObj->_Change_number() != 0) + { + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj->session_reference()); + m_sessionConstants = ref new MultiplayerSessionConstants(m_cppObj->session_constants()); + m_lastTournamentTeamResult = ref new TournamentTeamResult(m_cppObj->last_tournament_team_result()); + m_localMembers = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->local_members()); + m_lobbyMembers = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->members()); + } + else + { + m_sessionReference = nullptr; + m_sessionConstants = nullptr; + m_lastTournamentTeamResult = nullptr; + m_localMembers->Clear(); + m_lobbyMembers->Clear(); + } + } +} + +void +MultiplayerLobbySession::AddLocalUser( + _In_ XboxLiveUser_t user + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + + xbox_live_result result; + result = m_cppObj->add_local_user(user_context::user_convert(user)); + + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::RemoveLocalUser( + _In_ XboxLiveUser_t user + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + + xbox_live_result result; + result = m_cppObj->remove_local_user(user_context::user_convert(user)); + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::SetLocalMemberProperties( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + auto result = m_cppObj->set_local_member_properties( + user_context::user_convert(user), + STRING_T_FROM_PLATFORM_STRING(name), + valueJsonString, + context + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::DeleteLocalMemberProperties( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ name, + _In_opt_ context_t context + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + + auto result = m_cppObj->delete_local_member_properties( + user_context::user_convert(user), + STRING_T_FROM_PLATFORM_STRING(name), + context + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::SetLocalMemberConnectionAddress( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ connectionAddress, + _In_opt_ context_t context + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + + auto result = m_cppObj->set_local_member_connection_address( + user_context::user_convert(user), + STRING_T_FROM_PLATFORM_STRING(connectionAddress), + context + ); + + THROW_IF_ERR(result); +} + +bool +MultiplayerLobbySession::IsHost( + _In_ Platform::String^ xboxUserId + ) +{ + return m_cppObj->is_host(STRING_T_FROM_PLATFORM_STRING(xboxUserId)); +} + +void +MultiplayerLobbySession::SetProperties( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ) +{ + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + auto result = m_cppObj->set_properties( + STRING_T_FROM_PLATFORM_STRING(name), + valueJsonString, + context + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::SetSynchronizedProperties( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ) +{ + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + auto result = m_cppObj->set_synchronized_properties( + STRING_T_FROM_PLATFORM_STRING(name), + valueJsonString, + context + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::SetSynchronizedHost( + _In_ MultiplayerMember^ gameHost, + _In_opt_ context_t context + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(gameHost); + + auto result = m_cppObj->set_synchronized_host( + gameHost->GetCppObj(), + context + ); + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::InviteFriends( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ contextStringId, + _In_ Platform::String^ customActivationContext + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + + auto result = m_cppObj->invite_friends( + user_context::user_convert(user), + STRING_T_FROM_PLATFORM_STRING(contextStringId), + STRING_T_FROM_PLATFORM_STRING(customActivationContext) + ); + THROW_IF_ERR(result); +} + +void +MultiplayerLobbySession::InviteUsers( + _In_ XboxLiveUser_t user, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Platform::String^ contextStringId, + _In_ Platform::String^ customActivationContext + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + THROW_INVALIDARGUMENT_IF_NULL(xboxUserIds); + + auto result = m_cppObj->invite_users( + user_context::user_convert(user), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds), + STRING_T_FROM_PLATFORM_STRING(contextStringId), + STRING_T_FROM_PLATFORM_STRING(customActivationContext) + ); + THROW_IF_ERR(result); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.h new file mode 100644 index 00000000..64969f3a --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerLobbySession_WinRT.h @@ -0,0 +1,268 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/multiplayer_manager.h" +#include "MultiplayerMember_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MultiplayerSessionRestriction_WinRT.h" +#include "MultiplayerSessionConstants_WinRT.h" +#include "MultiplayerActivityDetails_WinRT.h" +#include "TournamentTeamResult_WinRT.h" + +namespace Microsoft{ namespace Xbox{ namespace Services { + namespace System { + ref class XboxLiveUser; + } +}}} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Manager for managing members that are local to this device. +/// +public ref class MultiplayerLobbySession sealed +{ +public: + + /// + /// A unique ID to the session used to query trace logs for entries that relate to the session. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(CorrelationId, correlation_id); + + /// + /// Object containing identifying information for the session. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ SessionReference + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ get(); + } + + /// + /// A collection of members that are local to this device. + /// + property Windows::Foundation::Collections::IVectorView^ LocalMembers + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// A collection of members that are in the lobby. When a friend accepts a game invite, + /// members will be added to the lobby. + /// + property Windows::Foundation::Collections::IVectorView^ Members + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// Returns the host member for the lobby. + /// There could be multiple hosts if there are multiple users on the same host device. + /// This returns user with the lowest index for that host device. + /// + property MultiplayerMember^ Host { MultiplayerMember^ get(); } + + /// + /// JSON string that specify the custom properties for the game. These can be changed anytime. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(Properties, properties); + + /// + /// A set of constants associated with this session. These can only be set through the session template. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionConstants^ SessionConstants + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionConstants^ get(); + } + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// The known last team result of the tournament. + /// + property Microsoft::Xbox::Services::Tournaments::TournamentTeamResult^ LastTournamentTeamResult + { + Microsoft::Xbox::Services::Tournaments::TournamentTeamResult^ get(); + } + + /// + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// Hosts a new lobby when the first user is added. For all other users, they will be added to the existing lobby + // as secondary users. This API will also advertise the lobby for friends to join. + /// You can send invites, set lobby properties, access lobby memebers via lobby() only once you've added the local user. + /// While joining a lobby via an invite, or a handleId, you can skip adding the local user to avoid creating a lobby and + /// instead pass in the list of users in the join_lobby() API. + /// + /// The associated xbox_live_context for the User. + void AddLocalUser( + _In_ XboxLiveUser_t user + ); + + /// + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// Removes the local user from the lobby and game session. + /// After this method is called, if no local users are active, title will not be able to perform any further multiplayer operations. + /// You can join another game or re-add the local user. + /// + /// The associated xbox_live_context for the User. + void RemoveLocalUser( + _In_ XboxLiveUser_t user + ); + + /// + /// Set a custom property on the local member to the specified JSON string + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// The associated xbox_live_context for the User you want to set the property for. + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + void SetLocalMemberProperties( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ); + + /// + /// Delete a custom property on the local member + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// The associated xbox_live_context for the User you want to delete the property for. + /// The name of the property to delete + void DeleteLocalMemberProperties( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ name, + _In_opt_ context_t context + ); + + /// + /// Set connection address for the local member. The address can be used for network and secure socket connection. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// The associated system User you want to set the property for. + /// The network connection address to set. + void SetLocalMemberConnectionAddress( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ connectionAddress, + _In_opt_ context_t context + ); + + /// + /// Whether or not the Xbox User ID is the host. + /// + /// The Xbox User ID of the user + bool IsHost( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Set a custom game property to the specified JSON string. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + void SetProperties( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ); + + /// + /// Sets a custom property to the specified JSON string using multiplayer_session_write_mode::synchronized_update. + /// Use this method to resolve any conflicts between devices while trying to set properties to a shared portion that other + /// devices can also modify. It ensures that updates to the session are atomic. If writing to non-sharable properties, use set_properties() instead. + /// The service may reject your request if a race condition occurred (due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type write_synchronized_properties_completed through do_work(). + /// + /// The name of the property to set. + /// The JSON value to assign to the property. (Optional) + void SetSynchronizedProperties( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson, + _In_opt_ context_t context + ); + + /// + /// Sets the host for the game using multiplayer_session_write_mode::synchronized_update. Use this method to resolve + /// any conflicts between devices trying to set the host at the same time. It ensures that updates to the session are atomic. + /// The service may reject your request if a race condition occurred(due to a conflict) resulting in error_code + /// http_status_412_precondition_failed (HTTP status 412). To resolve this, evaluate the need to write again and re-submit if needed. + /// The result is delivered via multiplayer_event callback of type write_synchronized_host_completed through do_work(). + /// + /// The host member. + void SetSynchronizedHost( + _In_ MultiplayerMember^ gameHost, + _In_opt_ context_t context + ); + + /// + /// Displays the invite UI and allows the user to select people from the user's people list and invite them to join the user's party + /// If a user accepts that notification the title will be activated. + /// + /// The associated xbox_live_context for the User. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with “///”. Pass an empty string if + /// you don't want a custom string added to the invite. + /// The activation context string. Pass an empty string if + /// you don't want a custom context added to the invite. + void InviteFriends( + _In_ XboxLiveUser_t user, + _In_ Platform::String^ contextStringId, + _In_ Platform::String^ customActivationContext + ); + + /// + /// Invites the specified users to a game. This will result in a notification being shown to + /// each invited user using standard invite text. If a user accepts that notification the title will be activated. + /// + /// The associated xbox_live_context for the User. + /// The list of xbox user IDs who will be invited. + /// The custom context string ID. This string ID is defined + /// during Xbox Live ingestion to identify the invitation text that is additional to the standard + /// invitation text. The ID string must be prefixed with “///”. Pass an empty string if + /// you don’t want a custom string added to the invite. + /// The activation context string. Pass an empty string if + /// you don't want a custom context added to the invite. + /// The async object for notifying when the operation is completed. + void InviteUsers( + _In_ XboxLiveUser_t user, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Platform::String^ contextStringId, + _In_ Platform::String^ customActivationContext + ); + +internal: + MultiplayerLobbySession( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + + void UpdateCppObj( + _In_ std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; + Windows::Foundation::Collections::IVector^ m_lobbyMembers; + Windows::Foundation::Collections::IVector^ m_localMembers; + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ m_sessionReference; + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionConstants^ m_sessionConstants; + Microsoft::Xbox::Services::Tournaments::TournamentTeamResult^ m_lastTournamentTeamResult; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.cpp new file mode 100644 index 00000000..8b6f2eab --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.cpp @@ -0,0 +1,323 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "MultiplayerManager_WinRT.h" +#include "MultiplayerEvent_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace xbox::services::multiplayer::manager; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Multiplayer; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +static std::mutex s_singletonLock; + +MultiplayerManager::MultiplayerManager() : + m_cppObj(multiplayer_manager::get_singleton_instance()) +{ +} + +MultiplayerManager^ +MultiplayerManager::SingletonInstance::get() +{ + std::lock_guard guard(s_singletonLock); + + static MultiplayerManager^ instance; + if (instance == nullptr) + { + instance = ref new MultiplayerManager(); + } + + return instance; +} + +std::shared_ptr +MultiplayerManager::GetCppObj() const +{ + return m_cppObj; +} + +void +MultiplayerManager::Initialize( + _In_ Platform::String^ lobbySessionTemplateName + ) +{ + m_cppObj->initialize( + STRING_T_FROM_PLATFORM_STRING(lobbySessionTemplateName) + ); + + m_multiplayerLobbySession = ref new MultiplayerLobbySession(m_cppObj->lobby_session()); +} + +void +MultiplayerManager::FindMatch( + _In_ Platform::String^ hopperName, + _In_opt_ Platform::String^ attributes, + _In_opt_ Windows::Foundation::TimeSpan timeout + ) +{ + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(attributes); + auto result = m_cppObj->find_match( + STRING_T_FROM_PLATFORM_STRING(hopperName), + valueJsonString, + UtilsWinRT::ConvertTimeSpanToSeconds(timeout) + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerManager::CancelMatch() +{ + m_cppObj->cancel_match(); +} + +void +MultiplayerManager::JoinLobby( + _In_ Platform::String^ handleId, + _In_ XboxLiveUser_t user + ) +{ + auto result = m_cppObj->join_lobby( + STRING_T_FROM_PLATFORM_STRING(handleId), + user_context::user_convert(user) + ); + + THROW_IF_ERR(result); +} + +#if TV_API +void +MultiplayerManager::JoinLobby( + _In_ Platform::String^ handleId, + _In_ Windows::Foundation::Collections::IVectorView^ users + ) +{ + auto vector = std::vector(); + for (const auto& user : users) + { + vector.push_back(user); + } + + auto result = m_cppObj->join_lobby( + STRING_T_FROM_PLATFORM_STRING(handleId), + vector + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerManager::JoinLobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ Windows::Foundation::Collections::IVectorView^ users + ) +{ + auto vector = std::vector(); + for (const auto& user : users) + { + vector.push_back(user); + } + + auto result = m_cppObj->join_lobby( + eventArgs, + vector + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerManager::InvitePartyToGame() +{ +} +#endif + +void +MultiplayerManager::JoinLobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ XboxLiveUser_t user + ) +{ + auto result = m_cppObj->join_lobby( + eventArgs, + user_context::user_convert(user) + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerManager::JoinGameFromLobby( + _In_ Platform::String^ sessionTemplateName + ) +{ + auto result = m_cppObj->join_game_from_lobby(STRING_T_FROM_PLATFORM_STRING(sessionTemplateName)); + THROW_IF_ERR(result); +} + +void +MultiplayerManager::JoinGame( + _In_ Platform::String^ sessionName, + _In_ Platform::String^ sessionTemplateName +) +{ + auto result = m_cppObj->join_game( + STRING_T_FROM_PLATFORM_STRING(sessionName), + STRING_T_FROM_PLATFORM_STRING(sessionTemplateName) + ); + THROW_IF_ERR(result); +} + +void +MultiplayerManager::JoinGame( + _In_ Platform::String^ sessionName, + _In_ Platform::String^ sessionTemplateName, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ) +{ + auto result = m_cppObj->join_game( + STRING_T_FROM_PLATFORM_STRING(sessionName), + STRING_T_FROM_PLATFORM_STRING(sessionTemplateName), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds) + ); + THROW_IF_ERR(result); +} + +void +MultiplayerManager::LeaveGame() +{ + auto result = m_cppObj->leave_game(); + THROW_IF_ERR(result); +} + + +MultiplayerLobbySession^ +MultiplayerManager::LobbySession::get() +{ + if (m_multiplayerLobbySession == nullptr) + { + throw Microsoft::Xbox::Services::System::UtilsWinRT::ConvertHRESULTToException(E_FAIL, ref new Platform::String(L"Call MultiplayerManager::Initialize() first.")); + } + return m_multiplayerLobbySession; +} + +MultiplayerGameSession^ +MultiplayerManager::GameSession::get() +{ + return m_multiplayerGameSession; +} + +IVectorView^ +MultiplayerManager:: DoWork() +{ + auto multiplayerEvents = m_cppObj->do_work(); + UpdateSessions(); + + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(multiplayerEvents)->GetView(); +} + +void +MultiplayerManager::UpdateSessions() +{ + if (m_multiplayerLobbySession != nullptr) + { + m_multiplayerLobbySession->UpdateCppObj(m_cppObj->lobby_session()); + } + + if (m_cppObj->game_session() != nullptr) + { + if (m_multiplayerGameSession == nullptr) + { + m_multiplayerGameSession = ref new MultiplayerGameSession(m_cppObj->game_session()); + } + else + { + m_multiplayerGameSession->UpdateCppObj(m_cppObj->game_session()); + } + } + else + { + m_multiplayerGameSession = nullptr; + } +} + +Microsoft::Xbox::Services::Multiplayer::Manager::MatchStatus +MultiplayerManager::MatchStatus::get() +{ + return static_cast(m_cppObj->match_status()); +} + +Microsoft::Xbox::Services::Multiplayer::Manager::Joinability +MultiplayerManager::Joinability::get() +{ + return static_cast(m_cppObj->joinability()); +} + +TimeSpan +MultiplayerManager::EstimatedMatchWaitTime::get() +{ + return UtilsWinRT::ConvertSecondsToTimeSpan(m_cppObj->estimated_match_wait_time()); +} + +bool +MultiplayerManager::AutoFillMembersDuringMatchmaking::get() +{ + return m_cppObj->auto_fill_members_during_matchmaking(); +} + +void +MultiplayerManager::AutoFillMembersDuringMatchmaking::set(_In_ bool value) +{ + m_cppObj->set_auto_fill_members_during_matchmaking(value); +} + +void +MultiplayerManager::SetJoinInProgress( + _In_ Microsoft::Xbox::Services::Multiplayer::Manager::Joinability value + ) +{ + auto result = m_cppObj->set_joinability( + static_cast(value) + ); + + THROW_IF_ERR(result); +} + +void +MultiplayerManager::SetQualityOfServiceMeasurements( + _In_ Windows::Foundation::Collections::IVectorView^ measurements + ) +{ + m_cppObj->set_quality_of_service_measurements( + std::make_shared>( + UtilsWinRT::CreateStdVectorObjectFromPlatformVectorObj( + measurements + ) + ) + ); +} + +#if UNIT_TEST_SERVICES +void +MultiplayerManager::_Shutdown() +{ + m_cppObj->_Shutdown(); +} +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.h new file mode 100644 index 00000000..dc3f1f04 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerManager_WinRT.h @@ -0,0 +1,279 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer_manager.h" +#include "MultiplayerLobbySession_WinRT.h" +#include "MultiplayerGameSession_WinRT.h" +#include "MultiplayerEvent_WinRT.h" +#include "MultiplayerMember_WinRT.h" +#include "MatchStatus_WinRT.h" +#include "JoinInProgressState_WinRT.h" +#include "MultiplayerQualityOfServiceMeasurements_WinRT.h" + +namespace Microsoft{ namespace Xbox{ namespace Services { + namespace System { + ref class XboxLiveUser; + } +}}} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// APIs for matchmaking, player roster and multiplayer session management. +/// +public ref class MultiplayerManager sealed +{ +public: + /// + /// Gets the multiplayer_manager singleton instance + /// + static property MultiplayerManager^ SingletonInstance { MultiplayerManager^ get(); } + + /// + /// Initializes the object. + /// + /// The name of the template for the lobby session to be based on. + void Initialize( + _In_ Platform::String^ lobbySessionTemplateName + ); + + /// + /// Sends a matchmaking request to the server. When a match is found, the manager will join + /// the game and notify the title via find_match_completed_event(). + /// + /// The name of the hopper. + /// The ticket attributes for the match. (Optional) + /// The maximum time to wait for members to join the match. (Optional) + void FindMatch( + _In_ Platform::String^ hopperName, + _In_opt_ Platform::String^ attributes, + _In_opt_ Windows::Foundation::TimeSpan timeout + ); + + /// + /// Cancels the match request on the server, if one exists. + /// + void CancelMatch(); + + /// + /// Joins a game given a session handle id. A handle is a service-side pointer to a game session. + /// The handleId is a GUID identifier of the handle. Callers will usually get the handleId from + /// another member's multiplayer_activity_details. Optionally, if you haven't added the local users through + /// lobby_session()::add_local_user(), you can pass in the list of users via the join_lobby() API. + /// The result is delivered via multiplayer_event callback of type join_game_completed through do_work(). + /// After joining, you can set the host via set_synchronized_host() if one doesn't exist. + /// + /// A multiplayer handle id, which uniquely identifies the game session you want to join. + /// The system User joining the lobby. + [Windows::Foundation::Metadata::DefaultOverloadAttribute] + void JoinLobby( + _In_ Platform::String^ handleId, + _In_ XboxLiveUser_t user + ); + +#if TV_API + /// + /// Joins a game given a session handle id. A handle is a service-side pointer to a game session. + /// The handleId is a GUID identifier of the handle. Callers will usually get the handleId from + /// another member's multiplayer_activity_details. Optionally, if you haven't added the local users through + /// lobby_session()::add_local_user(), you can pass in the list of users via the join_lobby() API. + /// The result is delivered via multiplayer_event callback of type join_game_completed through do_work(). + /// After joining, you can set the host via set_synchronized_host() if one doesn't exist. + /// + /// A multiplayer handle id, which uniquely identifies the game session you want to join. + /// List of xbox_live_contexts joining the lobby. + void JoinLobby( + _In_ Platform::String^ handleId, + _In_ Windows::Foundation::Collections::IVectorView^ users + ); + + /// + /// Joins a game via the specified IProtocolActivatedEventArgs. + /// The IProtocolActivatedEventArgs provides arguments for protocol activation. If the user accepts an invite or + /// joined a friends game via a shell UI, the title will get a protocol activation. The result is delivered via + /// join_lobby_completed_event_args() callback through do_work(). + /// Optionally, if you haven't added the local users through lobby_session()::add_local_user(), you can pass in + /// the list of users via the join_lobby() API. If the invited user is not added either via + /// lobby_session()::add_local_user() or through join_lobby(), then join_lobby() will fail and provide the + /// invited_xbox_user_id() that the invite was sent for as part of the join_lobby_completed_event_args() + /// After joining, you can set the host via set_synchronized_host() if one doesn't exist. + /// + /// The IProtocolActivatedEventArgs when the title is protocol activated. + /// List of users joining the lobby. + void JoinLobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ Windows::Foundation::Collections::IVectorView^ users + ); + + /// + /// Send invites to your party to join your game. + /// + void InvitePartyToGame(); +#endif + + /// + /// Joins a game via the specified IProtocolActivatedEventArgs. + /// The IProtocolActivatedEventArgs provides arguments for protocol activation. If the user accepts an invite or + /// joined a friends game via a shell UI, the title will get a protocol activation. The result is delivered via + /// join_lobby_completed_event_args() callback through do_work(). + /// Optionally, if you haven't added the local users through lobby_session()::add_local_user(), you can pass in + /// the list of users via the join_lobby() API. If the invited user is not added either via + /// lobby_session()::add_local_user() or through join_lobby(), then join_lobby() will fail and provide the + /// invited_xbox_user_id() that the invite was sent for as part of the join_lobby_completed_event_args() + /// After joining, you can set the host via set_synchronized_host() if one doesn't exist. + /// + /// The IProtocolActivatedEventArgs when the title is protocol activated. + /// The system User joining the lobby. + void JoinLobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ XboxLiveUser_t user + ); + + /// + /// Join the lobby's game session if one exists and if there is room. If the session doesn't exist, it creates a new game session + /// with the existing lobby members. The result is delivered via multiplayer_event callback of + /// type join_game_completed through do_work(). This does not migrate existing lobby session properties over to the game session. + /// After joining, you can set the properties or the host via game_session()::write_synchronized APIs. + /// + /// The name of the template for the game session to be based on. + void JoinGameFromLobby( + _In_ Platform::String^ sessionTemplateName + ); + + /// + /// Joins a game given a globally unique session name. Callers can get the unique session name + /// as a result of the title's third party matchmaking. + /// The result is delivered via multiplayer_event callback of type join_game_completed through do_work(). + /// After joining, you can set the properties or the host via game_session()::write_synchronized APIs. + /// + /// A unique name for the session. + /// The name of the template for the game session to be based on. +#if _MSC_VER >= 1800 + [Windows::Foundation::Metadata::Deprecated("Call JoinGame(String^, String^, IVectorView<>^) instead", Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0)] +#endif + void JoinGame( + _In_ Platform::String^ sessionName, + _In_ Platform::String^ sessionTemplateName + ); + + /// + /// Joins a game given a globally unique session name. Callers can get the unique session name + /// as a result of the title's third party matchmaking. + /// The result is delivered via multiplayer_event callback of type join_game_completed through do_work(). + /// After joining, you can set the properties or the host via game_session()::write_synchronized APIs. + /// + /// A unique name for the session. + /// The name of the template for the game session to be based on. + /// The list of xbox user IDs you want to be part of the game. + void JoinGame( + _In_ Platform::String^ sessionName, + _In_ Platform::String^ sessionTemplateName, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ); + + /// + /// Leaving the game will put you back into the lobby. This will remove all local users from the game. + /// + void LeaveGame(); + + /// + /// Ensures proper game state updates are maintained between the title and the Xbox Live Multiplayer Service. + /// To ensure best performance, do_work() must be called frequently, at least once per frame. + /// Title needs to be thread safe when calling do_work() since this is when the state will change. + /// For example, if you looping through the list of game session members(), it may change when do_work() is called. + /// + /// A list of all callback events for the game to handle. Empty if no events are triggered during this update. + Windows::Foundation::Collections::IVectorView^ DoWork(); + + /// + /// Provides the current state of matchmaking. 'None' if no matchmaking is in progress. + /// + property Microsoft::Xbox::Services::Multiplayer::Manager::MatchStatus MatchStatus + { + Microsoft::Xbox::Services::Multiplayer::Manager::MatchStatus get(); + } + + /// + /// Estimated wait time for a match request to be matched with other members. + /// Only applies after find_match() has been called. + /// + property Windows::Foundation::TimeSpan EstimatedMatchWaitTime { Windows::Foundation::TimeSpan get(); } + + /// + /// A collection of members that you have invited to your lobby. When a member accepts a game invite, + /// they will be added to the lobby and the game session. Users found via matchmaking will not be + /// added in the lobby. + /// + property MultiplayerLobbySession^ LobbySession { MultiplayerLobbySession^ get(); } + + /// + /// A collection of members that are part of your game session. When a member accepts a game invite, + /// they will be added to the lobby and the game session (if there is room). + /// You can call leave_game() to leave the game. + /// + property MultiplayerGameSession^ GameSession { MultiplayerGameSession^ get(); } + + /// + /// Indicates JoinInProgressState on who can join your game. + /// + property Microsoft::Xbox::Services::Multiplayer::Manager::Joinability Joinability + { + Microsoft::Xbox::Services::Multiplayer::Manager::Joinability get(); + } + + /// + /// Restricts who can join the game. Defaults to "enabled", meaning only local users and users who are followed + /// by an existing member of the lobby can join without an invite. + /// Changes are batched and written to the service on the next do_work(). All session properties and members + /// contain updated response returned from the server upon calling do_work(). + /// + /// Restriction on members to join the lobby. + void SetJoinInProgress( + _In_ Microsoft::Xbox::Services::Multiplayer::Manager::Joinability value + ); + + /// + /// Indicates whether the game should auto fill open slots during gameplay. + /// If set to true, it finds members via matchmaking to fill open slots during gameplay. + /// This can be changed anytime. + /// + property bool AutoFillMembersDuringMatchmaking + { + bool get(); + void set(_In_ bool value); + } + + /// + /// Sets a collection of MultiplayerQualityOfServiceMeasurements between itself and a list of remote clients. + /// This is only useful when the title is manually managing QoS. + /// + void SetQualityOfServiceMeasurements( + _In_ Windows::Foundation::Collections::IVectorView^ measurements + ); + +internal: + MultiplayerManager(); + + std::shared_ptr GetCppObj() const; + + std::shared_ptr m_cppObj; + +#if UNIT_TEST_SERVICES + void _Shutdown(); +#endif + +private: + void UpdateSessions(); + + MultiplayerLobbySession^ m_multiplayerLobbySession; + MultiplayerGameSession^ m_multiplayerGameSession; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.cpp new file mode 100644 index 00000000..91338925 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerMember_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +MultiplayerMember::MultiplayerMember( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +bool MultiplayerMember::IsMemberOnSameDevice( + _In_ MultiplayerMember^ member + ) +{ + return m_cppObj->is_member_on_same_device( + member->GetCppObj() + ); +} + +std::shared_ptr +MultiplayerMember::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.h new file mode 100644 index 00000000..767a7715 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerMember_WinRT.h @@ -0,0 +1,93 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer_manager.h" +#include "MultiplayerSessionMemberStatus_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +public ref class MultiplayerMember sealed +{ +public: + /// + /// Id for the member. + /// + DEFINE_PTR_PROP_GET_OBJ(MemberId, member_id, uint32); + + /// + /// Only applicable if you are using Xbox Live Tournaments. + /// Id of this members' team in a tournament. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(TeamId, team_id); + + /// + /// Xbox User ID of the member. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The Gamertag of the member. This is only to be used for debugging purposes. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(DebugGamertag, debug_gamertag); + + /// + /// Indicates if this member is playing on the local device. + /// + DEFINE_PTR_PROP_GET_OBJ(IsLocal, is_local, bool); + + /// + /// Indicates if this member is part of the lobby. + /// + DEFINE_PTR_PROP_GET_OBJ(IsInLobby, is_in_lobby, bool); + + /// + /// Indicates if this member is part of the game. + /// + DEFINE_PTR_PROP_GET_OBJ(IsInGame, is_in_game, bool); + + /// + /// The status of this member. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(Status, status, Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionMemberStatus); + + /// + /// The address used for network connection. + /// This can be used for secure socket connection. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ConnectionAddress, connection_address); + + /// + /// JSON value that specify the custom properties of the member. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(Properties, properties); + + /// + /// Determines whether the member is on the same device. + /// + bool IsMemberOnSameDevice( + _In_ MultiplayerMember^ member + ); + + /// + /// Internal function + /// + DEFINE_PTR_PROP_GET_STR_OBJ(_DeviceToken, _Device_token); + +internal: + MultiplayerMember( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/MultiplayerSessionType_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerSessionType_WinRT.h new file mode 100644 index 00000000..8969096d --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/MultiplayerSessionType_WinRT.h @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Defines values used to indicate change types for a multiplayer game. +/// +public enum class MultiplayerSessionType +{ + /// + /// The session type is unknown. + /// + Unknown = xbox::services::multiplayer::manager::multiplayer_session_type::unknown, + + /// + /// Indicates multiplayer lobby session. + /// + LobbySession = xbox::services::multiplayer::manager::multiplayer_session_type::lobby_session, + + /// + /// Indicates multiplayer game session. + /// + GameSession = xbox::services::multiplayer::manager::multiplayer_session_type::game_session +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.cpp new file mode 100644 index 00000000..09abd237 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.cpp @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "PerformQosMeasurementsEventArgs_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +PerformQosMeasurementsEventArgs::PerformQosMeasurementsEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + XSAPI_ASSERT(m_cppObj != nullptr); + + m_addressToDeviceTokenMap = ref new Platform::Collections::Map(); + for (const auto& address : m_cppObj->connection_address_to_device_tokens()) + { + m_addressToDeviceTokenMap->Insert(ref new Platform::String(address.first.c_str()), ref new Platform::String(address.second.c_str())); + } +} + +std::shared_ptr +PerformQosMeasurementsEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +Windows::Foundation::Collections::IMapView^ +PerformQosMeasurementsEventArgs::AddressToDeviceTokens::get() +{ + return m_addressToDeviceTokenMap->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.h new file mode 100644 index 00000000..124be157 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/PerformQosMeasurementsEventArgs_WinRT.h @@ -0,0 +1,44 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "MultiplayerMember_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a new game member joins the game. +/// +public ref class PerformQosMeasurementsEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// A list of members that joined the game. + /// + property Windows::Foundation::Collections::IMapView^ AddressToDeviceTokens + { + Windows::Foundation::Collections::IMapView^ get(); + } + +internal: + PerformQosMeasurementsEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + Platform::Collections::Map^ m_addressToDeviceTokenMap; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.cpp new file mode 100644 index 00000000..57f60c91 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "SessionPropertyChangedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +SessionPropertyChangedEventArgs::SessionPropertyChangedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +SessionPropertyChangedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.h new file mode 100644 index 00000000..538f1e18 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/SessionPropertyChangedEventArgs_WinRT.h @@ -0,0 +1,39 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a session property has been added or modified. +/// +public ref class SessionPropertyChangedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// The JSON of the property that changed. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(Properties, properties); + +internal: + SessionPropertyChangedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.cpp new file mode 100644 index 00000000..66d7f630 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "TournamentGameSessionReadyEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +TournamentGameSessionReadyEventArgs::TournamentGameSessionReadyEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +TournamentGameSessionReadyEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.h new file mode 100644 index 00000000..c61372a1 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/TournamentGameSessionReadyEventArgs_WinRT.h @@ -0,0 +1,39 @@ +#pragma once +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Contains information for an event that indicates when the tournament registration state changes. +/// +public ref class TournamentGameSessionReadyEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// Game's start time for the tournament. + /// + DEFINE_PTR_PROP_GET_DATETIME_OBJ(StartTime, start_time); + +internal: + TournamentGameSessionReadyEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END diff --git a/Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.cpp new file mode 100644 index 00000000..ac369c57 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "TournamentRegistrationStateChangedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +TournamentRegistrationStateChangedEventArgs::TournamentRegistrationStateChangedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +TournamentRegistrationStateChangedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.h new file mode 100644 index 00000000..a3212045 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/TournamentRegistrationStateChangedEventArgs_WinRT.h @@ -0,0 +1,47 @@ +#pragma once +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" +#include "TournamentRegistrationState_WinRT.h" +#include "TournamentRegistrationReason_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Contains information for an event that indicates when the tournament registration state changes. +/// +public ref class TournamentRegistrationStateChangedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// The tournament team registration state. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(RegistrationState, registration_state, Microsoft::Xbox::Services::Tournaments::TournamentRegistrationState); + + /// + /// The tournament team registration reason for the certain registration states. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(RegistrationReason, registration_reason, Microsoft::Xbox::Services::Tournaments::TournamentRegistrationReason); + +internal: + TournamentRegistrationStateChangedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.cpp new file mode 100644 index 00000000..4249f542 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "UserAddedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +UserAddedEventArgs::UserAddedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +UserAddedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.h new file mode 100644 index 00000000..0e6de056 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/UserAddedEventArgs_WinRT.h @@ -0,0 +1,39 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a new user was added. +/// +public ref class UserAddedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// Xbox User ID of the member that that was added. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + +internal: + UserAddedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.cpp b/Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.cpp new file mode 100644 index 00000000..27b58e66 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "UserRemovedEventArgs_WinRT.h" + +using namespace xbox::services::multiplayer::manager; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +UserRemovedEventArgs::UserRemovedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + XSAPI_ASSERT(cppObj != nullptr); +} + +std::shared_ptr +UserRemovedEventArgs::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.h b/Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.h new file mode 100644 index 00000000..295acfd6 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/WinRT/UserRemovedEventArgs_WinRT.h @@ -0,0 +1,39 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_BEGIN + +/// +/// Notifies the title when a user was removed. +/// +public ref class UserRemovedEventArgs sealed : MultiplayerEventArgs +{ +public: + + /// + /// Xbox User ID of the member that that was removed. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + +internal: + UserRemovedEventArgs( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/find_match_completed_event_args.cpp b/Source/Services/Multiplayer/Manager/find_match_completed_event_args.cpp new file mode 100644 index 00000000..48f68967 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/find_match_completed_event_args.cpp @@ -0,0 +1,39 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +find_match_completed_event_args::find_match_completed_event_args( + _In_ xbox::services::multiplayer::manager::match_status status, + _In_ multiplayer_measurement_failure failure + ): + m_matchStatus(status), + m_initializationFailure(failure) +{ +} + +xbox::services::multiplayer::manager::match_status +find_match_completed_event_args::match_status() const +{ + return m_matchStatus; +} + +multiplayer_measurement_failure +find_match_completed_event_args::initialization_failure_cause() const +{ + return m_initializationFailure; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/host_changed_event_args.cpp b/Source/Services/Multiplayer/Manager/host_changed_event_args.cpp new file mode 100644 index 00000000..f7d371e4 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/host_changed_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +host_changed_event_args::host_changed_event_args( + _In_ std::shared_ptr hostMember + ): + m_hostMember(std::move(hostMember)) +{ +} + +std::shared_ptr +host_changed_event_args::host_member() +{ + return m_hostMember; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/join_lobby_completed_event_args.cpp b/Source/Services/Multiplayer/Manager/join_lobby_completed_event_args.cpp new file mode 100644 index 00000000..1096d639 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/join_lobby_completed_event_args.cpp @@ -0,0 +1,28 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +join_lobby_completed_event_args::join_lobby_completed_event_args( + _In_ string_t xboxUserId + ): + m_invitedXboxUserid(std::move(xboxUserId)) +{ +} + +const string_t& +join_lobby_completed_event_args::invited_xbox_user_id() const +{ + return m_invitedXboxUserid; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/member_joined_event_args.cpp b/Source/Services/Multiplayer/Manager/member_joined_event_args.cpp new file mode 100644 index 00000000..6b5540cf --- /dev/null +++ b/Source/Services/Multiplayer/Manager/member_joined_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +member_joined_event_args::member_joined_event_args( + _In_ std::vector> members + ): + m_members(std::move(members)) +{ +} + +std::vector> +member_joined_event_args::members() +{ + return m_members; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/member_left_event_args.cpp b/Source/Services/Multiplayer/Manager/member_left_event_args.cpp new file mode 100644 index 00000000..39d64ea3 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/member_left_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +member_left_event_args::member_left_event_args( + _In_ std::vector> members + ): + m_members(std::move(members)) +{ +} + +std::vector> +member_left_event_args::members() +{ + return m_members; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/member_property_changed_event_args.cpp b/Source/Services/Multiplayer/Manager/member_property_changed_event_args.cpp new file mode 100644 index 00000000..e3fc74d1 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/member_property_changed_event_args.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +member_property_changed_event_args::member_property_changed_event_args( + _In_ std::shared_ptr member, + _In_ web::json::value jsonProperties + ): + m_member(std::move(member)), + m_properties(std::move(jsonProperties)) +{ +} + +std::shared_ptr +member_property_changed_event_args::member() +{ + return m_member; +} + +web::json::value +member_property_changed_event_args::properties() +{ + return m_properties; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_client_manager.cpp b/Source/Services/Multiplayer/Manager/multiplayer_client_manager.cpp new file mode 100644 index 00000000..35484622 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_client_manager.cpp @@ -0,0 +1,1220 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "pplx/pplxtasks.h" +#include "xsapi/services.h" +#include "user_context.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace xbox::services::real_time_activity; +using namespace pplx; +#if !XSAPI_U +using namespace Windows::Foundation::Collections; +#endif +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_client_manager::multiplayer_client_manager(const multiplayer_client_manager& other) +{ + std::lock_guard lock(other.m_clientRequestLock); + + m_sessionChangedContext = other.m_sessionChangedContext; + m_subscriptionLostContext = other.m_subscriptionLostContext; + m_rtaResyncContext = other.m_rtaResyncContext; + m_primaryXboxLiveContext = other.m_primaryXboxLiveContext == nullptr ? nullptr : other.m_primaryXboxLiveContext; + m_lastPendingRead = other.m_lastPendingRead == nullptr ? nullptr : other.m_lastPendingRead; + m_latestPendingRead = other.m_latestPendingRead == nullptr ? nullptr : other.m_latestPendingRead; +} + +multiplayer_client_manager::multiplayer_client_manager( + _In_ string_t lobbySessionTemplateName + ) : + m_lobbySessionTemplateName(std::move(lobbySessionTemplateName)), + m_sessionChangedContext(0), + m_subscriptionLostContext(0), + m_rtaResyncContext(0), + m_subscriptionsLostFired(false), + m_autoFillMembers(false) +{ + m_multiplayerLocalUserManager = std::make_shared(); +} + +void +multiplayer_client_manager::register_local_user_manager_events() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_sessionChangedContext = m_multiplayerLocalUserManager->add_multiplayer_session_changed_handler([thisWeakPtr](_In_ const multiplayer_session_change_event_args& args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_session_changed(args); + } + }); + + m_subscriptionLostContext = m_multiplayerLocalUserManager->add_multiplayer_subscription_lost_handler([thisWeakPtr](void) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_multiplayer_subscriptions_lost(); + } + }); + + m_rtaResyncContext = m_multiplayerLocalUserManager->add_rta_resync_handler([thisWeakPtr](void) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_resync_message_received(); + } + }); +} + +void +multiplayer_client_manager::initialize() +{ + if (m_multiplayerLocalUserManager == nullptr) + { + m_multiplayerLocalUserManager = std::make_shared(); + register_local_user_manager_events(); + } + + m_latestPendingRead = std::make_shared( + m_lobbySessionTemplateName, + m_multiplayerLocalUserManager + ); + + m_lastPendingRead = std::make_shared(); + m_subscriptionsLostFired.store(false); + m_latestPendingRead->set_auto_fill_members_during_matchmaking(m_autoFillMembers); +} + +void multiplayer_client_manager::shutdown() +{ + std::lock_guard guard(m_clientRequestLock); + destroy(); +} + +void +multiplayer_client_manager::destroy() +{ + m_latestPendingRead.reset(); + m_lastPendingRead.reset(); + if (m_multiplayerLocalUserManager != nullptr) + { + m_multiplayerLocalUserManager->remove_multiplayer_session_changed_handler(m_sessionChangedContext); + m_multiplayerLocalUserManager->remove_multiplayer_subscription_lost_handler(m_subscriptionLostContext); + m_multiplayerLocalUserManager->remove_rta_resync_handler(m_rtaResyncContext); + m_multiplayerLocalUserManager.reset(); + } +} + +std::shared_ptr +multiplayer_client_manager::local_user_manager() +{ + return m_multiplayerLocalUserManager; +} + +xbox_live_result +multiplayer_client_manager::set_properties( + _In_ const multiplayer_session_reference& sessionRef, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + // Note: sessionRef can be empty for the lobby initially as we may have not created one yet. + RETURN_CPP_IF(name.empty(), void, xbox_live_error_code::invalid_argument, "Name was empty"); + + std::lock_guard guard(m_clientRequestLock); + RETURN_CPP_IF(latest_pending_read() == nullptr || get_xbox_live_context_map().size() == 0, void, xbox_live_error_code::logic_error, "Call add_local_user() before writing lobby properties."); + + latest_pending_read()->set_properties(sessionRef, name, valueJson, context); + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_manager::set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ) +{ + std::lock_guard guard(m_clientRequestLock); + RETURN_CPP_IF(latest_pending_read() == nullptr || get_xbox_live_context_map().size() == 0, void, xbox_live_error_code::logic_error, "Call add_local_user() before writing lobby properties."); + + return latest_pending_read()->lobby_client()->set_joinability(value, context); +} + +xbox_live_result +multiplayer_client_manager::set_synchronized_host( + _In_ const multiplayer_session_reference& sessionRef, + _In_ const string_t& hostDeviceToken, + _In_opt_ context_t context + ) +{ + // Note: sessionRef can be empty for the lobby initially as we may have not created one yet. + RETURN_CPP_IF(hostDeviceToken.empty(), void, xbox_live_error_code::invalid_argument, "HostDeviceToken was empty"); + + std::lock_guard guard(m_clientRequestLock); + RETURN_CPP_IF(latest_pending_read() == nullptr || get_xbox_live_context_map().size() == 0, void, xbox_live_error_code::logic_error, "Call add_local_user() before writing host properties."); + + latest_pending_read()->set_synchronized_host(sessionRef, hostDeviceToken, context); + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_manager::set_synchronized_properties( + _In_ const multiplayer_session_reference& sessionRef, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + // Note: sessionRef can be empty for the lobby initially as we may have not created one yet. + RETURN_CPP_IF(name.empty(), void, xbox_live_error_code::invalid_argument, "Name was empty"); + + std::lock_guard guard(m_clientRequestLock); + RETURN_CPP_IF(latest_pending_read() == nullptr || get_xbox_live_context_map().size() == 0, void, xbox_live_error_code::logic_error, "Call add_local_user() before writing lobby properties."); + + latest_pending_read()->set_synchronized_properties(sessionRef, name, valueJson, context); + return xbox_live_result(); +} + +void +multiplayer_client_manager::synchronized_write_completed( + _In_ std::error_code errorCode, + _In_ std::string errorMessage, + _In_ multiplayer_event_type eventType, + _In_ multiplayer_session_type sessionType + ) +{ + add_multiplayer_event(eventType, sessionType, errorCode, errorMessage); +} + +xbox_live_result +multiplayer_client_manager::join_lobby_by_handle( + _In_ const string_t& handleId, + _In_ std::vector users + ) +{ + if(handleId.empty()) return xbox_live_result(xbox_live_error_code::invalid_argument); + if (users.size() == 0) return xbox_live_result(xbox_live_error_code::invalid_argument); + + if (latest_pending_read() == nullptr) + { + initialize(); + } + + latest_pending_read()->lobby_client()->add_local_users(users, handleId); + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_manager::join_lobby_by_session_reference( + _In_ const multiplayer_session_reference& sessionRef, + _In_ std::vector users + ) +{ + if(sessionRef.is_null()) return xbox_live_result(xbox_live_error_code::invalid_argument); + if (users.size() == 0) return xbox_live_result(xbox_live_error_code::invalid_argument); + + if (latest_pending_read() == nullptr) + { + initialize(); + } + + latest_pending_read()->lobby_client()->add_local_users(users, sessionRef); + return xbox_live_result(); +} + +#if !XSAPI_U +xbox_live_result +multiplayer_client_manager::join_lobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ std::vector users + ) +{ + if (users.size() == 0) return xbox_live_error_code::invalid_argument; + + auto url = ref new Windows::Foundation::Uri(eventArgs->Uri->RawUri); + return join_lobby(url, users); +} + +xbox_live_result +multiplayer_client_manager::join_lobby( + _In_ Windows::Foundation::Uri^ url, + _In_ std::vector users + ) +{ + string_t handleId; + string_t invitedXuid; + multiplayer_session_reference teamSessionRef; + if (utils::str_icmp(url->Host->Data(), _T("inviteHandleAccept")) == 0) + { + handleId = url->QueryParsed->GetFirstValueByName("handle")->Data(); + invitedXuid = url->QueryParsed->GetFirstValueByName("invitedXuid")->Data(); + } + else if(utils::str_icmp(url->Host->Data(), _T("activityHandleJoin")) == 0) + { + handleId = url->QueryParsed->GetFirstValueByName("handle")->Data(); + invitedXuid = url->QueryParsed->GetFirstValueByName("joinerXuid")->Data(); + } + else if (utils::str_icmp(url->Host->Data(), _T("tournament")) == 0) + { + // Only used for Tournament MPM integration support. + string_t action = url->QueryParsed->GetFirstValueByName("action")->Data(); + if (utils::str_icmp(action, _T("joinGame")) != 0) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid tournament protocol passed into join_lobby() API."); + } + + invitedXuid = url->QueryParsed->GetFirstValueByName("joinerXuid")->Data(); + + string_t scid = url->QueryParsed->GetFirstValueByName("scid")->Data(); + string_t templateName = url->QueryParsed->GetFirstValueByName("templateName")->Data(); + string_t sessionName = url->QueryParsed->GetFirstValueByName("name")->Data(); + teamSessionRef = multiplayer_session_reference(scid, templateName, sessionName); + } + else + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid protocol passed into join_lobby() API."); + } + + // Check if the xuid matches with the sent users. + bool invitedUserFound = false; + for (auto& user: users) + { + if (utils::str_icmp(invitedXuid, user_context::get_user_id(user)) == 0) + { + invitedUserFound = true; + break; + } + } + + if (!invitedUserFound) + { + // The invited user hasn't been added. + std::shared_ptr joinLobbyEventArgs = std::make_shared(invitedXuid); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::logic_error, + "InvitedXuid's user hasn't been added. Pass in the invited user into join_lobby() API.", + multiplayer_event_type::join_lobby_completed, + std::dynamic_pointer_cast(joinLobbyEventArgs), + multiplayer_session_type::lobby_session + ); + + // Since m_latestPendingRead hasn't been initialized yet, this will ensure + // the event is still returned correctly through multiplayer_manager::do_work(); + m_multiplayerEventQueue.push_back(multiplayerEvent); + + return xbox_live_result(xbox_live_error_code::logic_error, "Pass in the invited user into join_lobby() API."); + } + + // This will also join any game that is associated with the lobby. + if (!handleId.empty()) + { + return join_lobby_by_handle(handleId, users); + } + + return join_lobby_by_session_reference(teamSessionRef, users); +} +#endif + +xbox_live_result +multiplayer_client_manager::join_game_from_lobby( + _In_ const string_t& sessionTemplateName + ) +{ + auto primaryContext = get_primary_context(); + auto latestPending = latest_pending_read(); + if( primaryContext == nullptr || latestPending == nullptr || latestPending->lobby_client()->session() == nullptr) + { + return xbox_live_result(xbox_live_error_code::logic_error, "No lobby session exists. Call add_local_user() to create a lobby first."); + } + + if (latestPending->game_client()->session() != nullptr) + { + return xbox_live_result(xbox_live_error_code::logic_error, "A game session already exists. Call leave_game() to leave existing game before creating a new one."); + } + + if (latestPending->match_client()->match_status() > match_status::none) + { + return xbox_live_result(xbox_live_error_code::logic_error, "Matchmaking is currently in progress. Call cancel_match() before joining a game."); + } + + latestPending->game_client()->set_game_session_template(sessionTemplateName); + return latestPending->game_client()->join_game_from_lobby_helper(); +} + +xbox_live_result +multiplayer_client_manager::join_game( + _In_ const string_t& sessionName, + _In_ const string_t& sessionTemplateName, + _In_ const std::vector& xboxUserIds + ) +{ + if(sessionName.empty()) return xbox_live_result(xbox_live_error_code::invalid_argument); + + std::shared_ptr primaryContext = get_primary_context(); + RETURN_CPP_IF(primaryContext == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() before joining."); + + if (latest_pending_read()->match_client()->match_status() > match_status::none) + { + return xbox_live_result(xbox_live_error_code::logic_error, "Matchmaking is currently in progress. Call cancel_match() before joining a game."); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + create_task([thisWeakPtr, primaryContext, sessionName, sessionTemplateName, xboxUserIds]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, void, xbox_live_error_code::generic_error, "multiplayer_client_manager class was destroyed."); + + auto gameClient = pThis->latest_pending_read()->game_client(); + RETURN_CPP_IF(gameClient == nullptr, void, xbox_live_error_code::generic_error, "multiplayer_game_client class was destroyed."); + + if (xboxUserIds.size() > 0) + { + // Create a session with reservations. + multiplayer_session_reference gameSessionRef(utils::try_get_override_scid(), sessionTemplateName, sessionName); + auto gameSession = std::make_shared( + primaryContext->xbox_live_user_id(), + gameSessionRef, + xboxUserIds + ); + + gameSession->join(web::json::value::null(), false); + for (const auto& memberXuid : xboxUserIds) + { + if (utils::str_icmp(memberXuid, primaryContext->xbox_live_user_id()) != 0) + { + gameSession->add_member_reservation(memberXuid); + } + } + auto result = primaryContext->multiplayer_service().write_session(gameSession, multiplayer_session_write_mode::update_or_create_new).get(); + if (result.err()) + { + multiplayer_event multiplayerEvent( + result.err(), + result.err_message(), + multiplayer_event_type::join_game_completed, + std::make_shared(), + multiplayer_session_type::game_session + ); + + pThis->add_to_multiplayer_event_queue(multiplayerEvent); + return xbox_live_result(); + } + + // Continue joining the session for all local users. + } + + gameClient->set_game_session_template(sessionTemplateName); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(gameClient->join_game_helper(sessionName), void); + }); + + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_manager::leave_game() +{ + std::shared_ptr primaryContext = get_primary_context(); + auto latestPendingRead = latest_pending_read(); + if(latestPendingRead == nullptr || primaryContext == nullptr) + { + return xbox_live_result(xbox_live_error_code::logic_error, "Call add_local_user() before committing."); + } + + auto gameSession = latestPendingRead->game_client()->session(); + if (gameSession != nullptr) + { + latestPendingRead->game_client()->leave_remote_session(gameSession, true, true); + } + + if (latestPendingRead->match_client()->match_status() != match_status::none) + { + latestPendingRead->match_client()->cancel_match(); + latestPendingRead->match_client()->set_match_status(match_status::canceled); + latestPendingRead->match_client()->handle_find_match_completed(xbox_live_error_code::generic_error, "Matchmaking request was canceled since leave_game() was called."); + } + + m_multiplayerLocalUserManager->change_all_local_user_game_state(multiplayer_local_user_game_state::unknown); + return xbox_live_result(xbox_live_error_code::no_error); +} + +pplx::task>> +multiplayer_client_manager::get_activities_for_social_group( + _In_ xbox_live_user_t user, + _In_ const string_t& socialGroup + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(user == nullptr, std::vector, "Invalid xboxLiveContext argument passed."); + + return get_multiplayer_service(user).get_activities_for_social_group( + utils::try_get_override_scid(), + multiplayer_manager_utils::get_local_user_xbox_user_id(user), + socialGroup); +} + +xbox_live_result +multiplayer_client_manager::invite_friends( + _In_ xbox_live_user_t user, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ) +{ + RETURN_CPP_IF(user == nullptr, void, xbox_live_error_code::invalid_argument, "Invalid user argument passed."); + RETURN_CPP_IF(latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() and wait for user_added completion event before sending invites."); + RETURN_CPP_IF(latest_pending_read()->lobby_client()->session() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() and wait for user_added completion event before sending invites."); + + std::weak_ptr thisWeakPtr = shared_from_this(); + +#if TV_API + + auto sessionRef = latest_pending_read()->lobby_client()->session()->session_reference(); + auto sessionReferenceToInviteTo = ref new Windows::Xbox::Multiplayer::MultiplayerSessionReference( + ref new Platform::String(sessionRef.session_name().c_str()), + ref new Platform::String(sessionRef.service_configuration_id().c_str()), + ref new Platform::String(sessionRef.session_template_name().c_str()) + ); + + auto asyncOp = Windows::Xbox::UI::SystemUI::ShowSendGameInvitesAsync( + user, + sessionReferenceToInviteTo, + ref new Platform::String(contextStringId.c_str()), + ref new Platform::String(customActivationContext.c_str()) + ); + + pplx::create_task(asyncOp) + .then([thisWeakPtr](pplx::task t) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if(pThis != nullptr) + { + try + { + t.get(); + pThis->add_multiplayer_event(multiplayer_event_type::invite_sent, multiplayer_session_type::lobby_session); + } + catch (Platform::Exception^ ex) + { + xbox_live_error_code err = utils::convert_exception_to_xbox_live_error_code(); + pThis->add_multiplayer_event(multiplayer_event_type::invite_sent, multiplayer_session_type::lobby_session, err, "Failed sending invites."); + } + } + }); +#else + UNREFERENCED_PARAMETER(customActivationContext); +#if !XBOX_UWP +#if !UNIT_TEST_SERVICES + + auto asyncOp = xbox::services::system::title_callable_ui::show_game_invite_ui( + latest_pending_read()->lobby_client()->session()->session_reference(), + contextStringId + ); + + pplx::create_task(asyncOp) + .then([thisWeakPtr](xbox_live_result result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->add_multiplayer_event(multiplayer_event_type::invite_sent, multiplayer_session_type::lobby_session, result.err(), result.err_message()); + } + }); +#endif +#endif +#endif + + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_manager::invite_users( + _In_ xbox_live_user_t user, + _In_ const std::vector& xboxUserIds, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ) +{ + RETURN_CPP_IF(user == nullptr, void, xbox_live_error_code::invalid_argument, "Invalid user argument passed."); + RETURN_CPP_IF(latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() and wait for user_added completion event before sending invites."); + RETURN_CPP_IF(latest_pending_read()->lobby_client()->session() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() and wait for user_added completion event before sending invites."); + + std::weak_ptr thisWeakPtr = shared_from_this(); + + auto task = get_multiplayer_service(user).send_invites( + latest_pending_read()->lobby_client()->session()->session_reference(), + xboxUserIds, + utils::try_get_master_title_id(), + contextStringId, + customActivationContext + ) + .then([thisWeakPtr](xbox_live_result> result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->add_multiplayer_event(multiplayer_event_type::invite_sent, multiplayer_session_type::lobby_session, result.err(), result.err_message()); + } + }); + + return xbox_live_result(); +} + +multiplayer_service& +multiplayer_client_manager::get_multiplayer_service( + _In_ xbox_live_user_t user + ) +{ + auto localUser = m_multiplayerLocalUserManager->get_local_user(user); + if (localUser != nullptr) + { + m_clientManagerMultiplayerService = localUser->context()->multiplayer_service(); + } + else + { + std::shared_ptr userContext; + + userContext = std::make_shared(user); + std::shared_ptr xboxLiveContextSettings = std::make_shared(); + std::shared_ptr appConfig = xbox::services::xbox_live_app_config::get_app_config_singleton(); + m_clientManagerMultiplayerService = multiplayer_service(userContext, xboxLiveContextSettings, appConfig, nullptr); + } + + return m_clientManagerMultiplayerService; +} + +std::shared_ptr +multiplayer_client_manager::latest_pending_read() const +{ + return m_latestPendingRead; +} + +std::shared_ptr +multiplayer_client_manager::last_pending_read() const +{ + std::lock_guard guard(m_clientRequestLock); + return m_lastPendingRead; +} + +std::shared_ptr +multiplayer_client_manager::lobby_client() const +{ + return m_latestPendingRead->lobby_client(); +} + +bool +multiplayer_client_manager::is_request_in_progress() +{ + if (m_latestPendingRead->lobby_client()->is_request_in_progress() || + m_latestPendingRead->game_client()->is_request_in_progress()) + { + return true; + } + + return false; +} + +bool +multiplayer_client_manager::is_update_avaialable() +{ + if (m_latestPendingRead == nullptr) + { + return false; + } + + if (m_lastPendingRead->is_update_avaialable(*m_latestPendingRead)) + { + return true; + } + + if (get_xbox_live_context_map().size() == 0 && is_request_in_progress()) + { + return true; + } + + // Always do work for match + m_latestPendingRead->process_match_events(); + + return false; +} + +std::vector +multiplayer_client_manager::do_work() +{ + std::lock_guard guard(m_clientRequestLock); + + if (m_latestPendingRead == nullptr) + { + return std::vector(); + } + + m_latestPendingRead->do_work(); + + process_events(m_latestPendingRead->lobby_client()->session(), m_lastPendingRead->lobby_client()->session(), multiplayer_session_type::lobby_session); + process_events(m_latestPendingRead->game_client()->session(), m_lastPendingRead->game_client()->session(), multiplayer_session_type::game_session); + process_events(m_latestPendingRead->match_client()->session(), m_lastPendingRead->match_client()->session(), multiplayer_session_type::match_session); + + m_lastPendingRead->deep_copy_if_updated(*m_latestPendingRead); + auto eventQueue = m_lastPendingRead->multiplayer_event_queue(); + + if (get_xbox_live_context_map().size() == 0 && !is_request_in_progress()) + { + if (!m_subscriptionsLostFired) + { + // Force client disconnected event to fire for consistent developer behavior. + on_multiplayer_subscriptions_lost(); + } + else + { + // If the last person just left and no more events left, destroy all objects. + destroy(); + return eventQueue; + } + } + + m_latestPendingRead->clear_multiplayer_event_queue(); + m_lastPendingRead->clear_multiplayer_event_queue(); + + return eventQueue; +} + +std::map> +multiplayer_client_manager::get_xbox_live_context_map() +{ + return m_multiplayerLocalUserManager->get_local_user_map(); +} + +std::shared_ptr +multiplayer_client_manager::get_primary_context() +{ + return m_multiplayerLocalUserManager->get_primary_context(); +} + +void +multiplayer_client_manager::on_multiplayer_subscriptions_lost() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + create_task([thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + std::lock_guard guard(pThis->m_clientRequestLock); + + bool expected = false; + if (pThis->m_subscriptionsLostFired.compare_exchange_strong(expected, true)) + { + // Fired when the title's connection to MPSD using the real-time activity service is lost. + // When this event occurs, the title should shut down the multiplayer. + + auto lobbyClient = pThis->lobby_client(); + if (lobbyClient != nullptr) + { + lobbyClient->remove_all_local_users(); + } + + pThis->add_multiplayer_event_helper(multiplayer_event_type::client_disconnected_from_multiplayer_service, multiplayer_session_type::lobby_session); + } + } + }); +} + +void +multiplayer_client_manager::on_resync_message_received() +{ + // Upon receiving RTA resync message, re-fetch all multiplayer sessions. + // Note: You could get multiple re-sync messages. It's recommended that you only fetch once every 30 secs. + if (m_latestPendingRead != nullptr) + { + auto latestPendingReadSharedPtr = m_latestPendingRead; + create_task([latestPendingReadSharedPtr]() + { + latestPendingReadSharedPtr->lobby_client()->session_writer()->on_resync_message_received(); + latestPendingReadSharedPtr->game_client()->session_writer()->on_resync_message_received(); + }); + } +} + +void +multiplayer_client_manager::on_session_changed( + _In_ const multiplayer_session_change_event_args& args + ) +{ + std::lock_guard guard(m_synchronizeWriteWithTapLock); + + if (m_latestPendingRead != nullptr) + { + multiplayer_session_reference sessionRef = args.session_reference(); + if (m_latestPendingRead->is_match(sessionRef)) + { + m_latestPendingRead->match_client()->on_session_changed(args); + } + + if (m_latestPendingRead->is_lobby(sessionRef)) + { + m_latestPendingRead->lobby_client()->session_writer()->on_session_changed(args); + } + else if (m_latestPendingRead->is_game(sessionRef)) + { + m_latestPendingRead->game_client()->session_writer()->on_session_changed(args); + } + } +} + +std::vector +multiplayer_client_manager::event_queue() const +{ + std::lock_guard guard(m_clientRequestLock); + return m_multiplayerEventQueue; +} + +void +multiplayer_client_manager::clear_event_queue() +{ + std::lock_guard lock(m_clientRequestLock); + m_multiplayerEventQueue.clear(); +} + +void +multiplayer_client_manager::add_to_multiplayer_event_queue( + _In_ multiplayer_event multiplayerEvent + ) +{ + // Note: This function does not require a lock. Caller already has a m_clientRequestLock + + if (m_latestPendingRead != nullptr) + { + m_latestPendingRead->add_to_multiplayer_event_queue(multiplayerEvent); + } +} + +void +multiplayer_client_manager::add_multiplayer_event_helper( + _In_ multiplayer_event_type eventType, + _In_ multiplayer_session_type sessionType, + _In_ std::error_code errorCode, + _In_ std::string errorMessage + ) +{ + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + eventType, + std::make_shared(), + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); +} + +void +multiplayer_client_manager::add_multiplayer_event( + _In_ multiplayer_event_type eventType, + _In_ multiplayer_session_type sessionType, + _In_ std::error_code errorCode, + _In_ std::string errorMessage + ) +{ + std::lock_guard guard(m_clientRequestLock); + add_multiplayer_event_helper(eventType, sessionType, errorCode, errorMessage); +} + +multiplayer_session_type +multiplayer_client_manager::get_session_type( + _In_ std::shared_ptr session + ) +{ + multiplayer_session_type sessionType = multiplayer_session_type::unknown; + if (latest_pending_read()->is_lobby(session->session_reference())) + { + sessionType = multiplayer_session_type::lobby_session; + } + else if (latest_pending_read()->is_game(session->session_reference())) + { + sessionType = multiplayer_session_type::game_session; + } + + return sessionType; +} + +void +multiplayer_client_manager::process_events( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ) +{ + if (oldSession == nullptr || currentSession == nullptr || oldSession->change_number() == currentSession->change_number()) + { + return; + } + + xbox_live_result diff = multiplayer_session::compare_multiplayer_sessions(currentSession, oldSession); + if (!diff.err() && diff.payload() == multiplayer_session_change_types::none) + { + return; + } + + multiplayer_session_change_types diffType = diff.payload(); + + if (sessionType != multiplayer_session_type::match_session) + { + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::host_device_token_change)) + { + handle_host_changed(currentSession, sessionType); + } + + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::member_list_change)) + { + handle_member_list_changed(currentSession, oldSession, sessionType); + } + + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::custom_property_change)) + { + handle_session_properties_changed(currentSession, oldSession, sessionType); + } + + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::member_custom_property_change)) + { + handle_member_properties_changed(currentSession, oldSession, sessionType); + } + } + + if (sessionType != multiplayer_session_type::game_session) + { + // Don't need to process these for game. The match will take care of handling these events. + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::matchmaking_status_change)) + { + m_latestPendingRead->match_client()->handle_match_status_changed(currentSession); + } + } + + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::tournament_property_change)) + { + handle_tournament_properties_changed(currentSession, oldSession, sessionType); + } + + if (multiplayer_manager_utils::is_multiplayer_session_change_type(diffType, multiplayer_session_change_types::arbitration_property_change)) + { + if (currentSession->arbitration_server().result_state() != oldSession->arbitration_server().result_state() && + currentSession->arbitration_server().result_state() == tournaments::tournament_arbitration_state::completed) + { + add_multiplayer_event_helper(multiplayer_event_type::arbitration_complete, sessionType); + } + } +} + +void +multiplayer_client_manager::handle_member_list_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ) +{ + std::map> currentSessionMembers; + std::map> oldSessionMembers; + + for (const auto& currentSessionMember : currentSession->members()) + { + currentSessionMembers[currentSessionMember->xbox_user_id()] = currentSessionMember; + } + + for (const auto& oldSessionMember : oldSession->members()) + { + oldSessionMembers[oldSessionMember->xbox_user_id()] = oldSessionMember; + } + + bool haveMembersJoined = false; + bool haveMembersLeft = false; + + // See if any new members joined + std::vector> membersJoined; + for (const auto& currentSessionMember : currentSession->members()) + { + if (oldSessionMembers.find(currentSessionMember->xbox_user_id()) == oldSessionMembers.end()) + { + haveMembersJoined = true; + membersJoined.push_back(currentSessionMember); + } + } + + // See if any members left + std::vector> membersLeft; + for (const auto& oldSessionMember : oldSession->members()) + { + if (currentSessionMembers.find(oldSessionMember->xbox_user_id()) == currentSessionMembers.end()) + { + haveMembersLeft = true; + membersLeft.push_back(oldSessionMember); + } + } + + if (haveMembersJoined || haveMembersLeft) + { + if (haveMembersJoined) + { + std::vector> gameMembers; + for (const auto& member : membersJoined) + { + gameMembers.push_back(latest_pending_read()->convert_to_game_member(member)); + } + + std::shared_ptr memberJoinedEventArgs = std::make_shared( + gameMembers + ); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::member_joined, + std::dynamic_pointer_cast(memberJoinedEventArgs), + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); + } + + if (haveMembersLeft) + { + std::vector> gameMembers; + for (const auto& member : membersLeft) + { + gameMembers.push_back(latest_pending_read()->convert_to_game_member(member)); + } + + std::shared_ptr memberLeftEventArgs = std::make_shared( + gameMembers + ); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::member_left, + std::dynamic_pointer_cast(memberLeftEventArgs), + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); + } + } +} + +void +multiplayer_client_manager::handle_member_properties_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ) +{ + std::map> oldSessionMembers; + for (const auto& oldSessionMember : oldSession->members()) + { + oldSessionMembers[oldSessionMember->xbox_user_id()] = oldSessionMember; + } + + // See if properties changed and add them to the queue. + std::vector> memberPropertiesChanged; + for (const auto& currentSessionMember : currentSession->members()) + { + if (oldSessionMembers.find(currentSessionMember->xbox_user_id()) != oldSessionMembers.end()) + { + std::shared_ptr oldSessionMember = oldSessionMembers[currentSessionMember->xbox_user_id()]; + if (utils::str_icmp(currentSessionMember->member_custom_properties_json().serialize(), + oldSessionMember->member_custom_properties_json().serialize()) != 0) + { + memberPropertiesChanged.push_back(currentSessionMember); + } + } + } + + if (memberPropertiesChanged.size() > 0) + { + std::vector> gameMembers; + const auto& localUserMap = m_multiplayerLocalUserManager->get_local_user_map(); + for (const auto& member : memberPropertiesChanged) + { + auto iter = localUserMap.find(member->xbox_user_id()); + if (iter != localUserMap.end()) + { + // Don't trigger member property changed events for local users. + continue; + } + + std::shared_ptr memberPropertiesChangedArgs = std::make_shared( + latest_pending_read()->convert_to_game_member(member), + member->member_custom_properties_json() + ); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::member_property_changed, + std::dynamic_pointer_cast(memberPropertiesChangedArgs), + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); + } + } +} + +void +multiplayer_client_manager::handle_session_properties_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ) +{ + if (sessionType == multiplayer_session_type::lobby_session && + m_multiplayerLocalUserManager->is_local_user_game_state(multiplayer_local_user_game_state::pending_join)) + { + // Don't join the game if matchmaking is in progress. + if (latest_pending_read()->match_client()->match_status() == match_status::none) + { + // If state is completed, or transfer handle was removed. + if ( latest_pending_read()->lobby_client()->is_transfer_handle_state(_T("completed")) || + (multiplayer_manager_utils::has_session_property_changed(currentSession, oldSession, multiplayer_lobby_client::c_transferHandlePropertyName) && + latest_pending_read()->lobby_client()->get_transfer_handle().empty()) + ) + { + m_multiplayerLocalUserManager->change_all_local_user_game_state(multiplayer_local_user_game_state::join); + + // Join the game session using the handleId. + latest_pending_read()->game_client()->join_game_from_lobby_helper(); + } + } + } + + // Don't trigger property changed event if the transfer handle property changes. + if (multiplayer_manager_utils::has_session_property_changed(currentSession, oldSession, multiplayer_lobby_client::c_transferHandlePropertyName) || + multiplayer_manager_utils::has_session_property_changed(currentSession, oldSession, multiplayer_lobby_client::c_joinabilityPropertyName)) + { + return; + } + + auto gamePropertiesChangedArgs = std::make_shared( + currentSession->session_properties()->session_custom_properties_json() + ); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::session_property_changed, + std::dynamic_pointer_cast(gamePropertiesChangedArgs), + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); +} + +void +multiplayer_client_manager::handle_host_changed( + _In_ std::shared_ptr currentSession, + _In_ multiplayer_session_type sessionType + ) +{ + /// A host may have left, and there may be no new host. + std::shared_ptr hostMemeber = nullptr; + std::shared_ptr host = multiplayer_manager_utils::host_member(currentSession); + if (host != nullptr) + { + hostMemeber = latest_pending_read()->convert_to_game_member(host); + } + + std::shared_ptr hostChangedEventArgs = std::make_shared( + hostMemeber + ); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::host_changed, + std::dynamic_pointer_cast(hostChangedEventArgs), + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); +} + +void +multiplayer_client_manager::handle_tournament_properties_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ) +{ + auto currTournamentsServer = currentSession->tournaments_server(); + auto oldTournamentsServer = oldSession->tournaments_server(); + if (currTournamentsServer.registration_state() != oldTournamentsServer.registration_state() || + currTournamentsServer.registration_reason() != oldTournamentsServer.registration_reason()) + { + auto registrationStateChangedEventArgs = std::make_shared( + currTournamentsServer.registration_state(), + currTournamentsServer.registration_reason() + ); + + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::tournament_registration_state_changed, + registrationStateChangedEventArgs, + sessionType + ); + + add_to_multiplayer_event_queue(multiplayerEvent); + } + + auto currentGameSessionRef = currTournamentsServer.next_game_session_reference(); + if ( sessionType == multiplayer_session_type::lobby_session && + currentSession->session_constants()->capabilities_team() && + !currentGameSessionRef.is_null() && + currentGameSessionRef._Serialize() != oldTournamentsServer.next_game_session_reference()._Serialize()) + { + latest_pending_read()->lobby_client()->handle_game_session_ready_event(currentSession); + } +} + +std::shared_ptr +multiplayer_client_manager::match_client() +{ + return latest_pending_read()->match_client(); +} + +xbox_live_result +multiplayer_client_manager::find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout +) +{ + RETURN_CPP_IF(latest_pending_read() == nullptr || latest_pending_read()->lobby_client()->session() == nullptr, void, xbox_live_error_code::logic_error, "No local user added. Call add_local_user() first."); + return latest_pending_read()->find_match(hopperName, attributes, timeout); +} + +void +multiplayer_client_manager::set_auto_fill_members_during_matchmaking( + _In_ bool autoFillMembers + ) +{ + m_autoFillMembers = autoFillMembers; + if (latest_pending_read() != nullptr) + { + latest_pending_read()->set_auto_fill_members_during_matchmaking(autoFillMembers); + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_client_pending_reader.cpp b/Source/Services/Multiplayer/Manager/multiplayer_client_pending_reader.cpp new file mode 100644 index 00000000..cd291e99 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_client_pending_reader.cpp @@ -0,0 +1,460 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +void multiplayer_client_pending_reader::deep_copy_if_updated( + _In_ const multiplayer_client_pending_reader& other + ) +{ + std::lock_guard lock(other.m_clientRequestLock); + + m_multiplayerEventQueue = other.m_multiplayerEventQueue; + if (other.m_lobbyClient == nullptr) + { + m_lobbyClient = nullptr; + } + else + { + m_lobbyClient->deep_copy_if_updated(*other.m_lobbyClient); + } + + if (other.m_gameClient == nullptr) + { + m_gameClient = nullptr; + } + else + { + m_gameClient->deep_copy_if_updated(*other.m_gameClient); + } + + if (other.m_matchClient == nullptr) + { + m_matchClient = nullptr; + } + else + { + m_matchClient->deep_copy_if_updated(*other.m_matchClient); + } +} + +multiplayer_client_pending_reader::multiplayer_client_pending_reader() : + m_autoFillMembers(false) +{ + m_multiplayerLocalUserManager = std::make_shared(); + m_lobbyClient = std::make_shared(); + m_gameClient = std::make_shared(); + m_matchClient = std::make_shared(m_multiplayerLocalUserManager); +} + +multiplayer_client_pending_reader::~multiplayer_client_pending_reader() +{ + m_lobbyClient.reset(); + m_gameClient.reset(); + m_matchClient.reset(); + m_multiplayerLocalUserManager.reset(); +} + +multiplayer_client_pending_reader::multiplayer_client_pending_reader( + _In_ string_t lobbySessionTemplateName, + _In_ std::shared_ptr localUserManager + ) : + m_multiplayerLocalUserManager(localUserManager), + m_autoFillMembers(false) +{ + m_lobbyClient = std::make_shared(lobbySessionTemplateName, m_multiplayerLocalUserManager); + m_gameClient = std::make_shared(m_multiplayerLocalUserManager); + m_matchClient = std::make_shared(m_multiplayerLocalUserManager); + m_lobbyClient->initialize(); + m_gameClient->initialize(); +} + +bool +multiplayer_client_pending_reader::is_update_avaialable( + _In_ const multiplayer_client_pending_reader& other + ) +{ + std::lock_guard lock(other.m_clientRequestLock); + + if (other.m_lobbyClient->is_pending_lobby_changes() || + other.m_gameClient->is_pending_game_changes()) + { + return true; + } + + auto lobbySession = m_lobbyClient->session(); + auto otherLobbySession = other.m_lobbyClient->session(); + auto gameSession = m_gameClient->session(); + auto otherGameSession = other.m_gameClient->session(); + if ( !multiplayer_manager_utils::compare_sessions(lobbySession, otherLobbySession) || + !multiplayer_manager_utils::compare_sessions(gameSession, otherGameSession) || + !multiplayer_manager_utils::compare_sessions(m_matchClient->session(), other.m_matchClient->session()) || + m_lobbyClient->multiplayer_event_queue().size() != other.m_lobbyClient->multiplayer_event_queue().size() || + m_gameClient->multiplayer_event_queue().size() != other.m_gameClient->multiplayer_event_queue().size() || + m_matchClient->multiplayer_event_queue().size() != other.m_matchClient->multiplayer_event_queue().size() || + m_multiplayerEventQueue.size() != other.m_multiplayerEventQueue.size()) + { + return true; + } + + return false; +} + +std::shared_ptr +multiplayer_client_pending_reader::lobby_client() +{ + return m_lobbyClient; +} + +std::shared_ptr +multiplayer_client_pending_reader::game_client() +{ + return m_gameClient; +} + +std::shared_ptr +multiplayer_client_pending_reader::match_client() +{ + return m_matchClient; +} + +void +multiplayer_client_pending_reader::update_session( + _In_ multiplayer_session_reference sessionRef, + _In_ std::shared_ptr session + ) +{ + std::lock_guard lock(m_clientRequestLock); + + if (is_lobby(sessionRef)) + { + m_lobbyClient->update_session(session); + } + else if(is_game(sessionRef)) + { + m_gameClient->update_session(session); + } +} + +std::shared_ptr +multiplayer_client_pending_reader::get_session( + _In_ multiplayer_session_reference sessionRef + ) +{ + if (is_lobby(sessionRef)) + { + return m_lobbyClient->session(); + } + else if (is_game(sessionRef)) + { + return m_gameClient->session(); + } + + return nullptr; +} + +bool +multiplayer_client_pending_reader::is_lobby( + _In_ multiplayer_session_reference sessionRef + ) +{ + if (sessionRef.is_null() || m_lobbyClient == nullptr || m_lobbyClient->session() == nullptr) + { + return false; + } + + return multiplayer_manager_utils::do_session_references_match(sessionRef, m_lobbyClient->session()->session_reference()); +} + +bool +multiplayer_client_pending_reader::is_game( + _In_ multiplayer_session_reference sessionRef + ) +{ + if (sessionRef.is_null() || m_gameClient == nullptr || m_gameClient->session() == nullptr) + { + return false; + } + + return multiplayer_manager_utils::do_session_references_match(sessionRef, m_gameClient->session()->session_reference()); +} + +bool +multiplayer_client_pending_reader::is_match( + _In_ multiplayer_session_reference sessionRef +) +{ + if (sessionRef.is_null() || m_matchClient == nullptr || m_matchClient->session() == nullptr) + { + return false; + } + + return multiplayer_manager_utils::do_session_references_match(sessionRef, m_matchClient->session()->session_reference()); +} + +std::vector +multiplayer_client_pending_reader::multiplayer_event_queue() const +{ + return m_multiplayerEventQueue; +} + +void +multiplayer_client_pending_reader::add_to_multiplayer_event_queue( + _In_ multiplayer_event multiplayerEvent + ) +{ + std::lock_guard lock(m_clientRequestLock); + m_multiplayerEventQueue.push_back(multiplayerEvent); +} + +void +multiplayer_client_pending_reader::add_to_multiplayer_event_queue( + _In_ std::vector multiplayerEventQueue + ) +{ + std::lock_guard lock(m_clientRequestLock); + if (multiplayerEventQueue.size() > 0) + { + for (const auto& multiplayerEvent : multiplayerEventQueue) + { + m_multiplayerEventQueue.push_back(multiplayerEvent); + } + } +} + +void +multiplayer_client_pending_reader::clear_multiplayer_event_queue() +{ + std::lock_guard lock(m_clientRequestLock); + m_multiplayerEventQueue.clear(); +} + +void +multiplayer_client_pending_reader::do_work() +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr && + m_lobbyClient->multiplayer_event_queue().size() == 0 && + m_gameClient->multiplayer_event_queue().size() == 0 && + m_matchClient->multiplayer_event_queue().size() == 0 && + m_multiplayerEventQueue.size() == 0) + { + // After the primaryContext has been deleted, the lobbyClient could have userRemoved event in the queue. + // The pending reader will also fire a client_disconnected_from_multiplayer_service event. + return; + } + + auto lobbySession = m_lobbyClient->session(); + auto gameSession = m_gameClient->session(); + m_lobbyClient->update_objects(lobbySession, gameSession); + m_gameClient->update_objects(gameSession, lobbySession); + + auto lobbyClientEventQueue = m_lobbyClient->do_work(); + add_to_multiplayer_event_queue(lobbyClientEventQueue); + + auto gameClientEventQueue = m_gameClient->do_work(); + add_to_multiplayer_event_queue(gameClientEventQueue); + + process_match_events(); +} + +xbox_live_result +multiplayer_client_pending_reader::set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ) +{ + return m_lobbyClient->set_joinability(value, context); +} + +xbox_live_result +multiplayer_client_pending_reader::set_properties( + _In_ multiplayer_session_reference sessionRef, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ) +{ + auto pendingRequest = std::make_shared(); + pendingRequest->set_session_properties(name, valueJson, context); + add_to_pending_queue(sessionRef, pendingRequest); + + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_pending_reader::set_synchronized_host( + _In_ multiplayer_session_reference sessionRef, + _In_ const string_t& hostDeviceToken, + _In_opt_ context_t context + ) +{ + auto pendingRequest = std::make_shared(); + pendingRequest->set_synchronized_host_device_token(hostDeviceToken, context); + add_to_pending_queue(sessionRef, pendingRequest); + + return xbox_live_result(); +} + +xbox_live_result +multiplayer_client_pending_reader::set_synchronized_properties( + _In_ multiplayer_session_reference sessionRef, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ) +{ + auto pendingRequest = std::make_shared(); + pendingRequest->set_synchronized_session_properties(name, valueJson, context); + add_to_pending_queue(sessionRef, pendingRequest); + + return xbox_live_result(); +} + +void +multiplayer_client_pending_reader::add_to_pending_queue( + _In_ multiplayer_session_reference sessionRef, + _In_ std::shared_ptr pendingRequest + ) +{ + if (sessionRef.session_name().empty() || is_lobby(sessionRef)) + { + m_lobbyClient->add_to_pending_queue(pendingRequest); + } + else if (is_game(sessionRef)) + { + m_gameClient->add_to_pending_queue(pendingRequest); + } +} + +bool +multiplayer_client_pending_reader::is_local( + _In_ const string_t& xboxUserId, + _In_ const std::map>& xboxLiveContextMap + ) +{ + if(xboxUserId.empty()) return false; + + for(auto& xboxLiveContext : xboxLiveContextMap) + { + std::shared_ptr localUser = xboxLiveContext.second; + if (localUser != nullptr && utils::str_icmp(xboxUserId, localUser->xbox_user_id()) == 0) + { + return true; + } + } + + return false; +} + +std::shared_ptr +multiplayer_client_pending_reader::convert_to_game_member( + _In_ std::shared_ptr member + ) +{ + return multiplayer_manager_utils::convert_to_game_member( + member, + m_lobbyClient->session(), + m_gameClient->session(), + m_multiplayerLocalUserManager->get_local_user_map() + ); +} + +void +multiplayer_client_pending_reader::process_match_events() +{ + if (m_matchClient == nullptr || m_matchClient->match_status() == match_status::none) return; + + auto matchEventQueue = m_matchClient->do_work(); + auto matchSession = m_matchClient->session(); + + if (matchEventQueue.size() > 0) + { + for (uint32_t i = 0; i < matchEventQueue.size(); i++) + { + multiplayer_event multiplayerEvent = matchEventQueue.at(i); + add_to_multiplayer_event_queue(multiplayerEvent); + + if (multiplayerEvent.event_type() == multiplayer_event_type::find_match_completed) + { + auto matchStatus = m_matchClient->match_status(); + if (multiplayerEvent.err()) + { + if (!multiplayer_manager_utils::do_sessions_match(m_gameClient->session(), matchSession) && + !multiplayer_manager_utils::do_sessions_match(m_lobbyClient->session(), matchSession)) + { + m_lobbyClient->session_writer()->leave_remote_session(matchSession); + } + } + + if (matchStatus == match_status::resubmitting) + { + auto lobbySessionCopy = m_lobbyClient->session()->_Create_deep_copy(); + m_matchClient->resubmit_matchmaking(lobbySessionCopy); + break; + } + + if (matchStatus == match_status::completed) + { + m_gameClient->update_game_session(matchSession); + m_lobbyClient->advertise_game_session(); + } + + if (m_autoFillMembers && matchSession != nullptr && + matchSession->members().size() < matchSession->session_constants()->max_members_in_session() && + (matchStatus == match_status::completed || matchStatus == match_status::expired)) + { + // Continue looking for more players + m_matchClient->set_match_status(match_status::none); + m_matchClient->find_match(matchSession, true); + break; + } + + m_matchClient->set_match_status(match_status::none); + m_matchClient->update_session(nullptr); + break; + } + } + } +} + +xbox_live_result +multiplayer_client_pending_reader::find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout + ) +{ + RETURN_CPP_IF(!m_autoFillMembers && m_gameClient->session() != nullptr, void, xbox_live_error_code::logic_error, "A game already exists. Call leave_game() before you can start matchmaking."); + RETURN_CPP_IF(!m_autoFillMembers && !m_lobbyClient->get_transfer_handle().empty(), void, xbox_live_error_code::logic_error, "A game already exists for your Lobby. Call leave_game() for all Lobby members before you can start matchmaking."); + + if (m_autoFillMembers && m_gameClient->session() != nullptr) + { + return m_matchClient->find_match(hopperName, attributes, timeout, m_gameClient->session(), true); + } + + return m_matchClient->find_match(hopperName, attributes, timeout, m_lobbyClient->session(), false); +} + +void +multiplayer_client_pending_reader::set_auto_fill_members_during_matchmaking( + _In_ bool autoFillMembers + ) +{ + m_autoFillMembers = autoFillMembers; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_client_pending_request.cpp b/Source/Services/Multiplayer/Manager/multiplayer_client_pending_request.cpp new file mode 100644 index 00000000..a0c9f133 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_client_pending_request.cpp @@ -0,0 +1,270 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +volatile long multiplayer_client_pending_request::s_uniqueIndentifier = 0; + +multiplayer_client_pending_request::multiplayer_client_pending_request() : + m_joinability(joinability::none), + m_requestType(pending_request_type::non_synchronized_changes), + m_localUserLobbyState(multiplayer_local_user_lobby_state::unknown) +{ + m_identifier = utils::interlocked_increment(s_uniqueIndentifier); +} + +pending_request_type +multiplayer_client_pending_request::request_type() const +{ + return m_requestType; +} + +context_t +multiplayer_client_pending_request::context() +{ + return m_context; +} + +uint32_t +multiplayer_client_pending_request::identifier() const +{ + return m_identifier; +} + +// Local User properties +std::shared_ptr +multiplayer_client_pending_request::local_user() +{ + return m_localUser; +} + +void +multiplayer_client_pending_request::set_local_user( + _In_ std::shared_ptr user + ) +{ + m_localUser = user; +} + +multiplayer_local_user_lobby_state +multiplayer_client_pending_request::lobby_state() +{ + return m_localUserLobbyState; +} + +void +multiplayer_client_pending_request::set_lobby_state( + _In_ multiplayer_local_user_lobby_state userState + ) +{ + m_localUserLobbyState = userState; +} + +const string_t& +multiplayer_client_pending_request::lobby_handle_id() const +{ + return m_lobbyHandleId; +} + +void +multiplayer_client_pending_request::set_lobby_handle_id(_In_ const string_t& handleId) +{ + m_lobbyHandleId = handleId; +} + +const multiplayer_session_reference& +multiplayer_client_pending_request::team_session_reference() const +{ + return m_teamSessionRef; +} + +void +multiplayer_client_pending_request::set_team_session_reference(_In_ const multiplayer_session_reference& sessionRef) +{ + m_teamSessionRef = sessionRef; +} + +const string_t& +multiplayer_client_pending_request::local_user_connection_address() const +{ + return m_localUserConnectionAddress; +} + +void +multiplayer_client_pending_request::set_local_user_connection_address( + _In_ std::shared_ptr localUser, + _In_ string_t connectionAddress, + _In_opt_ context_t context + ) +{ + m_context = context; + m_localUser = localUser; + + // convert the address into a base64 string as the service will reject it otherwise. + utf8string utf8String = utility::conversions::to_utf8string(connectionAddress); + std::vector input(utf8String.c_str(), utf8String.c_str() + utf8String.size()); + m_localUserConnectionAddress = utility::conversions::to_base64(input); +} + +const std::map& +multiplayer_client_pending_request::local_user_properties() const +{ + return m_localUserProperties; +} + +void +multiplayer_client_pending_request::set_local_user_properties( + _In_ std::shared_ptr localUser, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ) +{ + m_context = context; + m_localUser = localUser; + m_localUserProperties[name] = valueJson; +} + +// Session non-synchronized properties +multiplayer::manager::joinability +multiplayer_client_pending_request::joinability() +{ + return m_joinability; +} + +void multiplayer_client_pending_request::set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ) +{ + m_context = context; + m_joinability = value; +} + +const std::map& +multiplayer_client_pending_request::session_properties() const +{ + return m_sessionProperties; +} + +void +multiplayer_client_pending_request::set_session_properties( + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ) +{ + m_context = context; + m_sessionProperties[name] = valueJson; +} + +// Session synchronized properties +const string_t& +multiplayer_client_pending_request::synchronized_host_device_token() const +{ + return m_synchronizedHostDeviceToken; +} + +void +multiplayer_client_pending_request::set_synchronized_host_device_token( + _In_ const string_t& hostDeviceToken, + _In_opt_ context_t context + ) +{ + m_context = context; + m_requestType = pending_request_type::synchronized_changes; + m_synchronizedHostDeviceToken = hostDeviceToken; +} + +const std::map& +multiplayer_client_pending_request::synchronized_session_properties() const +{ + return m_synchronizedSessionProperties; +} + +void +multiplayer_client_pending_request::set_synchronized_session_properties( + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ) +{ + m_context = context; + m_requestType = pending_request_type::synchronized_changes; + m_synchronizedSessionProperties[name] = valueJson; +} + +void +multiplayer_client_pending_request::append_pending_changes( + _In_ std::shared_ptr sessionToCommit, + _In_ std::shared_ptr localUser, + _In_ bool isGameInProgress + ) +{ + // Apply local user properties + if (localUser != nullptr && m_localUser != nullptr && + utils::str_icmp(localUser->xbox_user_id(), m_localUser->xbox_user_id() ) == 0) + { + if (!m_localUserConnectionAddress.empty()) + { + // Assign connection address to the localUser instance as it's used in oher places locally. + localUser->set_connection_address(m_localUserConnectionAddress); + sessionToCommit->set_current_user_secure_device_address_base64(m_localUserConnectionAddress); + } + + if (m_localUserProperties.size() > 0) + { + for (const auto& prop : m_localUserProperties) + { + sessionToCommit->set_current_user_member_custom_property_json(prop.first, prop.second); + } + } + + localUser->set_write_changes_to_service(false); + } + + // Apply session non-sync properties + + if (m_joinability != joinability::none) + { + multiplayer_manager_utils::set_joinability(m_joinability, sessionToCommit, isGameInProgress); + } + + if (m_sessionProperties.size() > 0) + { + for (const auto& prop : m_sessionProperties) + { + sessionToCommit->set_session_custom_property_json(prop.first, prop.second); + } + } + + // Apply session sync properties + + if (!m_synchronizedHostDeviceToken.empty()) + { + sessionToCommit->set_host_device_token(m_synchronizedHostDeviceToken); + } + + if (m_synchronizedSessionProperties.size() > 0) + { + for (const auto& prop : m_synchronizedSessionProperties) + { + sessionToCommit->set_session_custom_property_json(prop.first, prop.second); + } + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_event.cpp b/Source/Services/Multiplayer/Manager/multiplayer_event.cpp new file mode 100644 index 00000000..a44c19dc --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_event.cpp @@ -0,0 +1,70 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_event::multiplayer_event( + _In_ std::error_code errorCode, + _In_ std::string errorMessage, + _In_ multiplayer_event_type eventType, + _In_ std::shared_ptr eventArgs, + _In_ multiplayer_session_type sessionType, + _In_opt_ context_t context + ): + m_errorCode(std::move(errorCode)), + m_errorMessage(std::move(errorMessage)), + m_eventType(eventType), + m_eventArgs(std::move(eventArgs)), + m_sessionType(sessionType), + m_pContext(context) +{ +} + +const std::error_code& +multiplayer_event::err() const +{ + return m_errorCode; +} + +const std::string& +multiplayer_event::err_message() const +{ + return m_errorMessage; +} + +context_t +multiplayer_event::context() +{ + return m_pContext; +} + +multiplayer_event_type +multiplayer_event::event_type() const +{ + return m_eventType; +} + +std::shared_ptr +multiplayer_event::event_args() +{ + return m_eventArgs; +} + +multiplayer_session_type +multiplayer_event::session_type() const +{ + return m_sessionType; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_game_client.cpp b/Source/Services/Multiplayer/Manager/multiplayer_game_client.cpp new file mode 100644 index 00000000..095966ab --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_game_client.cpp @@ -0,0 +1,784 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" +#include + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_game_client::multiplayer_game_client() : + m_updateNumber(0), + m_pendingCommitInProgress(false) +{ + m_sessionWriter = std::make_shared(); +} + +multiplayer_game_client::multiplayer_game_client( + _In_ std::shared_ptr localUserManager + ) : + m_multiplayerLocalUserManager(localUserManager), + m_updateNumber(0), + m_pendingCommitInProgress(false) +{ + m_sessionWriter = std::make_shared(m_multiplayerLocalUserManager); +} + +multiplayer_game_client::~multiplayer_game_client() +{ + m_sessionWriter.reset(); +} + +void +multiplayer_game_client::initialize() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_sessionWriter->add_multiplayer_session_updated_handler([thisWeakPtr](_In_ const std::shared_ptr& updatedSession) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->update_session(updatedSession); + } + }); +} + +std::shared_ptr +multiplayer_game_client::lobby_client() +{ + return multiplayer_manager::get_singleton_instance()->_Lobby_client(); +} + +std::shared_ptr +multiplayer_game_client::lobby_session() +{ + auto mpInstance = multiplayer_manager::get_singleton_instance(); + if (mpInstance->_Lobby_client() == nullptr) + { + return nullptr; + } + + return mpInstance->_Lobby_client()->session(); +} + +void +multiplayer_game_client::set_game_session_template( + _In_ const string_t& sessionTemplateName + ) +{ + m_gameSessionTemplateName = sessionTemplateName; +} + +void +multiplayer_game_client::deep_copy_if_updated( + _In_ const multiplayer_game_client& other + ) +{ + std::lock_guard lock(other.m_clientRequestLock); + + if (other.m_sessionWriter->session() == nullptr) + { + m_sessionWriter->update_session(nullptr); + m_multiplayerGame = nullptr; + } + else if (other.m_multiplayerGame == nullptr) + { + m_multiplayerGame = nullptr; + } + else if (m_sessionWriter->session() == nullptr || + other.m_sessionWriter->session()->change_number() > m_sessionWriter->session()->change_number() || + other.m_sessionWriter->session()->e_tag() > m_sessionWriter->session()->e_tag()) + { + m_sessionWriter->update_session(other.m_sessionWriter->session()->_Create_deep_copy()); + m_multiplayerGame = other.m_multiplayerGame->_Create_deep_copy(); + } + else if (m_updateNumber != other.m_updateNumber) + { + m_multiplayerGame = other.m_multiplayerGame->_Create_deep_copy(); + } +} + +const std::shared_ptr& +multiplayer_game_client::session_writer() const +{ + return m_sessionWriter; +} + +const std::shared_ptr& +multiplayer_game_client::game() const +{ + return m_multiplayerGame; +} + +void +multiplayer_game_client::update_game( + _In_ const std::shared_ptr& multiplayerGame + ) +{ + ++m_updateNumber; + m_multiplayerGame = multiplayerGame; +} + +const std::shared_ptr& +multiplayer_game_client::session() const +{ + std::lock_guard lock(m_clientRequestLock); + return m_sessionWriter->session(); +} + +void +multiplayer_game_client::update_session( + _In_ const std::shared_ptr& updatedSession + ) +{ + auto cachedSession = session(); + if (updatedSession == nullptr || cachedSession == nullptr || + updatedSession->change_number() > cachedSession->change_number() || + updatedSession->e_tag() != cachedSession->e_tag()) + { + update_game_session(updatedSession); + } +} + +void +multiplayer_game_client::update_game_session( + _In_ const std::shared_ptr& updatedSession + ) +{ + std::lock_guard lock(m_clientRequestLock); + m_sessionWriter->update_session(updatedSession); +} + +void +multiplayer_game_client::update_objects( + const std::shared_ptr& updatedSession, + const std::shared_ptr& lobbySession + ) +{ + std::lock_guard lock(m_clientRequestLock); + if (updatedSession == nullptr) + { + update_game(nullptr); + } + else + { + auto multiplayerGame = convert_to_multiplayer_game(updatedSession, lobbySession); + update_game(multiplayerGame); + } +} + +std::shared_ptr +multiplayer_game_client::convert_to_multiplayer_game( + _In_ const std::shared_ptr& sessionToConvert, + _In_ const std::shared_ptr& lobbySession + ) +{ + if (sessionToConvert == nullptr) + { + return nullptr; + } + + std::shared_ptr hostMember = nullptr; + std::vector> gameMembers; + for (const auto& member : sessionToConvert->members()) + { + auto gameMember = multiplayer_manager_utils::convert_to_game_member( + member, + lobbySession, + sessionToConvert, + m_multiplayerLocalUserManager->get_local_user_map() + ); + if (!member->device_token().empty() && + utils::str_icmp(member->device_token(), sessionToConvert->session_properties()->host_device_token()) == 0) + { + hostMember = gameMember; + } + + gameMembers.push_back(gameMember); + } + + return std::make_shared( + sessionToConvert, + hostMember, + gameMembers + ); +} + +const std::vector& +multiplayer_game_client::multiplayer_event_queue() +{ + // Don't require a lock as STL is multithread read safe + return m_multiplayerEventQueue; +} + +void +multiplayer_game_client::clear_pending_queue() +{ + std::lock_guard lock(m_clientRequestLock); + while (!m_pendingRequestQueue.empty()) + { + m_pendingRequestQueue.pop(); + } +} + +void +multiplayer_game_client::add_to_pending_queue( + _In_ std::shared_ptr pendingRequest + ) +{ + std::lock_guard lock(m_clientRequestLock); + m_pendingRequestQueue.push(pendingRequest); +} + +void +multiplayer_game_client::add_to_processing_queue( + _In_ std::vector> processingQueue + ) +{ + for (const auto& request : processingQueue) + { + m_processingQueue.push_back(request); + } +} + +void +multiplayer_game_client::remove_from_processing_queue( + _In_ uint32_t identifier +) +{ + for (auto request = m_processingQueue.begin(); request != m_processingQueue.end(); ++request) + { + if ((*request)->identifier() == identifier) + { + m_processingQueue.erase(request); + break; + } + } +} + +std::vector> +multiplayer_game_client::get_processing_queue() +{ + return m_processingQueue; +} + +std::vector +multiplayer_game_client::do_work() +{ + bool expected = false; + if (m_pendingCommitInProgress.compare_exchange_strong(expected, true)) + { + if (m_pendingRequestQueue.size() > 0) + { + std::vector> processingQueue; + bool applySynchronizedChanges = false; + bool doneProcessing = false; + do + { + std::lock_guard lock(m_clientRequestLock); + { + auto pendingRequest = m_pendingRequestQueue.front(); + processingQueue.push_back(pendingRequest); + m_pendingRequestQueue.pop(); + + if (m_pendingRequestQueue.size() > 0) + { + if (pendingRequest->request_type() != m_pendingRequestQueue.front()->request_type()) + { + doneProcessing = true; + } + } + + if (!applySynchronizedChanges && pendingRequest->request_type() == pending_request_type::synchronized_changes) + { + applySynchronizedChanges = true; + } + } + + } while (!doneProcessing && m_pendingRequestQueue.size() > 0); + + if (processingQueue.size() > 0) + { + add_to_processing_queue(processingQueue); + pplx::task>> asyncOp; + if (applySynchronizedChanges) + { + asyncOp = m_sessionWriter->commit_pending_synchronized_changes(processingQueue, multiplayer_session_type::game_session); + } + else + { + asyncOp = m_sessionWriter->commit_pending_changes(processingQueue, multiplayer_session_type::game_session); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + + create_task(asyncOp) + .then([thisWeakPtr, processingQueue](xbox_live_result> result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + std::lock_guard lock(pThis->m_clientRequestLock); + { + auto eventQueue = result.payload(); + for (const auto& ev : eventQueue) + { + pThis->m_multiplayerEventQueue.push_back(ev); + } + } + + for (const auto& processingRequest : processingQueue) + { + pThis->remove_from_processing_queue(processingRequest->identifier()); + } + + pThis->m_pendingCommitInProgress.store(false); + } + }); + } + else + { + m_pendingCommitInProgress.store(false); + } + } + else + { + m_pendingCommitInProgress.store(false); + } + } + + std::vector eventQueue; + { + std::lock_guard lock(m_clientRequestLock); + eventQueue = m_multiplayerEventQueue; + m_multiplayerEventQueue.clear(); + } + + return eventQueue; +} + +bool +multiplayer_game_client::is_pending_game_changes() +{ + std::lock_guard lock(m_clientRequestLock); + if (m_pendingRequestQueue.size() > 0) + { + return true; + } + + if (m_sessionWriter != nullptr) + { + auto latestSession = m_sessionWriter->session(); + if (latestSession != nullptr && + m_multiplayerGame != nullptr && + latestSession->change_number() != m_multiplayerGame->_Change_number()) + { + return true; + } + } + + return false; +} + +bool +multiplayer_game_client::is_request_in_progress() +{ + return m_pendingRequestQueue.size() > 0 || m_processingQueue.size() > 0 || m_multiplayerEventQueue.size() > 0; +} + +void +multiplayer_game_client::set_local_member_properties_to_remote_session( + _In_ const std::shared_ptr& localUser, + _In_ const std::map& localUserMap, + _In_ const string_t& localUserConnectionAddress + ) +{ + if (session() == nullptr || localUser == nullptr) + { + return; + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::create_task([thisWeakPtr, localUser, localUserMap, localUserConnectionAddress]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis == nullptr) return; + + bool expected = false; + while (!pThis->m_pendingCommitInProgress.compare_exchange_weak(expected, true)) + { + expected = false; + utils::sleep(0); + } + + auto gameSession = pThis->session(); + if (gameSession != nullptr) + { + auto sessionToCommit = std::make_shared(localUser->xbox_user_id(), gameSession->session_reference()); + sessionToCommit->join(web::json::value::null(), false, true, false); + for (const auto& prop : localUserMap) + { + sessionToCommit->set_current_user_member_custom_property_json(prop.first, prop.second); + } + + if (!localUserConnectionAddress.empty()) + { + sessionToCommit->set_current_user_secure_device_address_base64(localUserConnectionAddress); + } + + pThis->m_sessionWriter->write_session(localUser->context(), sessionToCommit, multiplayer_session_write_mode::update_existing).get(); + } + + pThis->m_pendingCommitInProgress = false; + }); +} + +void +multiplayer_game_client::remove_stale_users_from_remote_session() +{ + auto gameSession = session(); + if (gameSession == nullptr) return; + + auto xboxLiveContextMap = m_multiplayerLocalUserManager->get_local_user_map(); + for (auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr && localUser->lobby_state() == multiplayer_local_user_lobby_state::remove) + { + // Leave the game session if it exists. + if (gameSession != nullptr) + { + std::weak_ptr thisWeakPtr = shared_from_this(); + + auto sessionToCommit = std::make_shared(localUser->xbox_user_id(), gameSession->session_reference()); + sessionToCommit->leave(); + m_sessionWriter->write_session(localUser->context(), sessionToCommit, multiplayer_session_write_mode::update_existing) + .then([thisWeakPtr](xbox_live_result> result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr && pThis->lobby_client() != nullptr) + { + pThis->lobby_client()->stop_advertising_game_session(result); + } + }); + } + } + } +} + +pplx::task>> +multiplayer_game_client::join_game_for_all_local_members_helper( + _In_ const std::shared_ptr& session, + _In_ bool writeMemberPropertiesFromLobby, + _In_ const string_t& handleId + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = pplx::create_task([thisWeakPtr, session, writeMemberPropertiesFromLobby, handleId]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "multiplayer_game_client class was destroyed."); + + xbox_live_result> multiplayerSessionResult; + + auto xboxLiveContextMap = pThis->m_multiplayerLocalUserManager->get_local_user_map(); + for (auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr) + { + auto updatedSession = std::make_shared(localUser->xbox_user_id(), session->session_reference()); + auto joinSessionResult = pThis->join_helper(localUser, updatedSession, writeMemberPropertiesFromLobby, handleId).get(); + if (joinSessionResult.err()) + { + return joinSessionResult; + } + + localUser->set_game_state(multiplayer_local_user_game_state::in_session); + multiplayerSessionResult = joinSessionResult; + } + } + + return multiplayerSessionResult; + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task>> +multiplayer_game_client::join_helper( + _In_ std::shared_ptr localUser, + _In_ std::shared_ptr session, + _In_ bool writeMemberPropertiesFromLobby, + _In_ const string_t& handleId + ) +{ + RETURN_TASK_CPP_IF(localUser == nullptr || localUser->context() == nullptr, std::shared_ptr, "Call add_local_user() first."); + + session->join(web::json::value::null(), false, true, false); + session->set_current_user_secure_device_address_base64(localUser->connection_address()); + session->set_session_change_subscription(multiplayer_session_change_types::everything); + + if (writeMemberPropertiesFromLobby) + { + auto localMember = multiplayer_manager_utils::get_player_in_session(localUser->xbox_user_id(), lobby_session()); + if (localMember != nullptr && localMember->member_custom_properties_json().size() > 0) + { + auto jsonPropertyObj = localMember->member_custom_properties_json(); + for (const auto& prop : jsonPropertyObj.as_object()) + { + session->set_current_user_member_custom_property_json(prop.first, prop.second); + } + } + } + if (handleId.empty()) + { + return m_sessionWriter->write_session(localUser->context(), session, multiplayer_session_write_mode::update_or_create_new); + } + else + { + return m_sessionWriter->write_session_by_handle(localUser->context(), session, multiplayer_session_write_mode::update_or_create_new, handleId); + } +} + +xbox_live_result +multiplayer_game_client::join_game_helper( + _In_ const string_t& sessionName + ) +{ + multiplayer_session_reference gameSessionRef( + utils::try_get_override_scid(), + m_gameSessionTemplateName, + sessionName + ); + + auto joinResult = join_game_by_session_reference(gameSessionRef).get(); + if (!joinResult.err() && joinResult.payload() != nullptr && lobby_client() != nullptr) + { + // If jon_game succeeds, advertise game sessions via the lobby. If the advertising fails, + // we simply eat the error as it isn't actionable for the title. + + lobby_client()->advertise_game_session(); + } + + return xbox_live_result(joinResult.err(), joinResult.err_message()); +} + +pplx::task>> +multiplayer_game_client::join_game_by_session_reference( + _In_ const multiplayer_session_reference& gameSessionRef + ) +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + RETURN_TASK_CPP_IF(primaryContext == nullptr, std::shared_ptr, "Call add_local_user() before joining."); + + auto gameSession = std::make_shared( + primaryContext->xbox_live_user_id(), + gameSessionRef + ); + + return join_game_for_all_local_members(gameSession, string_t(), false); +} + +pplx::task>> +multiplayer_game_client::join_game_by_handle( + _In_ const string_t& handleId, + _In_ bool createGameIfFailedToJoin + ) +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + RETURN_TASK_CPP_IF(primaryContext == nullptr, std::shared_ptr, "Call add_local_user() before joining."); + + auto gameSession = std::make_shared(primaryContext->xbox_live_user_id()); + + return join_game_for_all_local_members(gameSession, handleId, createGameIfFailedToJoin); +} + +pplx::task>> +multiplayer_game_client::join_game_for_all_local_members( + _In_ const std::shared_ptr& gameSession, + _In_ const string_t& handleId, + _In_ bool createGameIfFailedToJoin + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(gameSession == nullptr || (gameSession->session_reference().session_name().empty() && handleId.empty()), std::shared_ptr, "Multiplayer session reference and handleId is empty."); + + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + RETURN_TASK_CPP_IF(primaryContext == nullptr, std::shared_ptr, "Call add_local_user() before joining."); + + // Leave existing game without updating the latest as the leave may comeback after the actual join and overwrite it. + auto cachedSession = session(); + if (cachedSession != nullptr) + { + leave_remote_session(cachedSession, false, false); + } + + update_session(nullptr); + std::weak_ptr thisWeakPtr = shared_from_this(); + + auto task = join_game_for_all_local_members_helper(gameSession, true, handleId) + .then([thisWeakPtr, handleId, createGameIfFailedToJoin](xbox_live_result> joinResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "multiplayer_game_client class was destroyed."); + + auto lobbyClient = pThis->lobby_client(); + if (lobbyClient != nullptr) + { + if (joinResult.err() == xbox_live_error_condition::http_404_not_found && !handleId.empty()) + { + if (createGameIfFailedToJoin) + { + lobbyClient->create_game_from_lobby(); + return xbox_live_result>(); + } + + // Tried to join by handleId and we failed. The handleId must be invalid. + lobbyClient->clear_game_session_from_lobby(); + } + else if (joinResult.err() && handleId.empty()) + { + // Tried to create a new game and we failed. Clear the transfer handle pending state (GameSessionTransferHandle=pending~xuid). + lobbyClient->clear_game_session_from_lobby(); + } + } + + if (!joinResult.err()) + { + pThis->update_session(joinResult.payload()); + pThis->m_multiplayerLocalUserManager->change_all_local_user_game_state(multiplayer_local_user_game_state::in_session); + } + + pThis->add_multiplayer_event_helper( + joinResult.err(), + joinResult.err_message(), + multiplayer_event_type::join_game_completed, + std::make_shared() + ); + return joinResult; + }); + + return utils::create_exception_free_task>( + task + ); +} + +xbox_live_result +multiplayer_game_client::join_game_from_lobby_helper() +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + auto lobbySession = lobby_session(); + auto lobbyClient = lobby_client(); + if( primaryContext == nullptr || lobbyClient == nullptr || lobbySession == nullptr) + { + return xbox_live_result(xbox_live_error_code::logic_error, "No lobby session exists. Call add_local_user() to create a lobby first."); + } + + // Check if the lobby has a game session associated with it to join. + auto lobbyProperties = lobbySession->session_properties()->session_custom_properties_json(); + if (!lobbyProperties.has_field(multiplayer_lobby_client::c_transferHandlePropertyName)) + { + return lobbyClient->create_game_from_lobby(); + } + + string_t handleId; + if (lobbyClient->is_transfer_handle_state(_T("pending"))) + { + // Wait for the property changed event to join. + m_multiplayerLocalUserManager->change_all_local_user_game_state(multiplayer_local_user_game_state::pending_join); + return xbox_live_result(); + } + else if (lobbyClient->is_transfer_handle_state(_T("completed"))) + { + handleId = lobbyClient->get_transfer_handle(); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::create_task([thisWeakPtr, handleId, primaryContext]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, void, xbox_live_error_code::generic_error, "multiplayer_game_client class was destroyed."); + + auto joinResult = pThis->join_game_by_handle(handleId, true).get(); + return xbox_live_result(joinResult.err(), joinResult.err_message()); + }); + + return xbox_live_result(); +} + +void +multiplayer_game_client::leave_remote_session( + _In_ std::shared_ptr session, + _In_ bool stopAdvertisingGameSession, + _In_ bool triggerCompletionEvent + ) +{ + auto processingRequest = std::make_shared(); + m_processingQueue.push_back(processingRequest); + + std::weak_ptr thisWeakPtr = shared_from_this(); + m_sessionWriter->leave_remote_session(session) + .then([thisWeakPtr, stopAdvertisingGameSession, triggerCompletionEvent, processingRequest](xbox_live_result> result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + if (stopAdvertisingGameSession && pThis->lobby_client() != nullptr) + { + pThis->lobby_client()->stop_advertising_game_session(result); + } + + // Always set your local game session to null upon leaving. + pThis->update_session(nullptr); + + if (triggerCompletionEvent) + { + pThis->add_multiplayer_event_helper( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::leave_game_completed, + std::make_shared() + ); + + pThis->remove_from_processing_queue(processingRequest->identifier()); + } + } + }); +} + +void +multiplayer_game_client::add_multiplayer_event_helper( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_event_type eventType, + _In_ std::shared_ptr eventArgs, + _In_opt_ context_t context + ) +{ + std::lock_guard lock(m_clientRequestLock); + + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + eventType, + eventArgs, + multiplayer_session_type::game_session, + context + ); + + m_multiplayerEventQueue.push_back(multiplayerEvent); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_game_session.cpp b/Source/Services/Multiplayer/Manager/multiplayer_game_session.cpp new file mode 100644 index 00000000..4105375f --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_game_session.cpp @@ -0,0 +1,180 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +std::shared_ptr multiplayer_game_session::_Create_deep_copy() +{ + auto copy = std::make_shared(); + copy->deep_copy_from(*this); + return copy; +} + +void multiplayer_game_session::deep_copy_from( + _In_ const multiplayer_game_session& other + ) +{ + m_sessionReference = other.m_sessionReference; + m_host = other.m_host; + m_correlationId = other.m_correlationId; + m_changeNumber = other.m_changeNumber; + m_members = other.m_members; + m_properties = other.m_properties; + m_sessionConstants = other.m_sessionConstants; + m_multiplayerClientManager = other.m_multiplayerClientManager; + m_teams = other.m_teams; + m_tournamentTeamResults = other.m_tournamentTeamResults; +} + +multiplayer_game_session::multiplayer_game_session(): + m_changeNumber(0) +{ +} + +multiplayer_game_session::multiplayer_game_session( + _In_ std::shared_ptr session, + _In_ std::shared_ptr host, + _In_ std::vector> members + ): + m_sessionReference(session->session_reference()), + m_host(std::move(host)), + m_correlationId(session->multiplayer_correlation_id()), + m_changeNumber(session->change_number()), + m_members(std::move(members)), + m_properties(session->session_properties()->session_custom_properties_json()), + m_sessionConstants(session->session_constants()), + m_teams(session->tournaments_server().teams()), + m_tournamentTeamResults(session->arbitration_server().results()) +{ +} + +const multiplayer_session_reference& +multiplayer_game_session::session_reference() const +{ + return m_sessionReference; +} + +const string_t& +multiplayer_game_session::correlation_id() const +{ + return m_correlationId; +} + +uint64_t +multiplayer_game_session::_Change_number() const +{ + return m_changeNumber; +} + +std::shared_ptr +multiplayer_game_session::host() const +{ + return m_host; +} + +void +multiplayer_game_session::_Set_host( + _In_ std::shared_ptr hostMember + ) +{ + m_host = hostMember; +} + +const std::vector>& +multiplayer_game_session::members() const +{ + return m_members; +} + +std::shared_ptr +multiplayer_game_session::session_constants() const +{ + return m_sessionConstants; +} + +const std::unordered_map& +multiplayer_game_session::tournament_teams() const +{ + return m_teams; +} + +const std::unordered_map& +multiplayer_game_session::tournament_team_results() const +{ + return m_tournamentTeamResults; +} + +const web::json::value& +multiplayer_game_session::properties() const +{ + return m_properties; +} + +xbox_live_result +multiplayer_game_session::set_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_properties(m_sessionReference, name, valueJson, context), void); +} + +bool +multiplayer_game_session::is_host( + _In_ const string_t& xboxUserId + ) +{ + if (m_host == nullptr || m_members.size() == 0) + { + return false; + } + + return utils::str_icmp(xboxUserId, m_host->xbox_user_id()) == 0; +} + +xbox_live_result +multiplayer_game_session::set_synchronized_host( + _In_ std::shared_ptr gameHost, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(gameHost == nullptr, void, xbox_live_error_code::invalid_argument, "GameHost was null."); + + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_synchronized_host(m_sessionReference, gameHost->_Device_token(), context), void); +} + +xbox_live_result +multiplayer_game_session::set_synchronized_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_synchronized_properties(m_sessionReference, name, valueJson, context), void); +} + +void +multiplayer_game_session::_Set_multiplayer_client_manager( + _In_ std::shared_ptr clientManager + ) +{ + m_multiplayerClientManager = clientManager; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_lobby_client.cpp b/Source/Services/Multiplayer/Manager/multiplayer_lobby_client.cpp new file mode 100644 index 00000000..69ef4035 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_lobby_client.cpp @@ -0,0 +1,1418 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN +const string_t multiplayer_lobby_client::c_transferHandlePropertyName = _T("GameSessionTransferHandle"); +const string_t multiplayer_lobby_client::c_joinabilityPropertyName = _T("Joinability"); + +multiplayer_lobby_client::multiplayer_lobby_client() : + m_pendingCommitInProgress(false), + m_updateNumber(0), + m_joinability(joinability::none) +{ + m_sessionWriter = std::make_shared(); +} + +multiplayer_lobby_client::multiplayer_lobby_client( + _In_ string_t lobbySessionTemplateName, + _In_ std::shared_ptr localUserManager + ) : + m_lobbySessionTemplateName(std::move(lobbySessionTemplateName)), + m_multiplayerLocalUserManager(localUserManager), + m_pendingCommitInProgress(false), + m_updateNumber(0), + m_joinability(joinability::none) +{ + m_sessionWriter = std::make_shared(localUserManager); +} + +multiplayer_lobby_client::~multiplayer_lobby_client() +{ + m_sessionWriter.reset(); +} + +void +multiplayer_lobby_client::initialize() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_sessionWriter->add_multiplayer_session_updated_handler([thisWeakPtr](_In_ const std::shared_ptr& updatedSession) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->update_session(updatedSession); + } + }); +} + +void multiplayer_lobby_client::deep_copy_if_updated( + _In_ const multiplayer_lobby_client& other + ) +{ + std::lock_guard lock(other.m_clientRequestLock); + + m_joinability = other.m_joinability; + if (other.m_sessionWriter->session() == nullptr) + { + m_sessionWriter->update_session(nullptr); + m_multiplayerLobby = nullptr; + } + else if (other.m_multiplayerLobby == nullptr) + { + m_multiplayerLobby = nullptr; + } + else if (m_sessionWriter->session() == nullptr || + other.m_sessionWriter->session()->change_number() > m_sessionWriter->session()->change_number() || + other.m_sessionWriter->session()->e_tag() > m_sessionWriter->session()->e_tag()) + { + m_sessionWriter->update_session(other.m_sessionWriter->session()->_Create_deep_copy()); + m_multiplayerLobby = other.m_multiplayerLobby->_Create_deep_copy(); + } + else if (m_updateNumber != other.m_updateNumber) + { + m_multiplayerLobby = other.m_multiplayerLobby->_Create_deep_copy(); + } +} + +std::shared_ptr +multiplayer_lobby_client::game_client() +{ + return multiplayer_manager::get_singleton_instance()->_Game_client(); +} + +std::shared_ptr +multiplayer_lobby_client::game_session() +{ + auto mpInstance = multiplayer_manager::get_singleton_instance(); + if (mpInstance->_Game_client() == nullptr) + { + return nullptr; + } + + return mpInstance->_Game_client()->session(); +} + +const std::shared_ptr& +multiplayer_lobby_client::session_writer() const +{ + return m_sessionWriter; +} + +const std::shared_ptr& +multiplayer_lobby_client::lobby() const +{ + return m_multiplayerLobby; +} + +void +multiplayer_lobby_client::update_lobby( + _In_ std::shared_ptr multiplayerLobby + ) +{ + ++m_updateNumber; + m_multiplayerLobby = multiplayerLobby; +} + +const std::shared_ptr& +multiplayer_lobby_client::session() const +{ + std::lock_guard lock(m_clientRequestLock); + return m_sessionWriter->session(); +} + +void +multiplayer_lobby_client::update_session( + _In_ const std::shared_ptr& updatedSession + ) +{ + auto cachedSession = session(); + if (updatedSession == nullptr || cachedSession == nullptr || + updatedSession->change_number() > cachedSession->change_number() || + updatedSession->e_tag() != cachedSession->e_tag()) + { + update_lobby_session(updatedSession); + } +} + +void +multiplayer_lobby_client::update_lobby_session( + _In_ const std::shared_ptr& updatedSession + ) +{ + std::lock_guard lock(m_clientRequestLock); + m_sessionWriter->update_session(updatedSession); +} + +void +multiplayer_lobby_client::update_objects( + const std::shared_ptr& updatedSession, + const std::shared_ptr& gameSession + ) +{ + std::lock_guard lock(m_clientRequestLock); + if (updatedSession == nullptr) + { + update_lobby(nullptr); + m_localLobbyMembers.clear(); + m_joinability = joinability::none; + } + else + { + update_local_lobby_members(updatedSession, gameSession); + auto multiplayerLobby = convert_to_multiplayer_lobby(updatedSession, gameSession); + update_lobby(multiplayerLobby); + m_joinability = multiplayer_manager_utils::get_joinability(updatedSession->session_properties()); + } +} + +void +multiplayer_lobby_client::update_local_lobby_members( + _In_ const std::shared_ptr& updatedLobbySession, + _In_ const std::shared_ptr& gameSession + ) +{ + m_localLobbyMembers.clear(); + if (updatedLobbySession == nullptr) + { + return; + } + + std::vector> localLobbyGameMembers = std::vector>(); + + auto xboxLiveContextMap = m_multiplayerLocalUserManager->get_local_user_map(); + for(auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr) + { + std::shared_ptr member = multiplayer_manager_utils::get_player_in_session(localUser->xbox_user_id(), updatedLobbySession); + if (member != nullptr) + { + auto localMember = multiplayer_manager_utils::convert_to_game_member(member, updatedLobbySession, gameSession, true); + localLobbyGameMembers.push_back(localMember); + } + } + } + + m_localLobbyMembers = localLobbyGameMembers; +} + +std::shared_ptr +multiplayer_lobby_client::convert_to_multiplayer_lobby( + _In_ const std::shared_ptr& sessionToConvert, + _In_ const std::shared_ptr& gameSession + ) +{ + if (sessionToConvert == nullptr) + { + return nullptr; + } + + std::shared_ptr hostMember = nullptr; + std::vector> gameMembers; + for (const auto& member : sessionToConvert->members()) + { + auto gameMember = multiplayer_manager_utils::convert_to_game_member( + member, + sessionToConvert, + gameSession, + m_multiplayerLocalUserManager->get_local_user_map() + ); + if (!member->device_token().empty() && + utils::str_icmp(member->device_token(), sessionToConvert->session_properties()->host_device_token()) == 0) + { + hostMember = gameMember; + } + + gameMembers.push_back(gameMember); + } + + return std::make_shared( + sessionToConvert, + hostMember, + gameMembers, + m_localLobbyMembers + ); +} + +multiplayer::manager::joinability +multiplayer_lobby_client::joinability() +{ + return m_joinability; +} + +const std::vector& +multiplayer_lobby_client::multiplayer_event_queue() +{ + // Don't require a lock as STL is multithread read safe + return m_multiplayerEventQueue; +} + +void +multiplayer_lobby_client::clear_pending_queue() +{ + std::lock_guard lock(m_clientRequestLock); + while (!m_pendingRequestQueue.empty()) + { + m_pendingRequestQueue.pop(); + } +} + +void +multiplayer_lobby_client::add_to_pending_queue( + _In_ std::shared_ptr pendingRequest + ) +{ + // No lock required. Methods that call this already has a lock + m_pendingRequestQueue.push(pendingRequest); +} + +void +multiplayer_lobby_client::add_to_processing_queue( + _In_ std::vector> processingQueue + ) +{ + for (const auto& request : processingQueue) + { + m_processingQueue.push_back(request); + } +} + +void +multiplayer_lobby_client::remove_from_processing_queue( + _In_ uint32_t identifier + ) +{ + for (auto request = m_processingQueue.begin(); request != m_processingQueue.end(); ++request) + { + if ((*request)->identifier() == identifier) + { + m_processingQueue.erase(request); + break; + } + } +} + +std::vector> +multiplayer_lobby_client::get_processing_queue() +{ + return m_processingQueue; +} + +xbox_live_result +multiplayer_lobby_client::add_local_user( + _In_ xbox_live_user_t user, + _In_ multiplayer_local_user_lobby_state userState, + _In_ const string_t& handleId, + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionRef + ) +{ + std::lock_guard lock(m_clientRequestLock); + + if (user == nullptr) return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid user argument passed"); + + auto localUser = m_multiplayerLocalUserManager->get_local_user_helper(user); + RETURN_CPP_IF(localUser != nullptr && userState == multiplayer_local_user_lobby_state::add, void, xbox_live_error_code::logic_error, "User already added."); + + if (localUser == nullptr) + { + localUser = m_multiplayerLocalUserManager->add_user_to_xbox_live_context_to_map(user); + } + + auto pendingRequest = std::make_shared(); + pendingRequest->set_local_user(localUser); + pendingRequest->set_lobby_state(userState); + if (userState == multiplayer_local_user_lobby_state::join) + { + if (!handleId.empty()) + { + pendingRequest->set_lobby_handle_id(handleId); + } + else if(!sessionRef.is_null()) + { + pendingRequest->set_team_session_reference(sessionRef); + } + } + add_to_pending_queue(pendingRequest); + + return xbox_live_result(); +} + +void +multiplayer_lobby_client::add_local_users( + _In_ std::vector users, + _In_ const string_t& handleId + ) +{ + for (const auto& user : users) + { + add_local_user(user, multiplayer_local_user_lobby_state::join, handleId); + } +} + +void +multiplayer_lobby_client::add_local_users( + _In_ std::vector users, + _In_ const multiplayer_session_reference& sessionRef + ) +{ + for (const auto& user : users) + { + add_local_user(user, multiplayer_local_user_lobby_state::join, string_t(), sessionRef); + } +} + +xbox_live_result +multiplayer_lobby_client::remove_local_user( + _In_ xbox_live_user_t user + ) +{ + std::lock_guard lock(m_clientRequestLock); + + if (user == nullptr) return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid user argument passed"); + + auto localUser = m_multiplayerLocalUserManager->get_local_user_helper(user); + RETURN_CPP_IF(localUser == nullptr || localUser->context() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() first."); + + auto pendingRequest = std::make_shared(); + pendingRequest->set_local_user(localUser); + pendingRequest->set_lobby_state(multiplayer_local_user_lobby_state::leave); + add_to_pending_queue(pendingRequest); + + return xbox_live_result(); +} + +void +multiplayer_lobby_client::remove_all_local_users() +{ + std::lock_guard lock(m_clientRequestLock); + + if (m_multiplayerLocalUserManager == nullptr) return; + + const auto& xboxLiveContextMap = m_multiplayerLocalUserManager->get_local_user_map(); + for (auto xboxLiveContext : xboxLiveContextMap) + { + const auto& localUser = xboxLiveContext.second; + if (localUser != nullptr) + { + auto pendingRequest = std::make_shared(); + pendingRequest->set_local_user(localUser); + pendingRequest->set_lobby_state(multiplayer_local_user_lobby_state::leave); + add_to_pending_queue(pendingRequest); + } + } +} + +xbox_live_result +multiplayer_lobby_client::set_local_member_properties( + _In_ xbox_live_user_t user, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ) +{ + std::lock_guard lock(m_clientRequestLock); + + if (user == nullptr) return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid user argument passed"); + + auto localUser = m_multiplayerLocalUserManager->get_local_user_helper(user); + RETURN_CPP_IF(localUser == nullptr || localUser->context() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() before setting local member properties."); + + auto pendingRequest = std::make_shared(); + pendingRequest->set_local_user_properties(localUser, name, valueJson, context); + add_to_pending_queue(pendingRequest); + + return xbox_live_result(); +} + +xbox_live_result +multiplayer_lobby_client::delete_local_member_properties( + _In_ xbox_live_user_t user, + _In_ const string_t& name, + _In_opt_ context_t context + ) +{ + std::lock_guard lock(m_clientRequestLock); + + if (user == nullptr) return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid user argument passed"); + + auto localUser = m_multiplayerLocalUserManager->get_local_user_helper(user); + RETURN_CPP_IF(localUser == nullptr || localUser->context() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() before deleting local member properties."); + + auto pendingRequest = std::make_shared(); + pendingRequest->set_local_user_properties(localUser, name, web::json::value::null(), context); + add_to_pending_queue(pendingRequest); + + return xbox_live_result(); +} + +xbox_live_result +multiplayer_lobby_client::set_local_member_connection_address( + _In_ xbox_live_user_t user, + _In_ string_t address, + _In_opt_ context_t context + ) +{ + std::lock_guard lock(m_clientRequestLock); + + if (user == nullptr) return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid user argument passed"); + + auto localUser = m_multiplayerLocalUserManager->get_local_user_helper(user); + RETURN_CPP_IF(localUser == nullptr || localUser->context() == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() before setting local member connection address."); + + auto pendingRequest = std::make_shared(); + pendingRequest->set_local_user_connection_address(localUser, address, context); + add_to_pending_queue(pendingRequest); + + return xbox_live_result(); +} + +xbox_live_result multiplayer_lobby_client::set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ) +{ + if (value < joinability::joinable_by_friends || value > joinability::closed) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Join restriction enum out of range"); + } + + auto pendingRequest = std::make_shared(); + pendingRequest->set_joinability(value, context); + add_to_pending_queue(pendingRequest); + + return xbox_live_result(); +} + +std::vector +multiplayer_lobby_client::do_work() +{ + bool expected = false; + if (m_pendingCommitInProgress.compare_exchange_strong(expected, true)) + { + if (m_pendingRequestQueue.size() > 0) + { + std::vector> processingQueue; + multiplayer_session_reference teamSessionRef; + bool applySynchronizedChanges = false; + bool joinByHandleId = false; + bool doneProcessing = false; + do + { + std::lock_guard lock(m_clientRequestLock); + { + auto pendingRequest = m_pendingRequestQueue.front(); + processingQueue.push_back(pendingRequest); + m_pendingRequestQueue.pop(); + + if (m_pendingRequestQueue.size() > 0) + { + if (pendingRequest->request_type() != m_pendingRequestQueue.front()->request_type()) + { + doneProcessing = true; + } + } + + if (!applySynchronizedChanges && pendingRequest->request_type() == pending_request_type::synchronized_changes) + { + applySynchronizedChanges = true; + } + + if (pendingRequest->local_user() != nullptr) + { + auto lobbyState = pendingRequest->lobby_state(); + if (lobbyState == multiplayer_local_user_lobby_state::join) + { + // Leave existing lobby without updating the latest as the leave may comeback after the actual join and overwrite it. + auto latestSession = m_sessionWriter->session(); + if (latestSession != nullptr) + { + leave_remote_session(latestSession); + } + + m_sessionWriter->update_session(nullptr); + update_lobby(nullptr); + m_localLobbyMembers.clear(); + m_joinability = joinability::none; + + if (!pendingRequest->lobby_handle_id().empty()) + { + pendingRequest->local_user()->set_lobby_handle_id(pendingRequest->lobby_handle_id()); + joinByHandleId = true; + } + else if (!pendingRequest->team_session_reference().is_null()) + { + teamSessionRef = pendingRequest->team_session_reference(); + } + } + + if (lobbyState != multiplayer_local_user_lobby_state::unknown) + { + pendingRequest->local_user()->set_lobby_state(lobbyState); + } + + pendingRequest->local_user()->set_write_changes_to_service(true); + } + } + + } while (!doneProcessing && m_pendingRequestQueue.size() > 0); + + if (processingQueue.size() > 0) + { + add_to_processing_queue(processingQueue); + pplx::task>> asyncOp; + if (applySynchronizedChanges) + { + asyncOp = m_sessionWriter->commit_pending_synchronized_changes(processingQueue, multiplayer_session_type::lobby_session); + } + else + { + asyncOp = commit_pending_lobby_changes(joinByHandleId, teamSessionRef); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + + create_task(asyncOp) + .then([thisWeakPtr, processingQueue](xbox_live_result> result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + std::lock_guard lock(pThis->m_clientRequestLock); + { + auto eventQueue = result.payload(); + for (const auto& ev : eventQueue) + { + pThis->m_multiplayerEventQueue.push_back(ev); + } + } + + for (const auto& processingRequest : processingQueue) + { + pThis->remove_from_processing_queue(processingRequest->identifier()); + } + + pThis->m_pendingCommitInProgress.store(false); + } + }); + } + else + { + m_pendingCommitInProgress.store(false); + } + } + else + { + m_pendingCommitInProgress.store(false); + } + } + + std::vector eventQueue; + { + std::lock_guard lock(m_clientRequestLock); + eventQueue = m_multiplayerEventQueue; + m_multiplayerEventQueue.clear(); + } + + return eventQueue; +} + +bool +multiplayer_lobby_client::is_pending_lobby_changes() +{ + std::lock_guard lock(m_clientRequestLock); + if (m_pendingRequestQueue.size() > 0 || is_pending_lobby_local_user_changes()) + { + return true; + } + + if (m_sessionWriter != nullptr) + { + auto latestSession = m_sessionWriter->session(); + if (latestSession != nullptr && + m_multiplayerLobby != nullptr && + latestSession->change_number() != m_multiplayerLobby->_Change_number()) + { + return true; + } + } + + return false; +} + +bool +multiplayer_lobby_client::is_request_in_progress() +{ + return m_pendingRequestQueue.size() > 0 || m_processingQueue.size() > 0 || m_multiplayerEventQueue.size() > 0; +} + +bool +multiplayer_lobby_client::is_pending_lobby_local_user_changes() +{ + const auto& xboxLiveContextMap = m_multiplayerLocalUserManager->get_local_user_map(); + for (auto xboxLiveContext : xboxLiveContextMap) + { + const auto& localUser = xboxLiveContext.second; + if (localUser != nullptr && localUser->write_changes_to_service()) + { + return true; + } + } + + return false; +} + +pplx::task>> +multiplayer_lobby_client::commit_pending_lobby_changes( + _In_ bool joinByHandleId, + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef + ) +{ + if (is_pending_lobby_local_user_changes()) + { + // All local member changes always happen on the lobby session. + std::shared_ptr latestLobbySession; + auto lobbySession = session(); + if (lobbySession == nullptr) + { + auto primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (joinByHandleId) + { + latestLobbySession = std::make_shared(primaryContext->xbox_live_user_id()); + } + else + { + if (sessionRef.is_null()) + { + string_t sessionName = utils::create_guid(true); + sessionRef = multiplayer_session_reference( + utils::try_get_override_scid(), + m_lobbySessionTemplateName, + sessionName + ); + } + + latestLobbySession = std::make_shared(primaryContext->xbox_live_user_id(), sessionRef); + } + } + else + { + latestLobbySession = lobbySession->_Create_deep_copy(); + } + + // Committing local user changes will also update any pending lobby properties. + return commit_lobby_changes(latestLobbySession); + } + + bool isGameInProgress = game_session() != nullptr; + return m_sessionWriter->commit_pending_changes(get_processing_queue(), multiplayer_session_type::lobby_session, isGameInProgress); +} + +pplx::task>> +multiplayer_lobby_client::commit_lobby_changes( + _In_ std::shared_ptr lobbySessionToCommit + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = pplx::create_task([thisWeakPtr, lobbySessionToCommit]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::vector, xbox_live_error_code::generic_error, "multiplayer_lobby_client class was destroyed."); + + return pThis->commit_lobby_changes_helper(lobbySessionToCommit); + }); + + return utils::create_exception_free_task>(task); +} + +xbox_live_result> +multiplayer_lobby_client::commit_lobby_changes_helper( + _In_ std::shared_ptr lobbySession + ) +{ + auto sessionRefToCommit = lobbySession->session_reference(); + + uint32_t count = 0; + bool removeStaleUsers = false; + auto xboxLiveContextMap = m_multiplayerLocalUserManager->get_local_user_map(); + for(auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr && localUser->write_changes_to_service()) + { + auto lobbySessionToCommit = std::make_shared(localUser->xbox_user_id(), sessionRefToCommit); + switch (localUser->lobby_state()) + { + case multiplayer_local_user_lobby_state::add: + { + lobbySessionToCommit->join(); + lobbySessionToCommit->set_current_user_secure_device_address_base64(localUser->connection_address()); + lobbySessionToCommit->set_session_change_subscription(multiplayer_session_change_types::everything); + + // Only set this for the first user. Could cause a race condition if joinability was changed during the second write. + if (count == 0) + { + count++; + lobbySessionToCommit->session_properties()->set_join_restriction(multiplayer_session_restriction::followed); + lobbySessionToCommit->session_properties()->set_read_restriction(multiplayer_session_restriction::followed); + + string_t jsonValueStr = multiplayer_manager_utils::convert_joinability_to_string(joinability::joinable_by_friends); + lobbySessionToCommit->set_session_custom_property_json(c_joinabilityPropertyName, web::json::value::string(jsonValueStr)); + break; + } + } + + case multiplayer_local_user_lobby_state::join: + { + lobbySessionToCommit->join(); + + lobbySessionToCommit->set_current_user_secure_device_address_base64(localUser->connection_address()); + lobbySessionToCommit->set_session_change_subscription(multiplayer_session_change_types::everything); + break; + } + + case multiplayer_local_user_lobby_state::in_session: + { + // Forces to set the current user to yourself. + lobbySessionToCommit->join(); + break; + } + case multiplayer_local_user_lobby_state::leave: + { + if(multiplayer_manager_utils::is_player_in_session(localUser->xbox_user_id(), lobbySession)) + { + lobbySessionToCommit->leave(); + } + else + { + // In a scenario where the user was removed before he could have been added. + user_state_changed(xbox_live_error_code::logic_error, "User was removed before he could be added", multiplayer_local_user_lobby_state::add, localUser->xbox_user_id()); + user_state_changed(xbox_live_error_code::no_error, std::string(), multiplayer_local_user_lobby_state::leave, localUser->xbox_user_id()); + + removeStaleUsers = true; + localUser->set_lobby_state(multiplayer_local_user_lobby_state::remove); + continue; + } + break; + } + + default: + break; + } + + bool isGameInProgress = game_session() != nullptr; + + // Update any pending local user or lobby session properties. + auto processingQueue = get_processing_queue(); + for(auto& request : processingQueue) + { + request->append_pending_changes(lobbySessionToCommit, localUser, isGameInProgress); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::task>> writeSessionOp; + + if (localUser->lobby_handle_id().empty()) + { + writeSessionOp = m_sessionWriter->write_session(localUser->context(), lobbySessionToCommit, multiplayer_session_write_mode::update_or_create_new); + } + else + { + writeSessionOp = m_sessionWriter->write_session_by_handle(localUser->context(), lobbySessionToCommit, multiplayer_session_write_mode::update_or_create_new, localUser->lobby_handle_id()); + localUser->set_lobby_handle_id(string_t()); + } + + auto writeSessionTask = pplx::create_task(writeSessionOp) + .then([thisWeakPtr, localUser, sessionRefToCommit, processingQueue, &removeStaleUsers](xbox_live_result> sessionResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::vector, xbox_live_error_code::generic_error, "multiplayer_lobby_client class was destroyed."); + + pThis->user_state_changed(sessionResult.err(), sessionResult.err_message(), localUser->lobby_state(), localUser->xbox_user_id()); + pThis->handle_lobby_change_events(sessionResult.err(), sessionResult.err_message(), localUser, processingQueue); + + if (sessionResult.err()) + { + pThis->join_lobby_completed(sessionResult.err(), sessionResult.err_message(), string_t()); + return xbox_live_result>(sessionResult.err(), sessionResult.err_message()); + } + + if (localUser->lobby_state() == multiplayer_local_user_lobby_state::add || + localUser->lobby_state() == multiplayer_local_user_lobby_state::join) + { + auto updatedSession = sessionResult.payload(); + pThis->update_session(updatedSession); + auto lobbyState = localUser->lobby_state(); + localUser->set_lobby_state(multiplayer_local_user_lobby_state::in_session); + + if (lobbyState == multiplayer_local_user_lobby_state::join) + { + pThis->handle_join_lobby_completed(sessionResult.err(), sessionResult.err_message()); + } + + auto setActivityResult = localUser->context()->multiplayer_service().set_activity(updatedSession->session_reference()).get(); + if (setActivityResult.err()) + { + return xbox_live_result>(setActivityResult.err(), setActivityResult.err_message()); + } + + if (lobbyState == multiplayer_local_user_lobby_state::add && + pThis->should_update_host_token(localUser, updatedSession)) + { + updatedSession->set_host_device_token(updatedSession->current_user()->device_token()); + auto writeHostTokenResult = pThis->m_sessionWriter->write_session(localUser->context(), updatedSession, multiplayer_session_write_mode::update_existing).get(); + if (writeHostTokenResult.err()) + { + return xbox_live_result>(writeHostTokenResult.err(), writeHostTokenResult.err_message()); + } + } + } + else if (localUser->lobby_state() == multiplayer_local_user_lobby_state::leave) + { + removeStaleUsers = true; + + // If you leave the session you were advertising, you don't need to clear the activity. + localUser->set_lobby_state(multiplayer_local_user_lobby_state::remove); + } + + return xbox_live_result>(); + + }).get(); // write_session + + if (writeSessionTask.err()) + { + return xbox_live_result>(writeSessionTask.err(), writeSessionTask.err_message()); + } + } // end if + } // end for + + if (removeStaleUsers) + { + remove_stale_xbox_live_context_from_map(); + } + + return xbox_live_result>(); +} + +void +multiplayer_lobby_client::remove_stale_xbox_live_context_from_map() +{ + auto gameClient = game_client(); + if (gameClient != nullptr) + { + gameClient->remove_stale_users_from_remote_session(); + } + + // Remove stale context, switch primary context and re-activate multiplayer events. + m_multiplayerLocalUserManager->remove_stale_local_users_from_map(); +} + +std::map> +multiplayer_lobby_client::get_local_user_map() +{ + return m_multiplayerLocalUserManager->get_local_user_map(); +} + +std::shared_ptr +multiplayer_lobby_client::get_primary_context() +{ + return m_multiplayerLocalUserManager->get_primary_context(); +} + +xbox_live_result +multiplayer_lobby_client::create_game_from_lobby() +{ + auto lobbySession = session(); + RETURN_CPP_IF(lobbySession == nullptr, void, xbox_live_error_code::logic_error, "No lobby session exists. Call add_local_user() to create a lobby first"); + + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + RETURN_CPP_IF(primaryContext == nullptr, void, xbox_live_error_code::logic_error, "Call add_local_user() before joining."); + + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::create_task([thisWeakPtr, lobbySession, primaryContext]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, void, xbox_live_error_code::generic_error, "multiplayer_lobby_client class was destroyed."); + + // Try to write transfer handle to the lobby as pending state + // If succeeded, then create the game session, set the transfer handle, and advertise the game session. + // If failed, wait for the property changed event. + + auto sessionToCommitCopy = lobbySession->_Create_deep_copy(); + + string_t jsonValue; + jsonValue = _T("pending~") + primaryContext->xbox_live_user_id(); + sessionToCommitCopy->set_session_custom_property_json(multiplayer_lobby_client::c_transferHandlePropertyName, web::json::value::string(jsonValue)); + + auto commitResult = pThis->m_sessionWriter->commit_synchronized_changes(sessionToCommitCopy).get(); + auto gameClient = pThis->game_client(); + RETURN_CPP_IF(gameClient == nullptr, void, xbox_live_error_code::generic_error, "multiplayer_game_client class was destroyed."); + + if (commitResult.err() == xbox_live_error_condition::http_412_precondition_failed) + { + if (pThis->is_transfer_handle_state(_T("completed")) || pThis->is_transfer_handle_state(_T("pending"))) + { + return gameClient->join_game_from_lobby_helper(); + } + } + + auto sessionName = utils::create_guid(true); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(gameClient->join_game_helper(sessionName), void); + }); + + return xbox_live_result(); +} + +void +multiplayer_lobby_client::advertise_game_session() +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr || game_session() == nullptr) + { + return; + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::create_task([thisWeakPtr, primaryContext]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis == nullptr) return; + + bool expected = false; + while (!pThis->m_pendingCommitInProgress.compare_exchange_strong(expected, true)) + { + expected = false; + utils::sleep(0); + } + + auto lobbySession = pThis->session(); + if (pThis->game_session() == nullptr) return; + + // If the advertising fails, we simply eat the error as it isn't actionable for the title. + if (lobbySession == nullptr) + { + if (pThis->m_multiplayerLocalUserManager->get_local_user_map().size() == 0) + { + return; + } + + pThis->m_multiplayerLocalUserManager->change_all_local_user_lobby_state(multiplayer_local_user_lobby_state::add); + auto joinLobbyResult = pThis->commit_pending_lobby_changes(false).get(); + + pThis->m_pendingCommitInProgress = false; + pThis->join_lobby_completed(joinLobbyResult.err(), joinLobbyResult.err_message(), string_t()); + if (joinLobbyResult.err()) + { + return; + } + + lobbySession = pThis->session(); + } + else + { + pThis->m_pendingCommitInProgress = false; + } + + auto lobbyProperties = lobbySession->session_properties()->session_custom_properties_json(); + if (!lobbyProperties.has_field(c_transferHandlePropertyName) || + (pThis->is_transfer_handle_state(_T("pending")) && pThis->get_transfer_handle() == primaryContext->xbox_live_user_id())) + { + auto gameSession = pThis->game_session(); + if (gameSession == nullptr) return; + + auto result = primaryContext->multiplayer_service().set_transfer_handle(gameSession->session_reference(), lobbySession->session_reference()).get(); + if (!result.err()) + { + auto handleId = result.payload(); + auto lobbySessionCopy = lobbySession->_Create_deep_copy(); + + if (pThis->m_joinability == joinability::disable_while_game_in_progress) + { + lobbySessionCopy->set_closed(true); + } + + stringstream_t jsonHandleValue; + jsonHandleValue << "completed~"; + jsonHandleValue << handleId; + lobbySessionCopy->set_session_custom_property_json(c_transferHandlePropertyName, web::json::value::string(jsonHandleValue.str())); + pThis->m_sessionWriter->write_session(primaryContext, lobbySessionCopy, multiplayer_session_write_mode::update_existing); + } + else if (result.err() == xbox_live_error_code::http_status_403_forbidden) + { + // By MPSD design, if the game session doesn't exist on transfer handle creation, it throws a 403. + pThis->clear_game_session_from_lobby(); + } + } + }); +} + +void +multiplayer_lobby_client::stop_advertising_game_session( + _In_ xbox_live_result> result + ) +{ + bool bClearGameSession = false; + auto lobbySession = session(); + if (!result.err() && result.payload() == nullptr) + { + // When you are the last person to leave the session (handling err 204). + bClearGameSession = true; + } + else if (result.payload() != nullptr && lobbySession != nullptr) + { + auto latestGameSession = result.payload(); + + bool found = false; + auto members = lobbySession->members(); + for (const auto& member : members) + { + if (multiplayer_manager_utils::is_player_in_session(member->xbox_user_id(), latestGameSession)) + { + found = true; + break; + } + } + + if (!found && members.size() > 0) + { + bClearGameSession = true; + } + } + + if (bClearGameSession) + { + clear_game_session_from_lobby(); + } +} + +void +multiplayer_lobby_client::clear_game_session_from_lobby() +{ + auto lobbySession = session(); + if (lobbySession != nullptr) + { + auto lobbySessionCopy = lobbySession->_Create_deep_copy(); + + if (m_joinability == joinability::disable_while_game_in_progress) + { + // Re-open the lobby to be joinable when leaving the game session. + lobbySessionCopy->set_closed(false); + } + + lobbySessionCopy->delete_session_custom_property_json(c_transferHandlePropertyName); + m_sessionWriter->write_session(m_multiplayerLocalUserManager->get_primary_context(), lobbySessionCopy, multiplayer_session_write_mode::update_existing); + } +} + +bool +multiplayer_lobby_client::is_transfer_handle_state( + _In_ const string_t& state + ) +{ + auto lobbySession = session(); + if (lobbySession == nullptr) + { + return false; + } + + auto lobbyProperties = lobbySession->session_properties()->session_custom_properties_json(); + if (lobbyProperties.has_field(c_transferHandlePropertyName)) + { + auto transferHandleProp = lobbyProperties.at(c_transferHandlePropertyName).as_string(); + std::vector transferHandleSplit = utils::string_split(transferHandleProp, '~'); + + if (transferHandleSplit.size() > 0 && + utils::str_icmp(transferHandleSplit[0], state) == 0) + { + return true; + } + } + + return false; +} + +string_t +multiplayer_lobby_client::get_transfer_handle() +{ + auto lobbySession = session(); + if (lobbySession == nullptr) + { + return string_t(); + } + + auto lobbyProperties = lobbySession->session_properties()->session_custom_properties_json(); + if (lobbyProperties.has_field(c_transferHandlePropertyName)) + { + auto transferHandleProp = lobbyProperties.at(c_transferHandlePropertyName).as_string(); + std::vector transferHandleSplit = utils::string_split(transferHandleProp, '~'); + + if (transferHandleSplit.size() == 2) + { + return transferHandleSplit[1]; + } + } + + return string_t(); +} +void +multiplayer_lobby_client::leave_remote_session( + _In_ std::shared_ptr session + ) +{ + m_sessionWriter->leave_remote_session(session); +} + +bool +multiplayer_lobby_client::should_update_host_token( + _In_ std::shared_ptr localUser, + _In_ std::shared_ptr session + ) +{ + if(multiplayer_manager_utils::host_member(session) != nullptr) + { + return false; + } + + if(!localUser->is_primary_xbox_live_context()) + { + return false; + } + + // If the local user is already the host, skip it. + if (multiplayer_manager_utils::is_host(localUser->xbox_user_id(), session)) + { + return false; + } + + return true; +} + +void +multiplayer_lobby_client::user_state_changed( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_local_user_lobby_state localUserLobbyState, + _In_ string_t xboxUserId + ) +{ + if (localUserLobbyState != multiplayer_local_user_lobby_state::add && + localUserLobbyState != multiplayer_local_user_lobby_state::leave) + { + return; + } + + std::shared_ptr eventArgs; + multiplayer_event_type eventType = multiplayer_event_type::user_added; + if (localUserLobbyState == multiplayer_local_user_lobby_state::add) + { + eventType = multiplayer_event_type::user_added; + std::shared_ptr userAddedEventArgs = std::make_shared(xboxUserId); + eventArgs = std::dynamic_pointer_cast(userAddedEventArgs); + } + else if (localUserLobbyState == multiplayer_local_user_lobby_state::leave) + { + eventType = multiplayer_event_type::user_removed; + std::shared_ptr userRemovedEventArgs = std::make_shared(xboxUserId); + eventArgs = std::dynamic_pointer_cast(userRemovedEventArgs); + } + else + { + // We only care about user_added & user_removed. + return; + } + + add_multiplayer_event_helper(errorCode, errorMessage, eventType, eventArgs); +} + +void +multiplayer_lobby_client::handle_lobby_change_events( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ std::shared_ptr localUser, + _In_ const std::vector>& processingQueue + ) +{ + std::map localUserMap; + string_t localUserConnectionAddress; + for (auto& request : processingQueue) + { + // Handle local user change events + if (localUser != nullptr && request->local_user() != nullptr && + utils::str_icmp(localUser->xbox_user_id(), request->local_user()->xbox_user_id()) == 0) + { + if (!request->local_user_connection_address().empty()) + { + add_multiplayer_event_helper( + errorCode, + errorMessage, + multiplayer_event_type::local_member_connection_address_write_completed, + std::make_shared(), + request->context() + ); + + localUserConnectionAddress = request->local_user_connection_address(); + } + + // Fire events for each of the properties + for (const auto& prop : request->local_user_properties()) + { + add_multiplayer_event_helper( + errorCode, + errorMessage, + multiplayer_event_type::local_member_property_write_completed, + std::make_shared(), + request->context() + ); + + localUserMap[prop.first] = prop.second; + } + } + } + + // Handle lobby change events (session properties, etc) + auto eventQueue = m_sessionWriter->handle_events(processingQueue, errorCode, errorMessage, multiplayer_session_type::lobby_session); + if (eventQueue.size() > 0) + { + std::lock_guard lock(m_clientRequestLock); + for (auto& ev : eventQueue) + { + m_multiplayerEventQueue.push_back(ev); + } + } + + if (localUserMap.size() != 0 || !localUserConnectionAddress.empty()) + { + // write member properties to the game session. + auto gameClient = game_client(); + if (gameClient != nullptr) + { + gameClient->set_local_member_properties_to_remote_session(localUser, localUserMap, localUserConnectionAddress); + } + } +} + +void +multiplayer_lobby_client::handle_join_lobby_completed( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage + ) +{ + join_lobby_completed(errorCode, errorMessage, string_t()); + if (!errorCode) + { + // If joining the lobby succeeded, check if it has a game session associated with it to join. + + auto gameClient = game_client(); + if (gameClient == nullptr) return; + + auto lobbySession = session(); + + // If its a team session and it already has a GameSession ready to join + if (lobbySession->session_constants()->capabilities_team() && + !lobbySession->tournaments_server().next_game_session_reference().is_null()) + { + handle_game_session_ready_event(lobbySession); + return; + } + + // Join game via the transfer handle. + auto lobbyProperties = lobbySession->session_properties()->session_custom_properties_json(); + if (lobbyProperties.size() > 0) + { + string_t transferHandle; + + if (is_transfer_handle_state(_T("completed"))) + { + transferHandle = get_transfer_handle(); + } + else + { + // No existing game session + return; + } + + gameClient->join_game_by_handle(transferHandle, false); + } + } +} + +void +multiplayer_lobby_client::join_lobby_completed( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ const string_t& invitedXboxUserId + ) +{ + std::shared_ptr joinLobbyEventArgs = std::make_shared( + invitedXboxUserId + ); + + add_multiplayer_event_helper( + errorCode, + errorMessage, + multiplayer_event_type::join_lobby_completed, + std::dynamic_pointer_cast(joinLobbyEventArgs) + ); +} + +void +multiplayer_lobby_client::handle_game_session_ready_event( + _In_ const std::shared_ptr& lobbySession + ) +{ + auto lobbyTournamentsServer = lobbySession->tournaments_server(); + auto localStartTime = utility::datetime::utc_now() + utility::datetime::from_seconds(lobbyTournamentsServer.next_game_start_time() - lobbySession->date_of_session()); + auto gameSessionReadyEventArgs = std::make_shared( + localStartTime + ); + + add_multiplayer_event_helper( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::tournament_game_session_ready, + gameSessionReadyEventArgs + ); + + auto gameClient = game_client(); + if (gameClient != nullptr) + { + gameClient->join_game_by_session_reference(lobbyTournamentsServer.next_game_session_reference()); + } +} + +void +multiplayer_lobby_client::add_multiplayer_event_helper( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_event_type eventType, + _In_ std::shared_ptr eventArgs, + _In_opt_ context_t context + ) +{ + std::lock_guard lock(m_clientRequestLock); + + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + eventType, + eventArgs, + multiplayer_session_type::lobby_session, + context + ); + + m_multiplayerEventQueue.push_back(multiplayerEvent); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_lobby_session.cpp b/Source/Services/Multiplayer/Manager/multiplayer_lobby_session.cpp new file mode 100644 index 00000000..330fe819 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_lobby_session.cpp @@ -0,0 +1,276 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_lobby_session::multiplayer_lobby_session( + _In_ std::shared_ptr multiplayerClientManagerInstance + ): + m_multiplayerClientManager(std::move(multiplayerClientManagerInstance)), + m_changeNumber(0) +{ +} + +multiplayer_lobby_session::multiplayer_lobby_session(): + m_changeNumber(0) +{ +} + +multiplayer_lobby_session::multiplayer_lobby_session( + _In_ std::shared_ptr session, + _In_ std::shared_ptr host, + _In_ std::vector> members, + _In_ std::vector> localMembers + ) : + m_sessionReference(session->session_reference()), + m_host(std::move(host)), + m_correlationId(session->multiplayer_correlation_id()), + m_changeNumber(session->change_number()), + m_members(std::move(members)), + m_localMembers(std::move(localMembers)), + m_properties(session->session_properties()->session_custom_properties_json()), + m_sessionConstants(session->session_constants()), + m_lastTournamentTeamResult(session->tournaments_server().last_team_result()) +{ +} + +std::shared_ptr multiplayer_lobby_session::_Create_deep_copy() +{ + auto copy = std::make_shared(); + copy->deep_copy_from(*this); + return copy; +} + +void multiplayer_lobby_session::deep_copy_from( + _In_ const multiplayer_lobby_session& other + ) +{ + m_sessionReference = other.m_sessionReference; + m_host = other.m_host; + m_correlationId = other.m_correlationId; + m_changeNumber = other.m_changeNumber; + m_members = other.m_members; + m_localMembers = other.m_localMembers; + m_properties = other.m_properties; + m_sessionConstants = other.m_sessionConstants; + m_lastTournamentTeamResult = other.m_lastTournamentTeamResult; + m_multiplayerClientManager = other.m_multiplayerClientManager; +} + +xbox_live_result +multiplayer_lobby_session::add_local_user( + _In_ xbox_live_user_t user + ) +{ + if (m_multiplayerClientManager->latest_pending_read() == nullptr) + { + m_multiplayerClientManager->initialize(); + } + + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->lobby_client()->add_local_user( + user, + multiplayer_local_user_lobby_state::add + ), void); +} + +xbox_live_result +multiplayer_lobby_session::remove_local_user( + _In_ xbox_live_user_t user + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->lobby_client()->remove_local_user(user), void); +} + +xbox_live_result +multiplayer_lobby_session::set_local_member_properties( + _In_ xbox_live_user_t user, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->lobby_client()->set_local_member_properties(user, std::move(name), std::move(valueJson), context), void); +} + +xbox_live_result +multiplayer_lobby_session::delete_local_member_properties( + _In_ xbox_live_user_t user, + _In_ const string_t& name, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->lobby_client()->delete_local_member_properties(user, name, context), void); +} + +xbox_live_result +multiplayer_lobby_session::set_local_member_connection_address( + _In_ xbox_live_user_t user, + _In_ const string_t& connectionAddress, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->lobby_client()->set_local_member_connection_address(user, connectionAddress, context), void); +} + +const multiplayer_session_reference& +multiplayer_lobby_session::session_reference() const +{ + return m_sessionReference; +} + +const string_t& +multiplayer_lobby_session::correlation_id() const +{ + return m_correlationId; +} + +uint64_t +multiplayer_lobby_session::_Change_number() const +{ + return m_changeNumber; +} + +std::shared_ptr +multiplayer_lobby_session::host() const +{ + return m_host; +} + +void +multiplayer_lobby_session::_Set_host( + _In_ std::shared_ptr hostMember + ) +{ + m_host = hostMember; +} + +const std::vector>& +multiplayer_lobby_session::members() const +{ + return m_members; +} + +std::shared_ptr +multiplayer_lobby_session::session_constants() const +{ + return m_sessionConstants; +} + +const tournament_team_result& +multiplayer_lobby_session::last_tournament_team_result() const +{ + return m_lastTournamentTeamResult; +} + +const std::vector>& +multiplayer_lobby_session::local_members() const +{ + return m_localMembers; +} + +const web::json::value& +multiplayer_lobby_session::properties() const +{ + return m_properties; +} + +xbox_live_result +multiplayer_lobby_session::set_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_properties(m_sessionReference, name, valueJson, context), void); +} + +bool +multiplayer_lobby_session::is_host( + _In_ const string_t& xboxUserId + ) +{ + if (m_host == nullptr || m_members.size() == 0) + { + return false; + } + + return utils::str_icmp(xboxUserId, m_host->xbox_user_id()) == 0; +} + +xbox_live_result +multiplayer_lobby_session::set_synchronized_host( + _In_ std::shared_ptr gameHost, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(gameHost == nullptr, void, xbox_live_error_code::invalid_argument, "GameHost was null."); + + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_synchronized_host(m_sessionReference, gameHost->_Device_token(), context), void); +} + +xbox_live_result +multiplayer_lobby_session::set_synchronized_properties( + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_synchronized_properties(m_sessionReference, name, valueJson, context), void); +} + +void +multiplayer_lobby_session::_Set_multiplayer_client_manager( + _In_ std::shared_ptr clientManager + ) +{ + m_multiplayerClientManager = clientManager; +} + +#if !XSAPI_U +xbox_live_result +multiplayer_lobby_session::invite_friends( + _In_ xbox_live_user_t user, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->invite_friends(user, contextStringId, customActivationContext), void); +} +#endif + +xbox_live_result +multiplayer_lobby_session::invite_users( + _In_ xbox_live_user_t user, + _In_ const std::vector& xboxUserIds, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager->latest_pending_read() == nullptr, void, xbox_live_error_code::logic_error, "No user added. Call add_local_user() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->invite_users(user, xboxUserIds, contextStringId, customActivationContext), void); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_local_user.cpp b/Source/Services/Multiplayer/Manager/multiplayer_local_user.cpp new file mode 100644 index 00000000..8c1c0bb5 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_local_user.cpp @@ -0,0 +1,199 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/services.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_local_user::multiplayer_local_user( + _In_ xbox_live_user_t user, + _In_ string_t xboxUserId, + _In_ bool isPrimary + ) : + m_xboxLiveContextImpl(std::make_shared(user)), + m_xboxUserId(std::move(xboxUserId)), + m_isPrimaryXboxLiveContext(isPrimary), + m_writeChangesToService(false), + m_writeConnectionAddress(false), + m_lobbyState(multiplayer_local_user_lobby_state::unknown), + m_gameState(multiplayer_local_user_game_state::unknown), + m_rtaStateChangedContext(0), + m_sessionChangedContext(0), + m_subscriptionLostContext(0), + m_rtaResyncContext(0) +{ + m_xboxLiveContextImpl->user_context()->set_caller_context_type(caller_context_type::multiplayer_manager); + m_xboxLiveContextImpl->init(); +} + +multiplayer_local_user::~multiplayer_local_user() +{ + m_xboxLiveContextImpl.reset(); +} + +string_t +multiplayer_local_user::xbox_user_id() const +{ + return m_xboxUserId; +} + +multiplayer_local_user_lobby_state +multiplayer_local_user::lobby_state() const +{ + return m_lobbyState; +} + +void +multiplayer_local_user::set_lobby_state( + _In_ multiplayer_local_user_lobby_state userState + ) +{ + m_lobbyState = userState; + + if (userState == multiplayer_local_user_lobby_state::add || + userState == multiplayer_local_user_lobby_state::join || + userState == multiplayer_local_user_lobby_state::leave ) + { + m_writeChangesToService = true; + } +} + +multiplayer_local_user_game_state +multiplayer_local_user::game_state() const +{ + return m_gameState; +} + +void +multiplayer_local_user::set_game_state( + _In_ multiplayer_local_user_game_state userState + ) +{ + m_gameState = userState; +} + +const string_t& +multiplayer_local_user::lobby_handle_id() const +{ + return m_lobbyHandleId; +} + +void +multiplayer_local_user::set_lobby_handle_id(_In_ const string_t& handleId) +{ + m_lobbyHandleId = handleId; +} + +string_t +multiplayer_local_user::connection_address() const +{ + return m_connectionAddress; +} + +void +multiplayer_local_user::set_connection_address(_In_ string_t address) +{ + m_connectionAddress = address; +} + +bool +multiplayer_local_user::is_primary_xbox_live_context() const +{ + return m_isPrimaryXboxLiveContext; +} + +void +multiplayer_local_user::set_is_primary_xbox_live_context( + _In_ bool isPrimary + ) +{ + m_isPrimaryXboxLiveContext = isPrimary; +} + +bool +multiplayer_local_user::write_changes_to_service() const +{ + return m_writeChangesToService; +} + +void +multiplayer_local_user::set_write_changes_to_service(_In_ bool value) +{ + m_writeChangesToService = value; +} + +std::shared_ptr +multiplayer_local_user::context() const +{ + return m_xboxLiveContextImpl; +} + +function_context +multiplayer_local_user::rta_state_changed_context() const +{ + return m_rtaStateChangedContext; +} + +void +multiplayer_local_user::set_rta_state_changed_context( + _In_ function_context functionContext + ) +{ + m_rtaStateChangedContext = functionContext; +} + +function_context +multiplayer_local_user::session_changed_context() const +{ + return m_sessionChangedContext; +} + +void +multiplayer_local_user::set_session_changed_context( + _In_ function_context functionContext + ) +{ + m_sessionChangedContext = functionContext; +} + +function_context +multiplayer_local_user::subscription_lost_context() const +{ + return m_subscriptionLostContext; +} + +void +multiplayer_local_user::set_subscription_lost_context( + _In_ function_context functionContext + ) +{ + m_subscriptionLostContext = functionContext; +} + +function_context +multiplayer_local_user::rta_resync_context() const +{ + return m_rtaResyncContext; +} + +void +multiplayer_local_user::set_rta_resync_context( + _In_ function_context functionContext + ) +{ + m_rtaResyncContext = functionContext; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_local_user_manager.cpp b/Source/Services/Multiplayer/Manager/multiplayer_local_user_manager.cpp new file mode 100644 index 00000000..3c807c2a --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_local_user_manager.cpp @@ -0,0 +1,521 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" +#include "xsapi/services.h" +#include "user_context.h" + +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace xbox::services::real_time_activity; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_local_user_manager::multiplayer_local_user_manager() : + m_multiplayerSubscriptionLostEventHandlerCounter(0), + m_sessionChangeEventHandlerCounter(0), + m_rtaResyncEventHandlerCounter(0) +{ +} + +multiplayer_local_user_manager::~multiplayer_local_user_manager() +{ + change_all_local_user_lobby_state(multiplayer_local_user_lobby_state::remove); + remove_stale_local_users_from_map(); + + m_sessionChangeEventHandler.clear(); + m_multiplayerSubscriptionLostEventHandler.clear(); + m_rtaResyncEventHandler.clear(); +} + +std::map> +multiplayer_local_user_manager::get_local_user_map() +{ + std::lock_guard lock(m_lock.get()); + return m_localUserRequestMap; +} + +std::shared_ptr +multiplayer_local_user_manager::get_context( + _In_ const string_t& xboxUserId + ) +{ + if (xboxUserId.empty()) + { + return nullptr; + } + + std::lock_guard lock(m_lock.get()); + + auto iter = m_localUserRequestMap.find(xboxUserId); + if (iter != m_localUserRequestMap.end()) + { + return iter->second->context(); + } + return nullptr; +} + +std::shared_ptr +multiplayer_local_user_manager::get_local_user( + _In_ xbox_live_user_t user + ) +{ + if (user == nullptr) + { + return nullptr; + } + + std::lock_guard lock(m_lock.get()); + return get_local_user_helper(user); +} + +std::shared_ptr +multiplayer_local_user_manager::get_local_user( + _In_ const string_t& xboxUserId + ) +{ + std::lock_guard lock(m_lock.get()); + return get_local_user_helper(xboxUserId); +} + +std::shared_ptr +multiplayer_local_user_manager::get_local_user_helper( + _In_ xbox_live_user_t user + ) +{ + if (user == nullptr) + { + return nullptr; + } + + string_t xboxUserId = multiplayer_manager_utils::get_local_user_xbox_user_id(user); + return get_local_user_helper(xboxUserId); +} + +std::shared_ptr +multiplayer_local_user_manager::get_local_user_helper( + _In_ const string_t& xboxUserId + ) +{ + if (xboxUserId.empty()) + { + return nullptr; + } + + auto iter = m_localUserRequestMap.find(xboxUserId); + if (iter != m_localUserRequestMap.end()) + { + return iter->second; + } + return nullptr; +} + +std::shared_ptr +multiplayer_local_user_manager::get_primary_context() +{ + std::lock_guard lock(m_lock.get()); + return m_primaryXboxLiveContext; +} + +void +multiplayer_local_user_manager::change_all_local_user_lobby_state( + _In_ multiplayer_local_user_lobby_state state + ) +{ + std::lock_guard lock(m_lock.get()); + + for(const auto& user : m_localUserRequestMap) + { + const auto& localUser = user.second; + if (localUser != nullptr) + { + localUser->set_lobby_state(state); + } + } +} + +void +multiplayer_local_user_manager::change_all_local_user_game_state( + _In_ multiplayer_local_user_game_state state + ) +{ + std::lock_guard lock(m_lock.get()); + + for(const auto& user : m_localUserRequestMap) + { + const auto& localUser = user.second; + if (localUser != nullptr) + { + localUser->set_game_state(state); + } + } +} + +bool +multiplayer_local_user_manager::is_local_user_game_state( + _In_ multiplayer_local_user_game_state state + ) +{ + std::lock_guard lock(m_lock.get()); + + for(const auto& user : m_localUserRequestMap) + { + const auto& localUser = user.second; + if (localUser != nullptr && localUser->game_state() != state) + { + return false; + } + } + + return true; +} + +const std::shared_ptr& +multiplayer_local_user_manager::add_user_to_xbox_live_context_to_map( + _In_ xbox_live_user_t user + ) +{ + XSAPI_ASSERT(user != nullptr); + + string_t xboxUserId = user_context::get_user_id(user); + + bool isPrimary = m_localUserRequestMap.size() == 0 ? true : false; + + auto iter = m_localUserRequestMap.find(xboxUserId); + if (iter == m_localUserRequestMap.end()) + { + auto localUser = std::make_shared( + user, + xboxUserId, + isPrimary + ); + + auto ret = m_localUserRequestMap.insert(std::pair>(xboxUserId, localUser)); + iter = ret.first; + + if (isPrimary) + { + m_primaryXboxLiveContext = localUser->context(); + } + + // Activate events only for all users + activate_multiplayer_events(localUser); + } + + return iter->second; +} + +void +multiplayer_local_user_manager::remove_stale_local_users_from_map() +{ + std::lock_guard lock(m_lock.get()); + + bool swtichPrimaryXboxLiveContext = false; + for(auto iter = m_localUserRequestMap.begin(); iter != m_localUserRequestMap.end(); ) + { + const auto& localUser = iter->second; + if (localUser != nullptr && localUser->lobby_state() == multiplayer_local_user_lobby_state::remove) + { + // De-activate rta events for the old user. + deactivate_multiplayer_events(localUser); + + swtichPrimaryXboxLiveContext = localUser->is_primary_xbox_live_context(); + m_localUserRequestMap.erase(iter++); + } + else + { + ++iter; + } + } + + if (m_localUserRequestMap.size() == 0) + { + m_primaryXboxLiveContext = nullptr; + return; + } + + if (swtichPrimaryXboxLiveContext) + { + // Assign the first guy in the map to be the primary user. + std::shared_ptr user = m_localUserRequestMap.begin()->second; + if (user != nullptr) + { + user->set_is_primary_xbox_live_context(true); + m_primaryXboxLiveContext = user->context(); + } + } +} + +void +multiplayer_local_user_manager::activate_multiplayer_events( + _In_ const std::shared_ptr& localUser + ) +{ + XSAPI_ASSERT(localUser != nullptr); + if (localUser == nullptr) return; + + std::weak_ptr thisWeakPtr = shared_from_this(); + + auto xboxUserId = localUser->xbox_user_id(); + localUser->context()->real_time_activity_service()->activate(); + function_context rtaStateChanged = localUser->context()->real_time_activity_service()->add_connection_state_change_handler([thisWeakPtr, xboxUserId](_In_ real_time_activity_connection_state state) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_connection_state_changed(xboxUserId, state); + } + }); + localUser->set_rta_state_changed_context(rtaStateChanged); + + function_context rtaResyncContext = localUser->context()->real_time_activity_service()->add_resync_handler([thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_resync_message_received(); + } + }); + localUser->set_rta_resync_context(rtaResyncContext); + + if (!localUser->context()->multiplayer_service().subscriptions_enabled()) + { + localUser->context()->multiplayer_service().enable_multiplayer_subscriptions(); + function_context sessionChangedContext = localUser->context()->multiplayer_service().add_multiplayer_session_changed_handler([thisWeakPtr](_In_ const multiplayer_session_change_event_args& args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_session_changed(args); + } + }); + localUser->set_session_changed_context(sessionChangedContext); + + function_context subscriptionLostContext = localUser->context()->multiplayer_service().add_multiplayer_subscription_lost_handler([thisWeakPtr, xboxUserId](void) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_subscriptions_lost(xboxUserId); + } + }); + localUser->set_subscription_lost_context(subscriptionLostContext); + } +} + +void +multiplayer_local_user_manager::deactivate_multiplayer_events( + _In_ const std::shared_ptr& localUser + ) +{ + XSAPI_ASSERT(localUser != nullptr); + if (localUser == nullptr) return; + + pplx::create_task([localUser]() + { + if (localUser->context()->multiplayer_service().subscriptions_enabled()) + { + localUser->context()->multiplayer_service().remove_multiplayer_session_changed_handler(localUser->session_changed_context()); + localUser->context()->multiplayer_service().disable_multiplayer_subscriptions(); + } + + localUser->context()->real_time_activity_service()->remove_connection_state_change_handler(localUser->rta_state_changed_context()); + localUser->context()->real_time_activity_service()->remove_resync_handler(localUser->rta_resync_context()); + localUser->context()->real_time_activity_service()->deactivate(); + }); +} + +void +multiplayer_local_user_manager::on_connection_state_changed( + _In_ const string_t& xboxUserId, + _In_ real_time_activity_connection_state state + ) +{ + if (state == real_time_activity_connection_state::disconnected) + { + on_subscriptions_lost(xboxUserId); + } +} + +function_context +multiplayer_local_user_manager::add_multiplayer_session_changed_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_sessionChangeEventHandlerCounter; + m_sessionChangeEventHandler[m_sessionChangeEventHandlerCounter] = std::move(handler); + } + + return context; +} + +void +multiplayer_local_user_manager::remove_multiplayer_session_changed_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + m_sessionChangeEventHandler.erase(context); +} + +void +multiplayer_local_user_manager::on_session_changed( + _In_ const multiplayer_session_change_event_args& args + ) +{ + std::unordered_map> sessionChangeEventHandlerCopy; + { + std::lock_guard lock(m_subscriptionLock.get()); + sessionChangeEventHandlerCopy = m_sessionChangeEventHandler; + } + + for(auto& handler : sessionChangeEventHandlerCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(args); + } + catch (...) + { + LOG_ERROR("multiplayer_local_user_manager::on_session_changed call threw an exception"); + } + } + } +} + +function_context +multiplayer_local_user_manager::add_multiplayer_subscription_lost_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_multiplayerSubscriptionLostEventHandlerCounter; + m_multiplayerSubscriptionLostEventHandler[m_multiplayerSubscriptionLostEventHandlerCounter] = std::move(handler); + } + + return context; +} + +void +multiplayer_local_user_manager::remove_multiplayer_subscription_lost_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + m_multiplayerSubscriptionLostEventHandler.erase(context); +} + +void +multiplayer_local_user_manager::on_subscriptions_lost( + _In_ const string_t& xboxUserId + ) +{ + { + // Only fire this for the last user. + // Note: This will be fired from the previous user's deactivation. + std::lock_guard lock(m_lock.get()); + auto user = get_local_user_helper(xboxUserId); + if (user == nullptr && m_localUserRequestMap.size() > 0) + { + return; + } + } + + std::unordered_map> multiplayerSubscriptionLostEventHandlerCopy; + { + std::lock_guard lock(m_subscriptionLock.get()); + multiplayerSubscriptionLostEventHandlerCopy = m_multiplayerSubscriptionLostEventHandler; + } + + for(auto& handler : multiplayerSubscriptionLostEventHandlerCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(); + } + catch (...) + { + LOG_ERROR("multiplayer_local_user_manager::on_subscriptions_lost call threw an exception"); + } + } + } +} + +function_context +multiplayer_local_user_manager::add_rta_resync_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_rtaResyncEventHandlerCounter; + m_rtaResyncEventHandler[m_rtaResyncEventHandlerCounter] = std::move(handler); + } + + return context; +} + +void +multiplayer_local_user_manager::remove_rta_resync_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + m_rtaResyncEventHandler.erase(context); +} + +void +multiplayer_local_user_manager::on_resync_message_received() +{ + std::unordered_map> rtaResyncEventHandlerCopy; + { + std::lock_guard lock(m_subscriptionLock.get()); + rtaResyncEventHandlerCopy = m_rtaResyncEventHandler; + } + + for(auto& handler : rtaResyncEventHandlerCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(); + } + catch (...) + { + LOG_ERROR("multiplayer_local_user_manager::on_resync_message_received call threw an exception"); + } + } + } +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_manager.cpp b/Source/Services/Multiplayer/Manager/multiplayer_manager.cpp new file mode 100644 index 00000000..05225740 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_manager.cpp @@ -0,0 +1,388 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "xsapi/multiplayer_manager.h" +#include "multiplayer_manager_internal.h" + +#if defined __cplusplus_winrt +using namespace Platform; +using namespace Windows::Foundation::Collections; +#endif +using namespace xbox::services; +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +static std::mutex s_singletonLock; + +multiplayer_manager::multiplayer_manager() : + m_joinability(joinability::none), + m_isDirty(false) +{ +} + +std::shared_ptr +multiplayer_manager::get_singleton_instance() +{ + std::lock_guard guard(s_singletonLock); + static std::shared_ptr instance; + if (instance == nullptr) + { + instance = std::shared_ptr(new multiplayer_manager()); + } + + return instance; +} + +void +multiplayer_manager::initialize( + _In_ string_t lobbySessionTemplateName + ) +{ + XSAPI_ASSERT(!lobbySessionTemplateName.empty()); + + std::lock_guard guard(m_lock); + if(m_multiplayerClientManager != nullptr) + { + m_multiplayerClientManager->shutdown(); + + m_multiplayerLobbySession = nullptr; + m_multiplayerClientManager = nullptr; + } + + m_multiplayerClientManager = std::make_shared( + lobbySessionTemplateName + ); + + m_multiplayerClientManager->register_local_user_manager_events(); + m_multiplayerLobbySession = std::make_shared(m_multiplayerClientManager); +} + +bool +multiplayer_manager::_Is_dirty() +{ + return m_isDirty; +} + +std::vector +multiplayer_manager::do_work() +{ + std::lock_guard guard(m_lock); + + if (m_multiplayerClientManager == nullptr) + { + m_isDirty = false; + + // The title hasn't called initialize() on the manager yet. + return std::vector(); + } + else if (!m_multiplayerClientManager->is_update_avaialable()) + { + m_isDirty = false; + + // To handle the scenario of returning InvitedXuid info in the join_lobby_completed event + std::vector eventQueue; + if (m_multiplayerClientManager->event_queue().size() > 0) + { + eventQueue = m_multiplayerClientManager->event_queue(); + m_multiplayerClientManager->clear_event_queue(); + } + + return eventQueue; + } + + std::vector eventQueue; + + try + { + m_isDirty = true; + eventQueue = m_multiplayerClientManager->do_work(); + + std::shared_ptr clientRequest = m_multiplayerClientManager->last_pending_read(); + if (clientRequest != nullptr) + { + m_joinability = clientRequest->lobby_client()->joinability(); + set_multiplayer_game_session(clientRequest->game_client()->game()); + set_multiplayer_lobby_session(clientRequest->lobby_client()->lobby()); + } + else + { + m_joinability = joinability::none; + set_multiplayer_game_session(nullptr); + set_multiplayer_lobby_session(nullptr); + } + } + catch(...){} + + return eventQueue; +} + +std::shared_ptr +multiplayer_manager::game_session() const +{ + std::lock_guard guard(m_lock); + return m_multiplayerGameSession; +} + +std::shared_ptr +multiplayer_manager::lobby_session() const +{ + std::lock_guard guard(m_lock); + return m_multiplayerLobbySession; +} + +void +multiplayer_manager::set_multiplayer_game_session( + _In_ std::shared_ptr gameSession + ) +{ + // Note: This function does not require a lock as the functions that call this already has a m_lock. + + if (gameSession == nullptr) + { + m_multiplayerGameSession = nullptr; + } + else + { + m_multiplayerGameSession = gameSession; + m_multiplayerGameSession->_Set_multiplayer_client_manager(m_multiplayerClientManager); + } +} + +void +multiplayer_manager::set_multiplayer_lobby_session( + _In_ std::shared_ptr multiplayerLobby + ) +{ + // Note: This function does not require a lock as the functions that call this already has a m_lock. + + if (multiplayerLobby == nullptr) + { + if (m_multiplayerLobbySession != nullptr) + { + m_multiplayerLobbySession.reset(); + } + + // Don't set the lobby to null so that the title can add local users whenever it chooses. + m_multiplayerLobbySession = std::make_shared(m_multiplayerClientManager); + } + else + { + m_multiplayerLobbySession = multiplayerLobby; + m_multiplayerLobbySession->_Set_multiplayer_client_manager(m_multiplayerClientManager); + } +} + +xbox_live_result +multiplayer_manager::join_lobby( + _In_ const string_t& handleId, + _In_ xbox_live_user_t user + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + + std::vector users; + users.push_back(user); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->join_lobby_by_handle(handleId, users), void); +} + +#if TV_API +xbox_live_result +multiplayer_manager::join_lobby( + _In_ const string_t& handleId, + _In_ std::vector users + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->join_lobby_by_handle(handleId, users), void); +} + +xbox_live_result +multiplayer_manager::join_lobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ std::vector users + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->join_lobby(eventArgs, users), void); +} + +void +multiplayer_manager::invite_party_to_game() +{ +} +#endif + +#if !XSAPI_U +xbox_live_result +multiplayer_manager::join_lobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ xbox_live_user_t user + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + + std::vector users; + users.push_back(user); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->join_lobby(eventArgs, users), void); +} +#endif + +xbox_live_result +multiplayer_manager::join_game_from_lobby( + _In_ const string_t& sessionTemplateName + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->join_game_from_lobby(sessionTemplateName), void); +} + +xbox_live_result +multiplayer_manager::join_game( + _In_ const string_t& sessionName, + _In_ const string_t& sessionTemplateName, + _In_ const std::vector& xboxUserIds + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->join_game(sessionName, sessionTemplateName, xboxUserIds), void); +} + +xbox_live_result +multiplayer_manager::leave_game() +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->leave_game(), void); +} + +xbox_live_result +multiplayer_manager::find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->find_match(hopperName, attributes, timeout), void); +} + +void +multiplayer_manager::cancel_match() +{ + if (m_multiplayerClientManager != nullptr && m_multiplayerClientManager->match_client() != nullptr) + { + m_multiplayerClientManager->match_client()->cancel_match(); + } +} + +xbox::services::multiplayer::manager::match_status +multiplayer_manager::match_status() const +{ + if (m_multiplayerClientManager != nullptr && m_multiplayerClientManager->match_client() != nullptr) + { + return m_multiplayerClientManager->match_client()->match_status(); + } + + return match_status::none; +} + +std::chrono::seconds +multiplayer_manager::estimated_match_wait_time() const +{ + if (m_multiplayerClientManager != nullptr && m_multiplayerClientManager->match_client() != nullptr) + { + return m_multiplayerClientManager->match_client()->estimated_match_wait_time(); + } + + return std::chrono::seconds(0); +} + +void +multiplayer_manager::set_quality_of_service_measurements( + _In_ std::shared_ptr> measurements + ) +{ + if (m_multiplayerClientManager != nullptr && m_multiplayerClientManager->match_client() != nullptr) + { + m_multiplayerClientManager->match_client()->set_quality_of_service_measurements(measurements); + } +} + +bool +multiplayer_manager::auto_fill_members_during_matchmaking() const +{ + return false; +} + +void +multiplayer_manager::set_auto_fill_members_during_matchmaking( + _In_ bool autoFillMembers + ) +{ + if (m_multiplayerClientManager != nullptr) + { + m_multiplayerClientManager->set_auto_fill_members_during_matchmaking(autoFillMembers); + } +} + +xbox::services::multiplayer::manager::joinability +multiplayer_manager::joinability() const +{ + return m_joinability; +} + +xbox_live_result +multiplayer_manager::set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ) +{ + RETURN_CPP_IF(m_multiplayerClientManager == nullptr, void, xbox_live_error_code::logic_error, "Call multiplayer_manager::initialize() first."); + + RETURN_EXCEPTION_FREE_XBOX_LIVE_RESULT(m_multiplayerClientManager->set_joinability(value, context), void); +} + +std::shared_ptr +multiplayer_manager::_Game_client() +{ + auto clientManger = m_multiplayerClientManager; + if (clientManger == nullptr || clientManger->latest_pending_read() == nullptr) + { + return nullptr; + } + return clientManger->latest_pending_read()->game_client(); +} + +std::shared_ptr +multiplayer_manager::_Lobby_client() +{ + auto clientManger = m_multiplayerClientManager; + if (clientManger == nullptr || clientManger->latest_pending_read() == nullptr) + { + return nullptr; + } + return clientManger->latest_pending_read()->lobby_client(); +} + +#if UNIT_TEST_SERVICES +void +multiplayer_manager::_Shutdown() +{ + auto clientManger = m_multiplayerClientManager; + if (clientManger == nullptr || clientManger->latest_pending_read() == nullptr) + { + return; + } + return clientManger->shutdown(); +} +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_manager_internal.h b/Source/Services/Multiplayer/Manager/multiplayer_manager_internal.h new file mode 100644 index 00000000..c1402526 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_manager_internal.h @@ -0,0 +1,1227 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include +#include +#include "pplx/pplxtasks.h" +#include "xsapi/multiplayer.h" +#include "xsapi/multiplayer_manager.h" +#include "xsapi/social.h" +#include "xsapi/real_time_activity.h" +#include "system_internal.h" +#include "user_context.h" +#include "xbox_live_context_impl.h" + +namespace xbox { namespace services { + class xbox_live_context_impl; +}} + +namespace xbox { namespace services { namespace multiplayer { namespace manager { + +class multiplayer_match_client; +class multiplayer_client_manager; +class multiplayer_local_user_manager; +class multiplayer_lobby_client; + +enum class multiplayer_local_user_lobby_state +{ + unknown, + + add, + + join, + + in_session, + + leave, + + remove +}; + +enum class multiplayer_local_user_game_state +{ + unknown, + + pending_join, + + join, + + in_session, + + leave +}; + +enum class pending_request_type +{ + synchronized_changes, + + non_synchronized_changes +}; + +class multiplayer_client_pending_request +{ +public: + multiplayer_client_pending_request(); + + pending_request_type request_type() const; + + context_t context(); + + uint32_t identifier() const; + + // Local user properties + std::shared_ptr local_user(); + void set_local_user(_In_ std::shared_ptr user); + + multiplayer_local_user_lobby_state lobby_state(); + void set_lobby_state(_In_ multiplayer_local_user_lobby_state userState); + + const string_t& lobby_handle_id() const; + void set_lobby_handle_id(_In_ const string_t& handleId); + + const multiplayer_session_reference& team_session_reference() const; + void set_team_session_reference(_In_ const multiplayer_session_reference& sessionRef); + + const string_t& local_user_connection_address() const; + void set_local_user_connection_address( + _In_ std::shared_ptr localUser, + _In_ string_t connectionAddress, + _In_opt_ context_t context + ); + + const std::map& local_user_properties() const; + void set_local_user_properties( + _In_ std::shared_ptr localUser, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ); + + // Session non-synchronized properties + multiplayer::manager::joinability joinability(); + void set_joinability(_In_ xbox::services::multiplayer::manager::joinability value, _In_opt_ context_t context); + + const std::map& session_properties() const; + void set_session_properties(_In_ string_t name, _In_ web::json::value valueJson, _In_opt_ context_t context); + + // Session synchronized properties + const string_t& synchronized_host_device_token() const; + void set_synchronized_host_device_token(_In_ const string_t& hostDeviceToken, _In_opt_ context_t context); + + const std::map& synchronized_session_properties() const; + void set_synchronized_session_properties(_In_ string_t name, _In_ web::json::value valueJson, _In_opt_ context_t context); + + void append_pending_changes( + _In_ std::shared_ptr sessionToCommit, + _In_ std::shared_ptr localUser, + _In_ bool isGameInProgress = false + ); + +private: + + context_t m_context; + pending_request_type m_requestType; + uint32_t m_identifier; + static volatile long s_uniqueIndentifier; + + // Local user properties + std::shared_ptr m_localUser; + multiplayer_local_user_lobby_state m_localUserLobbyState; + std::map m_localUserProperties; + string_t m_localUserConnectionAddress; + string_t m_lobbyHandleId; // Only used while joining a friend's lobby + xbox::services::multiplayer::multiplayer_session_reference m_teamSessionRef; // Only used for Tournament MPM integration support. + + // Session non-synchronized properties + std::map m_sessionProperties; + xbox::services::multiplayer::manager::joinability m_joinability; + + // Session synchronized properties + string_t m_synchronizedHostDeviceToken; + std::map m_synchronizedSessionProperties; +}; + + +class multiplayer_session_writer : public std::enable_shared_from_this +{ +public: + multiplayer_session_writer(); + + multiplayer_session_writer( + _In_ std::shared_ptr localUserManager + ); + + const std::shared_ptr& session() const; + void update_session(_In_ const std::shared_ptr& updatedSession); + + uint64_t tap_change_number() const; + void set_tap_change_number(_In_ uint64_t changeNumber); + + bool is_tap_received() const; + void set_tap_received(_In_ bool bReceived); + + bool is_write_in_progress() const; + void set_write_in_progress(_In_ bool writeInProgress); + + void on_session_changed( + _In_ const xbox::services::multiplayer::multiplayer_session_change_event_args& args + ); + + pplx::task> commit_synchronized_changes( + _In_ std::shared_ptr sessionToCommit + ); + + pplx::task>> leave_remote_session( + _In_ std::shared_ptr session + ); + + pplx::task>> commit_pending_changes( + _In_ std::vector> processingQueue, + _In_ multiplayer_session_type sessionType, + _In_ bool isGameInProgress = false + ); + + pplx::task>> commit_pending_synchronized_changes( + _In_ std::vector> processingQueue, + _In_ multiplayer_session_type sessionType + ); + + pplx::task>> write_session( + _In_ std::shared_ptr xboxLiveContext, + _In_ std::shared_ptr session, + _In_ xbox::services::multiplayer::multiplayer_session_write_mode mode, + _In_ bool updateLatest = true + ); + + pplx::task>> write_session_by_handle( + _In_ std::shared_ptr xboxLiveContext, + _In_ std::shared_ptr session, + _In_ xbox::services::multiplayer::multiplayer_session_write_mode mode, + _In_ const string_t& handleId, + _In_ bool updateLatest = true + ); + + void on_session_updated( + _In_ const std::shared_ptr& updatedSession + ); + + function_context add_multiplayer_session_updated_handler( + _In_ std::function& )> handler + ); + + void on_resync_message_received(); + + std::shared_ptr get_primary_context(); + + std::vector handle_events( + _In_ std::vector> processingQueue, + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_session_type sessionType + ); + +private: + void destroy(); + + void resync(); + + xbox_live_result> write_session_helper( + _In_ xbox_live_result> sessionResult, + _In_ bool updateLatest + ); + + pplx::task>> get_current_session_helper( + _In_ std::shared_ptr xboxLiveContext, + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionReference + ); + + // resync + bool m_isTaskInProgress; + function_context m_handleResyncEventCounter; + xbox::services::system::xbox_live_mutex m_resyncLock; + + xbox::services::system::xbox_live_mutex m_stateLock; + function_context m_sessionUpdateEventHandlerCounter; + std::unordered_map)>> m_sessionUpdateEventHandler; + + std::mutex m_synchronizeWriteWithTapLock; + uint64_t m_tapChangeNumber; + bool m_isTapReceived; + uint64_t m_numOfWritesInProgress; + std::shared_ptr m_session; + std::shared_ptr m_multiplayerLocalUserManager; +}; + +class multiplayer_game_client : public std::enable_shared_from_this +{ +public: + multiplayer_game_client(); + + ~multiplayer_game_client(); + + multiplayer_game_client( + _In_ std::shared_ptr localUserManager + ); + + void deep_copy_if_updated(_In_ const multiplayer_game_client& other); + + void initialize(); + + void set_game_session_template(_In_ const string_t& sessionTemplateName); + + const std::shared_ptr& session_writer() const; + + const std::shared_ptr& game() const; + + void update_game(_In_ const std::shared_ptr& multiplayerGame); + + std::vector do_work(); + bool is_request_in_progress(); + bool is_pending_game_changes(); + + void clear_pending_queue(); + void add_to_pending_queue(_In_ std::shared_ptr pendingRequest); + void add_to_processing_queue(_In_ std::vector> processingQueue); + void remove_from_processing_queue(_In_ uint32_t identifier); + + const std::vector& multiplayer_event_queue(); + std::vector> get_processing_queue(); + + void update_game_session(_In_ const std::shared_ptr& session); + + void update_objects( + const std::shared_ptr& updatedSession, + const std::shared_ptr& lobbySession + ); + + const std::shared_ptr& session() const; + + void update_session(_In_ const std::shared_ptr& session); + + void remove_stale_users_from_remote_session(); + + void set_local_member_properties_to_remote_session( + _In_ const std::shared_ptr& localUser, + _In_ const std::map& localUserMap, + _In_ const string_t& localUserConnectionAddress + ); + + xbox_live_result join_game_helper( + _In_ const string_t& sessionName + ); + + void leave_remote_session( + _In_ std::shared_ptr session, + _In_ bool stopAdvertisingGameSession, + _In_ bool triggerCompletionEvent + ); + + xbox_live_result join_game_from_lobby_helper(); + + pplx::task>> join_game_by_session_reference( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& gameSessionRef + ); + + pplx::task>> join_game_by_handle( + _In_ const string_t& handleId, + _In_ bool createGameIfFailedToJoin + ); + + pplx::task>> join_game_for_all_local_members( + _In_ const std::shared_ptr& gameSession, + _In_ const string_t& handleId = string_t(), + _In_ bool createGameIfFailedToJoin = false + ); + + pplx::task>> join_game_for_all_local_members_helper( + _In_ const std::shared_ptr& session, + _In_ bool writeMemberPropertiesFromLobby, + _In_ const string_t& handleId + ); + +private: + + std::shared_ptr lobby_client(); + std::shared_ptr lobby_session(); + + std::shared_ptr convert_to_multiplayer_game( + _In_ const std::shared_ptr& sessionToConvert, + _In_ const std::shared_ptr& lobbySession + ); + + pplx::task>> join_helper( + _In_ std::shared_ptr localUser, + _In_ std::shared_ptr session, + _In_ bool writeMemberPropertiesFromLobby, + _In_ const string_t& handleId + ); + + void add_multiplayer_event_helper( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_event_type eventType, + _In_ std::shared_ptr eventArgs, + _In_opt_ context_t context = nullptr + ); + + mutable std::mutex m_clientRequestLock; + std::atomic m_pendingCommitInProgress; + string_t m_gameSessionTemplateName; + uint64_t m_updateNumber; + std::shared_ptr m_sessionWriter; + std::vector m_multiplayerEventQueue; + std::shared_ptr m_multiplayerGame; + std::shared_ptr m_multiplayerLocalUserManager; + std::queue> m_pendingRequestQueue; + std::vector> m_processingQueue; +}; + +class multiplayer_lobby_client : public std::enable_shared_from_this +{ +public: + multiplayer_lobby_client(); + + ~multiplayer_lobby_client(); + + multiplayer_lobby_client( + _In_ string_t lobbySessionTemplateName, + _In_ std::shared_ptr localUserManager + ); + + void deep_copy_if_updated(_In_ const multiplayer_lobby_client& other); + + void initialize(); + + const std::shared_ptr& session_writer() const; + + const std::shared_ptr& lobby() const; + + void clear_pending_queue(); + void add_to_pending_queue(_In_ std::shared_ptr pendingRequest); + void add_to_processing_queue(_In_ std::vector> processingQueue); + void remove_from_processing_queue(_In_ uint32_t identifier); + + xbox_live_result add_local_user( + _In_ xbox_live_user_t user, + _In_ multiplayer_local_user_lobby_state userState, + _In_ const string_t& handleId = string_t(), + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionRef = xbox::services::multiplayer::multiplayer_session_reference() + ); + + void add_local_users(_In_ std::vector user, _In_ const string_t& handleId); + void add_local_users(_In_ std::vector user, _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionRef); + + xbox_live_result remove_local_user(_In_ xbox_live_user_t user); + void remove_all_local_users(); + + xbox_live_result set_local_member_properties( + _In_ xbox_live_user_t user, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ); + + xbox_live_result delete_local_member_properties( + _In_ xbox_live_user_t user, + _In_ const string_t& name, + _In_opt_ context_t context + ); + + xbox_live_result set_local_member_connection_address( + _In_ xbox_live_user_t user, + _In_ string_t address, + _In_opt_ context_t context + ); + + std::vector do_work(); + bool is_pending_lobby_changes(); + bool is_request_in_progress(); + + pplx::task>> commit_pending_lobby_changes( + _In_ bool joinByHandleId, + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef = xbox::services::multiplayer::multiplayer_session_reference() + ); + + pplx::task>> commit_lobby_changes( + _In_ std::shared_ptr lobbySessionToCommit + ); + + xbox_live_result create_game_from_lobby(); + + xbox::services::multiplayer::manager::joinability joinability(); + + xbox_live_result set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ); + + const std::vector& multiplayer_event_queue(); + std::vector> get_processing_queue(); + + void update_lobby_session(_In_ const std::shared_ptr& updatedSession); + + void update_objects( + const std::shared_ptr& updatedSession, + const std::shared_ptr& gameSession + ); + + const std::shared_ptr& session() const; + + void update_session( + _In_ const std::shared_ptr& updatedSession + ); + + void leave_remote_session( + _In_ std::shared_ptr session + ); + + void stop_advertising_game_session( + _In_ xbox_live_result> result + ); + + void advertise_game_session(); + void clear_game_session_from_lobby(); + + bool is_transfer_handle_state(_In_ const string_t& state); + string_t get_transfer_handle(); + + void handle_game_session_ready_event( + _In_ const std::shared_ptr& lobbySession + ); + + static const string_t c_transferHandlePropertyName; + static const string_t c_joinabilityPropertyName; + + void remove_stale_xbox_live_context_from_map(); + std::map> get_local_user_map(); + std::shared_ptr get_primary_context(); + +private: + std::shared_ptr game_client(); + std::shared_ptr game_session(); + + void update_lobby(_In_ std::shared_ptr multiplayerLobby); + void update_local_lobby_members( + _In_ const std::shared_ptr& lobbySession, + _In_ const std::shared_ptr& gameSession + ); + + bool is_pending_lobby_local_user_changes(); + + bool should_update_host_token( + _In_ std::shared_ptr localUser, + _In_ std::shared_ptr session + ); + + void user_state_changed( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_local_user_lobby_state localUserLobbyState, + _In_ string_t xboxUserId + ); + + void handle_lobby_change_events( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ std::shared_ptr localUser, + _In_ const std::vector>& processingQueue + ); + + void handle_join_lobby_completed( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage + ); + + void join_lobby_completed( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ const string_t& invitedXboxUserId + ); + + void add_to_multiplayer_event_queue(); + + void add_multiplayer_event_helper( + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_event_type eventType, + _In_ std::shared_ptr eventArgs, + _In_opt_ context_t context = nullptr + ); + + xbox_live_result> commit_lobby_changes_helper( + _In_ std::shared_ptr lobbySessionToCommit + ); + + std::shared_ptr convert_to_multiplayer_lobby( + _In_ const std::shared_ptr& sessionToConvert, + _In_ const std::shared_ptr& gameSession + ); + + string_t m_lobbySessionTemplateName; + std::atomic m_pendingCommitInProgress; + + uint64_t m_updateNumber; + xbox::services::multiplayer::manager::joinability m_joinability; + mutable std::mutex m_clientRequestLock; + std::queue> m_pendingRequestQueue; + std::vector m_multiplayerEventQueue; + std::shared_ptr m_sessionWriter; + std::shared_ptr m_multiplayerLobby; + std::vector> m_localLobbyMembers; + std::shared_ptr m_multiplayerLocalUserManager; + std::vector> m_processingQueue; +}; + +class multiplayer_client_pending_reader : public std::enable_shared_from_this +{ +public: + multiplayer_client_pending_reader(); + + ~multiplayer_client_pending_reader(); + + multiplayer_client_pending_reader( + _In_ string_t lobbySessionTemplateName, + _In_ std::shared_ptr localUserManager + ); + + void deep_copy_if_updated(_In_ const multiplayer_client_pending_reader& other); + bool is_update_avaialable(_In_ const multiplayer_client_pending_reader& other); + + void do_work(); + void process_match_events(); + + std::shared_ptr lobby_client(); + std::shared_ptr game_client(); + std::shared_ptr match_client(); + + std::vector multiplayer_event_queue() const; + + void clear_multiplayer_event_queue(); + void add_to_multiplayer_event_queue(_In_ multiplayer_event multiplayerEvent); + void add_to_multiplayer_event_queue(_In_ std::vector multiplayerEventQueue); + + std::shared_ptr get_session(_In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef); + void update_session(_In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef, _In_ std::shared_ptr session); + + bool is_lobby(_In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef); + bool is_game(_In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef); + bool is_match(_In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef); + + xbox_live_result find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout + ); + + void set_auto_fill_members_during_matchmaking(_In_ bool autoFillMembers); + + xbox_live_result set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ); + + xbox_live_result set_properties( + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ); + + xbox_live_result set_synchronized_properties( + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef, + _In_ string_t name, + _In_ web::json::value valueJson, + _In_opt_ context_t context + ); + + xbox_live_result set_synchronized_host( + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef, + _In_ const string_t& hostDeviceToken, + _In_opt_ context_t context + ); + + std::shared_ptr convert_to_game_member(_In_ std::shared_ptr member); + +private: + void add_to_pending_queue( + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef, + _In_ std::shared_ptr pendingRequest + ); + + static bool is_local(_In_ const string_t& xboxUserId, _In_ const std::map>& xboxLiveContextMap); + + bool m_autoFillMembers; + std::vector m_multiplayerEventQueue; + mutable std::mutex m_clientRequestLock; + std::shared_ptr m_lobbyClient; + std::shared_ptr m_gameClient; + std::shared_ptr m_matchClient; + std::shared_ptr m_multiplayerLocalUserManager; +}; + +class multiplayer_local_user +{ +public: + + multiplayer_local_user( + _In_ xbox_live_user_t user, + _In_ string_t xboxUserId, + _In_ bool isPrimary + ); + + ~multiplayer_local_user(); + + string_t xbox_user_id() const; + + std::shared_ptr context() const; + + const string_t& lobby_handle_id() const; + void set_lobby_handle_id(_In_ const string_t& handleId); + + multiplayer_local_user_lobby_state lobby_state() const; + void set_lobby_state(_In_ multiplayer_local_user_lobby_state userState); + + multiplayer_local_user_game_state game_state() const; + void set_game_state(_In_ multiplayer_local_user_game_state userState); + + string_t connection_address() const; + void set_connection_address(_In_ string_t address); + + bool is_primary_xbox_live_context() const; + void set_is_primary_xbox_live_context(_In_ bool isPrimary); + + void set_write_changes_to_service(_In_ bool value); + bool write_changes_to_service() const; + + function_context rta_state_changed_context() const; + void set_rta_state_changed_context(_In_ function_context functionContext); + + function_context session_changed_context() const; + void set_session_changed_context(_In_ function_context functionContext); + + function_context rta_resync_context() const; + void set_rta_resync_context(_In_ function_context functionContext); + + function_context subscription_lost_context() const; + void set_subscription_lost_context(_In_ function_context functionContext); + +private: + function_context m_rtaStateChangedContext; + function_context m_sessionChangedContext; + function_context m_subscriptionLostContext; + function_context m_rtaResyncContext; + bool m_writeChangesToService; + bool m_writeConnectionAddress; + string_t m_xboxUserId; + string_t m_connectionAddress; + string_t m_lobbyHandleId; + multiplayer_local_user_lobby_state m_lobbyState; + multiplayer_local_user_game_state m_gameState; + bool m_isPrimaryXboxLiveContext; + std::shared_ptr m_xboxLiveContextImpl; +}; + +class multiplayer_local_user_manager : public std::enable_shared_from_this +{ +public: + multiplayer_local_user_manager(); + + ~multiplayer_local_user_manager(); + + xbox::services::system::xbox_live_mutex m_lock; + std::shared_ptr get_primary_context(); + + void change_all_local_user_lobby_state(_In_ multiplayer_local_user_lobby_state state); + void change_all_local_user_game_state(_In_ multiplayer_local_user_game_state state); + bool is_local_user_game_state(_In_ multiplayer_local_user_game_state state); + + std::map> get_local_user_map(); + std::shared_ptr get_context(_In_ const string_t& xboxUserId); + + std::shared_ptr get_local_user(_In_ const string_t& xboxUserId); + std::shared_ptr get_local_user_helper(_In_ const string_t& xboxUserId); + + std::shared_ptr get_local_user( + _In_ xbox_live_user_t user + ); + + std::shared_ptr get_local_user_helper( + _In_ xbox_live_user_t user + ); + + const std::shared_ptr& add_user_to_xbox_live_context_to_map(_In_ xbox_live_user_t user); + void remove_stale_local_users_from_map(); + + void activate_multiplayer_events(_In_ const std::shared_ptr& localuser); + void deactivate_multiplayer_events(_In_ const std::shared_ptr& localUser); + + function_context add_multiplayer_session_changed_handler( + _In_ std::function handler + ); + void remove_multiplayer_session_changed_handler(_In_ function_context context); + + function_context add_multiplayer_subscription_lost_handler(_In_ std::function handler); + void remove_multiplayer_subscription_lost_handler(_In_ function_context context); + + function_context add_rta_resync_handler(_In_ std::function handler); + void remove_rta_resync_handler(_In_ function_context context); + +private: + void on_subscriptions_lost(_In_ const string_t& xboxUserId); + + void on_session_changed( + _In_ const xbox::services::multiplayer::multiplayer_session_change_event_args& args + ); + + void on_connection_state_changed( + _In_ const string_t& xboxUserId, + _In_ xbox::services::real_time_activity::real_time_activity_connection_state state + ); + + void on_resync_message_received(); + + xbox::services::system::xbox_live_mutex m_subscriptionLock; + function_context m_sessionChangeEventHandlerCounter; + function_context m_multiplayerSubscriptionLostEventHandlerCounter; + function_context m_rtaResyncEventHandlerCounter; + std::unordered_map> m_sessionChangeEventHandler; + std::unordered_map> m_multiplayerSubscriptionLostEventHandler; + std::unordered_map> m_rtaResyncEventHandler; + + std::map> m_localUserRequestMap; + std::shared_ptr m_primaryXboxLiveContext; +}; + +class multiplayer_client_manager : public std::enable_shared_from_this +{ +public: + multiplayer_client_manager(const multiplayer_client_manager& other); + + multiplayer_client_manager& deep_copy(_In_ const multiplayer_client_manager& other); + + multiplayer_client_manager( + _In_ string_t lobbySessionTemplateName + ); + + void initialize(); + void shutdown(); + + void register_local_user_manager_events(); + bool is_update_avaialable(); + bool is_request_in_progress(); + + std::shared_ptr local_user_manager(); + + std::shared_ptr get_primary_context(); + + std::shared_ptr lobby_client() const; + std::shared_ptr latest_pending_read() const; + std::shared_ptr last_pending_read() const; + + xbox_live_result join_lobby_by_handle( + _In_ const string_t& handleId, + _In_ std::vector users + ); + + xbox_live_result join_lobby_by_session_reference( + _In_ const multiplayer_session_reference& sessionRef, + _In_ std::vector users + ); +#if !XSAPI_U + xbox_live_result join_lobby( + _In_ Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs^ eventArgs, + _In_ std::vector users + ); + + xbox_live_result join_lobby( _In_ Windows::Foundation::Uri^ url, _In_ std::vector users ); +#endif + xbox_live_result join_game_from_lobby(_In_ const string_t& sessionTemplateName); + + xbox_live_result join_game( + _In_ const string_t& sessionName, + _In_ const string_t& sessionTemplateName, + _In_ const std::vector& xboxUserIds + ); + + xbox_live_result leave_game(); + + std::vector do_work(); + + pplx::task>> get_activities_for_social_group( + _In_ xbox_live_user_t user, + _In_ const string_t& socialGroup + ); + + xbox_live_result invite_friends( + _In_ xbox_live_user_t user, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ); + + xbox_live_result invite_users( + _In_ xbox_live_user_t user, + _In_ const std::vector& xboxUserIds, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ); + + xbox_live_result set_properties( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionRef, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ); + + xbox_live_result set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_opt_ context_t context + ); + + xbox_live_result set_synchronized_host( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionRef, + _In_ const string_t& hostDeviceToken, + _In_opt_ context_t context + ); + + xbox_live_result set_synchronized_properties( + _In_ const xbox::services::multiplayer::multiplayer_session_reference& sessionRef, + _In_ const string_t& name, + _In_ const web::json::value& valueJson, + _In_opt_ context_t context + ); + + std::shared_ptr match_client(); + + xbox_live_result find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout + ); + + void set_auto_fill_members_during_matchmaking(_In_ bool autoFillMembers); + + void on_session_changed( + _In_ const xbox::services::multiplayer::multiplayer_session_change_event_args& args + ); + + std::vector event_queue() const; + void clear_event_queue(); + + void on_multiplayer_subscriptions_lost(); + +private: + + void destroy(); + + xbox::services::multiplayer::multiplayer_service& get_multiplayer_service( + _In_ xbox_live_user_t user + ); + + std::map> get_xbox_live_context_map(); + + bool is_pending_lobby_local_user_changes(); + void on_resync_message_received(); + + bool should_update_host_token( + _In_ std::shared_ptr localUser, + _In_ std::shared_ptr session + ); + + void update_match_session(_In_ std::shared_ptr session); + void add_to_multiplayer_event_queue(_In_ multiplayer_event multiplayerEvent); + + pplx::task>> get_current_session_helper( + _In_ std::shared_ptr xboxLiveContext, + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionReference + ); + + multiplayer_session_type get_session_type( + _In_ std::shared_ptr session + ); + + void process_events( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ); + + void handle_member_list_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ); + + void handle_member_properties_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ); + + void handle_session_properties_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ); + + void handle_host_changed( + _In_ std::shared_ptr currentSession, + _In_ multiplayer_session_type sessionType + ); + + void handle_tournament_properties_changed( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession, + _In_ multiplayer_session_type sessionType + ); + + void handle_match_status_changed( + _In_ std::shared_ptr currentSession + ); + + void handle_initialization_state_changed( + _In_ std::shared_ptr currentSession + ); + + void synchronized_write_completed( + _In_ std::error_code errorCode, + _In_ std::string errorMessage, + _In_ multiplayer_event_type eventType, + _In_ multiplayer_session_type sessionType + ); + + void add_multiplayer_event( + _In_ multiplayer_event_type eventType, + _In_ multiplayer_session_type sessionType, + _In_ std::error_code errorCode = xbox::services::xbox_live_error_code::no_error, + _In_ std::string errorMessage = std::string() + ); + + void add_multiplayer_event_helper( + _In_ multiplayer_event_type eventType, + _In_ multiplayer_session_type sessionType, + _In_ std::error_code errorCode = xbox::services::xbox_live_error_code::no_error, + _In_ std::string errorMessage = std::string() + ); + + mutable std::mutex m_clientRequestLock; + std::mutex m_synchronizeWriteWithTapLock; + std::atomic m_subscriptionsLostFired; + + bool m_autoFillMembers; + string_t m_lobbySessionTemplateName; + function_context m_sessionChangedContext; + function_context m_subscriptionLostContext; + function_context m_rtaResyncContext; + + pplx::task m_pendingGameCommitTask; + std::vector m_multiplayerEventQueue; + xbox::services::multiplayer::multiplayer_service m_clientManagerMultiplayerService; + std::shared_ptr m_primaryXboxLiveContext; + std::shared_ptr m_multiplayerLocalUserManager; + std::shared_ptr m_lastPendingRead; + std::shared_ptr m_latestPendingRead; +}; + +class multiplayer_match_client : public std::enable_shared_from_this +{ +public: + multiplayer_match_client( + _In_ std::shared_ptr localUserManager + ); + + std::vector do_work(); + const std::vector& multiplayer_event_queue(); + void deep_copy_if_updated(_In_ const multiplayer_match_client& other); + + xbox::services::multiplayer::manager::match_status match_status() const; + void set_match_status(_In_ xbox::services::multiplayer::manager::match_status status); + + std::chrono::seconds estimated_match_wait_time() const; + + xbox_live_result find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout, + _In_ std::shared_ptr session, + _In_ bool preserveSession = false + ); + + xbox_live_result find_match( + _In_ std::shared_ptr session, + _In_ bool preserveSession + ); + + void cancel_match(); + + void update_session(_In_ std::shared_ptr currentSession); + std::shared_ptr session(); + + void handle_match_status_changed( + _In_ std::shared_ptr matchSession + ); + + void handle_initialization_state_changed( + _In_ std::shared_ptr matchSession + ); + + void on_session_changed( + _In_ const xbox::services::multiplayer::multiplayer_session_change_event_args& args + ); + + void set_quality_of_service_measurements( + _In_ std::shared_ptr> measurements + ); + + void resubmit_matchmaking( + _In_ std::shared_ptr session + ); + + void handle_find_match_completed( + _In_ std::error_code errorCode, + _In_ std::string errorMessage + ); + + void disable_next_timer(bool value); + + bool m_disableNextTimer; + +private: + void check_next_timer(); + void process_ticket_response(); + void handle_session_joined(); + void get_latest_session(); + + void handle_qos_measurements(); + + void handle_match_found( + _In_ std::shared_ptr currentSession + ); + + pplx::task>> + join_session_helper( + _In_ std::shared_ptr session + ); + + xbox::services::system::xbox_live_mutex m_lock; + xbox::services::system::xbox_live_mutex m_getSessionLock; + utility::datetime m_nextTimerToFetchSession; + string_t m_hopperName; + web::json::value m_attributes; + std::chrono::seconds m_timeout; + bool m_preservingMatchmakingSession; + std::atomic m_matchStatus; + mutable std::mutex m_multiplayerEventQueueLock; + std::vector m_multiplayerEventQueue; + xbox::services::matchmaking::create_match_ticket_response m_matchTicketResponse; + xbox::services::multiplayer::multiplayer_session_reference m_matchTicketSessionRef; + std::shared_ptr m_matchSession; + std::shared_ptr m_multiplayerLocalUserManager; + + pplx::task m_getSessionTask; + pplx::task>> m_joinTargetSessionTask; +}; + +class multiplayer_manager_utils +{ +public: + + static bool do_sessions_match( + _In_ const std::shared_ptr& session1, + _In_ const std::shared_ptr& session2 + ); + + static bool do_session_references_match( + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef1, + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef2 + ) + { + return utils::str_icmp(sessionRef1.service_configuration_id(), sessionRef2.service_configuration_id()) == 0 && + utils::str_icmp(sessionRef1.session_template_name(), sessionRef2.session_template_name()) == 0 && + utils::str_icmp(sessionRef1.session_name(), sessionRef2.session_name()) == 0; + } + + static bool is_multiplayer_session_change_type( + _In_ xbox::services::multiplayer::multiplayer_session_change_types diffType, + _In_ xbox::services::multiplayer::multiplayer_session_change_types value + ) + { + return (diffType & value) == value; + } + + static bool is_player_in_session( + _In_ const string_t& xboxUserId, + _In_ const std::shared_ptr& session + ); + + static std::shared_ptr get_player_in_session( + _In_ const string_t& xboxUserId, + _In_ const std::shared_ptr& session + ); + + static bool is_host(_In_ const string_t& xboxUserId, + _In_ const std::shared_ptr& session + ); + + static std::shared_ptr host_member( + _In_ const std::shared_ptr& session + ); + + static string_t get_local_user_xbox_user_id( + _In_ xbox_live_user_t user + ); + + static bool has_session_property_changed( + _In_ const std::shared_ptr& currentSession, + _In_ const std::shared_ptr& oldSession, + _In_ const string_t& propertyName + ); + + static bool is_local( + _In_ const string_t& xboxUserId, + _In_ const std::map>& xboxLiveContextMap + ); + + static std::shared_ptr convert_to_game_member( + _In_ const std::shared_ptr& member, + _In_ const std::shared_ptr& lobbySession, + _In_ const std::shared_ptr& gameSession, + _In_ const std::map>& xboxLiveContextMap + ); + + static std::shared_ptr convert_to_game_member( + _In_ const std::shared_ptr& member, + _In_ const std::shared_ptr& lobbySession, + _In_ const std::shared_ptr& gameSession, + _In_ bool isLocal + ); + + static bool compare_sessions( + _In_ const std::shared_ptr& session1, + _In_ const std::shared_ptr& session2 + ); + + static void set_joinability( + _In_ xbox::services::multiplayer::manager::joinability value, + _In_ std::shared_ptr sessionToCommit, + _In_ bool isGameInProgress + ); + + static xbox::services::multiplayer::manager::joinability get_joinability( + _In_ std::shared_ptr sessionProperties + ); + + static xbox::services::multiplayer::manager::joinability convert_string_to_joinability( + _In_ const string_t& value + ); + + static string_t convert_joinability_to_string(_In_ xbox::services::multiplayer::manager::joinability value); +}; + +}}}} diff --git a/Source/Services/Multiplayer/Manager/multiplayer_manager_utils.cpp b/Source/Services/Multiplayer/Manager/multiplayer_manager_utils.cpp new file mode 100644 index 00000000..260eeda4 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_manager_utils.cpp @@ -0,0 +1,324 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +bool +multiplayer_manager_utils::do_sessions_match( + _In_ const std::shared_ptr& session1, + _In_ const std::shared_ptr& session2 + ) +{ + if (session1 == nullptr || session2 == nullptr) + { + return false; + } + + return do_session_references_match(session1->session_reference(), session2->session_reference()); +} + +bool +multiplayer_manager_utils::is_host( + _In_ const string_t& memberDeviceToken, + _In_ const std::shared_ptr& session + ) +{ + if(memberDeviceToken.empty() || session == nullptr || session->session_properties() == nullptr) + { + return false; + } + + return utils::str_icmp(memberDeviceToken, session->session_properties()->host_device_token()) == 0; +} + +bool +multiplayer_manager_utils::is_player_in_session( + _In_ const string_t& xboxUserId, + _In_ const std::shared_ptr& session + ) +{ + if(xboxUserId.empty() || session == nullptr) + { + return false; + } + + for (const auto& member : session->members()) + { + if (utils::str_icmp(xboxUserId, member->xbox_user_id()) == 0) + { + return true; + } + } + + return false; +} + +std::shared_ptr + multiplayer_manager_utils::get_player_in_session( + _In_ const string_t& xboxUserId, + _In_ const std::shared_ptr& session + ) +{ + if(xboxUserId.empty()) return nullptr; + + if(session == nullptr) + { + return nullptr; + } + + for (const auto& member : session->members()) + { + if (utils::str_icmp(xboxUserId, member->xbox_user_id()) == 0) + { + return member; + } + } + + return nullptr; +} + +std::shared_ptr +multiplayer_manager_utils::host_member( + _In_ const std::shared_ptr& session + ) +{ + if(session == nullptr || session->session_properties() == nullptr) + { + return nullptr; + } + + for (const auto& member : session->members()) + { + if (utils::str_icmp(member->device_token(), session->session_properties()->host_device_token() ) == 0) + { + return member; + } + } + + return nullptr; +} + +string_t +multiplayer_manager_utils::get_local_user_xbox_user_id( + _In_ xbox_live_user_t user + ) +{ + if (user == nullptr) + { + return string_t(); + } + + return user_context::get_user_id(user); +} + +bool +multiplayer_manager_utils::has_session_property_changed( + _In_ const std::shared_ptr& session1, + _In_ const std::shared_ptr& session2, + _In_ const string_t& propertyName + ) +{ + if (session1 == nullptr && session2 == nullptr) + { + return true; + } + + if (session1 == nullptr || session2 == nullptr) + { + return false; + } + + const auto& customProp1 = session1->session_properties()->session_custom_properties_json(); + const auto& customProp2 = session2->session_properties()->session_custom_properties_json(); + if ( (customProp1.has_field(propertyName) && !customProp2.has_field(propertyName)) || + (!customProp1.has_field(propertyName) && customProp2.has_field(propertyName))) + { + return true; + } + + if (customProp1.has_field(propertyName) && customProp2.has_field(propertyName)) + { + const auto& prop1 = customProp1.at(propertyName).as_string(); + const auto& prop2 = customProp2.at(propertyName).as_string(); + return utils::str_icmp(prop1, prop2) != 0; + } + + return false; +} + +bool +multiplayer_manager_utils::is_local( + _In_ const string_t& xboxUserId, + _In_ const std::map>& xboxLiveContextMap + ) +{ + if(xboxUserId.empty()) return false; + + for(const auto& xboxLiveContext : xboxLiveContextMap) + { + const auto& localUser = xboxLiveContext.second; + if (localUser != nullptr && utils::str_icmp(xboxUserId, localUser->xbox_user_id()) == 0) + { + return true; + } + } + + return false; +} + +std::shared_ptr +multiplayer_manager_utils::convert_to_game_member( + _In_ const std::shared_ptr& member, + _In_ const std::shared_ptr& lobbySession, + _In_ const std::shared_ptr& gameSession, + _In_ const std::map>& xboxLiveContextMap + ) +{ + return std::make_shared( + member, + is_local(member->xbox_user_id(), xboxLiveContextMap), // isLocal + is_host(member->device_token(), gameSession), // isGameHost + is_host(member->device_token(), lobbySession), // isLobbyHost + is_player_in_session(member->xbox_user_id(), lobbySession), // isinLobby + is_player_in_session(member->xbox_user_id(), gameSession) // isinGame + ); +} + +std::shared_ptr +multiplayer_manager_utils::convert_to_game_member( + _In_ const std::shared_ptr& member, + _In_ const std::shared_ptr& lobbySession, + _In_ const std::shared_ptr& gameSession, + _In_ bool isLocal + ) +{ + return std::make_shared( + member, + isLocal, // isLocal + is_host(member->device_token(), gameSession), // isGameHost + is_host(member->device_token(), lobbySession), // isLobbyHost + is_player_in_session(member->xbox_user_id(), lobbySession), // isinLobby + is_player_in_session(member->xbox_user_id(), gameSession) // isinGame + ); +} + +bool +multiplayer_manager_utils::compare_sessions( + _In_ const std::shared_ptr& session1, + _In_ const std::shared_ptr& session2 + ) +{ + if (session1 == nullptr && session2 == nullptr) + { + return true; + } + + if ( (session1 == nullptr && session2 != nullptr) || + (session1 != nullptr && session2 == nullptr) || + session1->change_number() != session2->change_number()) + { + return false; + } + + return true; +} + + +// joinable_by_friends : !closed & JoinRestricion::Followed +// invite_only : !closed & JoinRestricion::Local +// disable_while_game_in_progress : closed & JoinRestricion::Local (when in game) +// closed : closed & JoinRestricion::Local + +void +multiplayer_manager_utils::set_joinability( + _In_ joinability value, + _In_ std::shared_ptr sessionToCommit, + _In_ bool isGameInProgress + ) +{ + sessionToCommit->set_closed(false); + sessionToCommit->session_properties()->set_join_restriction(multiplayer_session_restriction::local); + if (value == joinability::joinable_by_friends) + { + sessionToCommit->session_properties()->set_join_restriction(multiplayer_session_restriction::followed); + } + else if (value == joinability::closed || + (isGameInProgress && value == joinability::disable_while_game_in_progress)) + { + sessionToCommit->set_closed(true); + } + + string_t jsonValueStr = convert_joinability_to_string(value); + sessionToCommit->set_session_custom_property_json(multiplayer_lobby_client::c_joinabilityPropertyName, web::json::value::string(jsonValueStr)); +} + +joinability +multiplayer_manager_utils::get_joinability( + _In_ std::shared_ptr sessionProperties + ) +{ + string_t joinableStr; + auto customPropertiesjson = sessionProperties->session_custom_properties_json(); + if (customPropertiesjson.has_field(multiplayer_lobby_client::c_joinabilityPropertyName)) + { + joinableStr = customPropertiesjson.at(multiplayer_lobby_client::c_joinabilityPropertyName).as_string(); + } + + return convert_string_to_joinability(joinableStr); +} + +joinability +multiplayer_manager_utils::convert_string_to_joinability( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("joinable_by_friends")) == 0) + { + return joinability::joinable_by_friends; + } + else if (utils::str_icmp(value, _T("invite_only")) == 0) + { + return joinability::invite_only; + } + else if (utils::str_icmp(value, _T("disable_while_game_in_progress")) == 0) + { + return joinability::disable_while_game_in_progress; + } + else if (utils::str_icmp(value, _T("closed")) == 0) + { + return joinability::closed; + } + + return joinability::none; +} + +string_t +multiplayer_manager_utils::convert_joinability_to_string( + _In_ joinability value + ) +{ + switch (value) + { + case xbox::services::multiplayer::manager::joinability::joinable_by_friends: return _T("joinable_by_friends"); + case xbox::services::multiplayer::manager::joinability::invite_only: return _T("invite_only"); + case xbox::services::multiplayer::manager::joinability::disable_while_game_in_progress: return _T("disable_while_game_in_progress"); + case xbox::services::multiplayer::manager::joinability::closed: return _T("closed"); + default: return _T("none"); + } +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_match_client.cpp b/Source/Services/Multiplayer/Manager/multiplayer_match_client.cpp new file mode 100644 index 00000000..a5230742 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_match_client.cpp @@ -0,0 +1,725 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include +#include "pplx/pplxtasks.h" +#include "multiplayer_manager_internal.h" +#include "xsapi/services.h" +#include "user_context.h" + +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace xbox::services::matchmaking; +using namespace xbox::services::real_time_activity; +using namespace pplx; +#if TV_API +using namespace Windows::Xbox::Networking; +#endif + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_match_client::multiplayer_match_client( + _In_ std::shared_ptr localUserManager + ) : + m_multiplayerLocalUserManager(localUserManager), + m_matchStatus(match_status::none), + m_disableNextTimer(false), + m_preservingMatchmakingSession(false) +{ + m_getSessionTask = pplx::create_task([]{}); +} + +void +multiplayer_match_client::deep_copy_if_updated( + _In_ const multiplayer_match_client& other + ) +{ + std::lock_guard lock(m_lock.get()); + if (other.m_matchSession == nullptr) + { + m_matchSession = nullptr; + } + else if (m_matchSession == nullptr || other.m_matchSession->change_number() > m_matchSession->change_number()) + { + m_matchSession = other.m_matchSession->_Create_deep_copy(); + } +} + +const std::vector& +multiplayer_match_client::multiplayer_event_queue() +{ + return m_multiplayerEventQueue; +} + +std::vector +multiplayer_match_client::do_work() +{ + switch (static_cast(m_matchStatus)) + { + case match_status::none: + { + return std::vector(); + } + + case match_status::searching: + { + check_next_timer(); + break; + } + + case match_status::found: + case match_status::canceled: + { + // Nothing to do here. Wait for match_status_changed event. + break; + } + + case match_status::joining: + { + if(m_joinTargetSessionTask.is_done()) + { + handle_session_joined(); + } + break; + } + + case match_status::waiting_for_remote_clients_to_join: + case match_status::waiting_for_remote_clients_to_upload_qos: + { + handle_initialization_state_changed(session()); + break; + } + + case match_status::measuring: + { + // Waiting for title to perform qos and provide qos measurements (via set_quality_of_service_measurements) + handle_initialization_state_changed(session()); + break; + } + + case match_status::evaluating: + { + // Nothing to do here. Wait for initialization stage changed event. + break; + } + } + + std::vector eventQueue; + { + std::lock_guard lock(m_multiplayerEventQueueLock); + eventQueue = m_multiplayerEventQueue; + m_multiplayerEventQueue.clear(); + } + + return eventQueue; +} + +void +multiplayer_match_client::disable_next_timer(bool value) +{ + m_disableNextTimer = value; +} + +void +multiplayer_match_client::check_next_timer() +{ + if (m_disableNextTimer) return; // Only used for Unit tests + + int64_t delta = m_nextTimerToFetchSession.to_interval() - utility::datetime::utc_now().to_interval(); + if ( delta < 0) + { + if (m_matchStatus == match_status::searching) + { + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr) return; + if (!m_getSessionTask.is_done()) return; + + // Fetch ticket session + std::weak_ptr thisWeakPtr = shared_from_this(); + m_getSessionTask = primaryContext->multiplayer_service().get_current_session(m_matchTicketSessionRef) + .then([thisWeakPtr](xbox_live_result> sessionResult) + { + if (!sessionResult.err()) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->handle_match_status_changed(sessionResult.payload()); + } + } + }); + } + else + { + get_latest_session(); + } + } +} + +void +multiplayer_match_client::handle_qos_measurements() +{ + std::map addressDeviceTokenMap; + for (const auto& member : session()->members()) + { + if (!member->is_current_user()) + { + std::vector base64ConnectionAddress(utility::conversions::from_base64(std::move(member->secure_device_base_address64()))); + const string_t& secureDeviceAddress = string_t(base64ConnectionAddress.begin(), base64ConnectionAddress.end()); + if (!secureDeviceAddress.empty()) + { + addressDeviceTokenMap[secureDeviceAddress] = member->device_token(); + } + } + } + + if (addressDeviceTokenMap.size() > 0) + { + m_matchStatus = match_status::measuring; + + std::shared_ptr performQosEventArgs = std::make_shared(addressDeviceTokenMap); + multiplayer_event multiplayerEvent( + xbox_live_error_code::no_error, + std::string(), + multiplayer_event_type::perform_qos_measurements, + std::dynamic_pointer_cast(performQosEventArgs), + multiplayer_session_type::game_session + ); + + std::lock_guard lock(m_multiplayerEventQueueLock); + m_multiplayerEventQueue.push_back(multiplayerEvent); + } + else + { + // If clients fail to join, the stage advances to "measuring". + // Wait until memberInitialization either succeeds or fails. + check_next_timer(); + } +} + +void +multiplayer_match_client::handle_find_match_completed( + _In_ std::error_code errorCode, + _In_ std::string errorMessage + ) +{ + multiplayer_measurement_failure failure = multiplayer_measurement_failure::unknown; + + auto matchSession = session(); + if (matchSession != nullptr && matchSession->current_user() != nullptr) + { + failure = matchSession->current_user()->initialization_failure_cause(); + } + + std::shared_ptr findMatchEventArgs = std::make_shared( + m_matchStatus, + failure + ); + + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + multiplayer_event_type::find_match_completed, + std::dynamic_pointer_cast(findMatchEventArgs), + multiplayer_session_type::game_session + ); + + std::lock_guard lock(m_multiplayerEventQueueLock); + m_multiplayerEventQueue.push_back(multiplayerEvent); +} + +void +multiplayer_match_client::handle_match_status_changed( + _In_ std::shared_ptr matchSession + ) +{ + matchmaking_status status = matchSession->matchmaking_server().status(); + switch (status) + { + case matchmaking_status::searching: + { + xbox::services::multiplayer::manager::match_status expected = match_status::none; + if (m_matchStatus.compare_exchange_strong(expected, match_status::searching, std::memory_order_release)) + { + // Wait for status to change on ticket session or fetch after 2 mins. + m_nextTimerToFetchSession = utility::datetime::utc_now() + utility::datetime::from_seconds(120); + } + else + { + if (m_disableNextTimer) return; // Only used for Unit tests + + int64_t delta = m_nextTimerToFetchSession.to_interval() - utility::datetime::utc_now().to_interval(); + if ( delta < 0) + { + // Delete the match ticket and let the title know that it failed. + if (!m_hopperName.empty() && !m_matchTicketResponse.match_ticket_id().empty()) + { + // Only the host has the ticketId info. Since we aren't the host who started the match, we cannot cancel it either. + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr) return; + + primaryContext->matchmaking_service().delete_match_ticket( + xbox::services::xbox_live_app_config::get_app_config_singleton()->scid(), + m_hopperName, + m_matchTicketResponse.match_ticket_id() + ); + } + + m_matchStatus = match_status::failed; + handle_find_match_completed(xbox_live_error_code::generic_error, "Matchmaking request failed."); + } + } + break; + } + case matchmaking_status::expired: + { + m_matchStatus = match_status::expired; + handle_find_match_completed(xbox_live_error_code::generic_error, "Matchmaking request expired."); + break; + } + case matchmaking_status::canceled: + { + m_matchStatus = match_status::canceled; + handle_find_match_completed(xbox_live_error_code::generic_error, "Matchmaking request was canceled."); + break; + } + case matchmaking_status::found: + { + handle_match_found(matchSession); + break; + } + default: + break; + } +} + +void +multiplayer_match_client::handle_initialization_state_changed( + _In_ std::shared_ptr matchSession + ) +{ + update_session(matchSession); + if (matchSession->intializing_episode() > 0) + { + switch (matchSession->initialization_stage()) + { + case multiplayer_initialization_stage::joining: + { + check_next_timer(); + break; + } + + case multiplayer_initialization_stage::measuring: + { + if (m_matchStatus == match_status::waiting_for_remote_clients_to_upload_qos || + m_matchStatus == match_status::measuring) + { + check_next_timer(); + } + else if (m_matchStatus == match_status::waiting_for_remote_clients_to_join) + { + handle_qos_measurements(); + } + break; + } + + case multiplayer_initialization_stage::failed: + { + m_matchStatus = match_status::failed; + handle_find_match_completed(xbox_live_error_code::generic_error, "multiplayer_initialization_stage failed"); + return; + } + } + } + else + { + if (matchSession->current_user()->initialization_failure_cause() == multiplayer_measurement_failure::none) + { + // QoS succeeded. + m_matchStatus = match_status::completed; + handle_find_match_completed(xbox_live_error_code::no_error, std::string()); + } + else + { + // Resubmit + m_matchStatus = match_status::resubmitting; + handle_find_match_completed(xbox_live_error_code::generic_error, "multiplayer_initialization_stage failed"); + } + } +} + +xbox_live_result +multiplayer_match_client::find_match( + _In_ std::shared_ptr session, + _In_ bool preserveSession + ) +{ + return find_match(m_hopperName, m_attributes, m_timeout, session, preserveSession); +} + +xbox_live_result +multiplayer_match_client::find_match( + _In_ const string_t& hopperName, + _In_ const web::json::value& attributes, + _In_ const std::chrono::seconds& timeout, + _In_ std::shared_ptr session, + _In_ bool preserveSession + ) +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if( primaryContext == nullptr || session == nullptr) + { + return xbox_live_result(xbox_live_error_code::logic_error, "No local user added. Call add_local_user() first."); + } + + xbox::services::multiplayer::manager::match_status expected = match_status::none; + if (!m_matchStatus.compare_exchange_strong(expected, match_status::submitting_match_ticket, std::memory_order_release)) + { + return xbox_live_result(xbox_live_error_code::logic_error, "Match search already in progress."); + } + + if (preserveSession) + { + update_session(session); + } + else + { + update_session(nullptr); + } + + m_hopperName = hopperName; + m_attributes = attributes; + m_timeout = timeout; + m_preservingMatchmakingSession = preserveSession; + m_matchTicketSessionRef = session->session_reference(); + + std::weak_ptr thisWeakPtr = shared_from_this(); + primaryContext->matchmaking_service().create_match_ticket( + session->session_reference(), + session->session_reference().service_configuration_id(), + hopperName, + timeout, + preserveSession ? preserve_session_mode::always : preserve_session_mode::never, + attributes + ) + .then([thisWeakPtr, timeout](xbox_live_result result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + if (!result.err()) + { + pThis->m_matchTicketResponse = result.payload(); + pThis->m_matchStatus = match_status::searching; + pThis->m_nextTimerToFetchSession = utility::datetime::utc_now() + + utility::datetime::from_seconds(static_cast(timeout.count())) + + utility::datetime::from_seconds(5); // some extra delay to be safe + } + else + { + pThis->m_matchStatus = match_status::failed; + pThis->handle_find_match_completed(result.err(), result.err_message()); + } + } + }); + + return xbox_live_result(); +} + +void +multiplayer_match_client::cancel_match() +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr) + { + return; + } + + if (m_matchStatus == match_status::none || m_matchStatus == match_status::expired || + m_matchStatus == match_status::canceled || m_matchStatus == match_status::failed) + { + return; + } + + if (m_hopperName.empty() || m_matchTicketResponse.match_ticket_id().empty()) + { + // Since we aren't the host who started the match, we cannot cancel it either. + return; + } + + m_matchStatus = match_status::canceling; + primaryContext->matchmaking_service().delete_match_ticket( + xbox::services::xbox_live_app_config::get_app_config_singleton()->scid(), + m_hopperName, + m_matchTicketResponse.match_ticket_id() + ); +} + +xbox::services::multiplayer::manager::match_status +multiplayer_match_client::match_status() const +{ + return m_matchStatus; +} + +void +multiplayer_match_client::set_match_status( + _In_ xbox::services::multiplayer::manager::match_status status + ) +{ + m_matchStatus = status; +} + +std::chrono::seconds +multiplayer_match_client::estimated_match_wait_time() const +{ + return m_matchTicketResponse.estimated_wait_time(); +} + +void +multiplayer_match_client::on_session_changed( + _In_ const multiplayer_session_change_event_args& args + ) +{ + auto matchSession = session(); + if (matchSession != nullptr && + multiplayer_manager_utils::do_session_references_match(matchSession->session_reference(), args.session_reference()) && + args.change_number() > matchSession->change_number()) + { + get_latest_session(); + } +} + +void +multiplayer_match_client::update_session( + _In_ std::shared_ptr session + ) +{ + std::lock_guard lock(m_lock.get()); + + if (m_matchSession == nullptr || session == nullptr) + { + m_matchSession = session; + } + else if(multiplayer_manager_utils::do_sessions_match(m_matchSession, session) && + session->change_number() > m_matchSession->change_number()) + { + m_matchSession = session; + m_nextTimerToFetchSession = utility::datetime::utc_now() + utility::datetime::from_seconds(session->date_of_next_timer() - session->date_of_session()); + } +} + +std::shared_ptr +multiplayer_match_client::session() +{ + std::lock_guard lock(m_lock.get()); + return m_matchSession; +} + +void +multiplayer_match_client::handle_session_joined() +{ + auto result = m_joinTargetSessionTask.get(); + if (result.err()) + { + m_matchStatus = match_status::failed; + handle_find_match_completed(result.err(), result.err_message()); + return; + } + + if (session()->intializing_episode() == 0) + { + m_matchStatus = match_status::completed; + handle_find_match_completed(xbox_live_error_code::no_error, std::string()); + } + else + { + m_matchStatus = match_status::waiting_for_remote_clients_to_join; + } +} + +void +multiplayer_match_client::handle_match_found( + _In_ std::shared_ptr currentSession + ) +{ + std::shared_ptr primaryXboxLiveContext = m_multiplayerLocalUserManager->get_primary_context(); + if(primaryXboxLiveContext == nullptr) + { + m_matchStatus = match_status::failed; + handle_find_match_completed(xbox_live_error_code::runtime_error, "No primary xbox live context."); + return; + } + + m_matchStatus = match_status::found; + auto targetSessionRef = currentSession->matchmaking_server().target_session_ref(); + auto targetGameSession = std::make_shared( + primaryXboxLiveContext->xbox_live_user_id(), + targetSessionRef + ); + + auto gameClient = multiplayer_manager::get_singleton_instance()->_Game_client(); + if (m_preservingMatchmakingSession && gameClient != nullptr) + { + auto gameSession = gameClient->session(); + if (gameSession != nullptr && + multiplayer_manager_utils::do_session_references_match(gameSession->session_reference(), targetSessionRef)) + { + targetGameSession = gameSession; + } + } + + update_session(targetGameSession); + m_joinTargetSessionTask = join_session_helper(targetGameSession); +} + +pplx::task>> +multiplayer_match_client::join_session_helper( + _In_ std::shared_ptr session + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = pplx::create_task([thisWeakPtr, session]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "matchmaking_client_manager class was destroyed."); + + xbox_live_result> multiplayerSessionResult; + pThis->m_matchStatus = match_status::joining; + if (pThis->m_preservingMatchmakingSession) + { + // Matchmaking session was preserved so we're already part of it + return xbox_live_result>(session); + } + + auto xboxLiveContextMap = pThis->m_multiplayerLocalUserManager->get_local_user_map(); + for(auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr) + { + auto updatedSession = std::make_shared(localUser->xbox_user_id(), session->session_reference()); + updatedSession->join(); + updatedSession->set_current_user_secure_device_address_base64(localUser->connection_address()); + updatedSession->set_session_change_subscription(multiplayer_session_change_types::everything); + auto writeSessionResult = localUser->context()->multiplayer_service().write_session(updatedSession, multiplayer_session_write_mode::update_or_create_new).get(); + if (writeSessionResult.err()) + { + return writeSessionResult; + } + + multiplayerSessionResult = writeSessionResult; + } + } + + auto matchSession = multiplayerSessionResult.payload(); + pThis->update_session(matchSession); + return multiplayerSessionResult; + }); + + return utils::create_exception_free_task>(task); +} + +void +multiplayer_match_client::get_latest_session() +{ + std::lock_guard lock(m_getSessionLock.get()); + if (session() == nullptr) return; + + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr) return; + if (!m_getSessionTask.is_done()) return; + + std::weak_ptr thisWeakPtr = shared_from_this(); + m_getSessionTask = primaryContext->multiplayer_service().get_current_session(session()->session_reference()) + .then([thisWeakPtr](xbox_live_result> sessionResult) + { + if (!sessionResult.err()) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->update_session(sessionResult.payload()); + } + } + }); +} + +void +multiplayer_match_client::set_quality_of_service_measurements( + _In_ std::shared_ptr> measurements + ) +{ + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + auto matchSession = session(); + if (primaryContext == nullptr || matchSession == nullptr) return; + + auto matchSessionRef = matchSession->session_reference(); + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = pplx::create_task([thisWeakPtr, matchSessionRef, measurements]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis == nullptr) return; + + pThis->m_matchStatus = match_status::uploading_qos_measurements; + + xbox_live_result> matchSessionResult; + auto xboxLiveContextMap = pThis->m_multiplayerLocalUserManager->get_local_user_map(); + for (auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr) + { + auto matchSession = std::make_shared(localUser->xbox_user_id(), matchSessionRef); + matchSession->join(); + matchSession->set_current_user_quality_of_service_measurements(measurements); + matchSessionResult = localUser->context()->multiplayer_service().write_session(matchSession, multiplayer_session_write_mode::update_existing).get(); + if (matchSessionResult.err()) + { + break; + } + } + } + + pThis->update_session(matchSessionResult.payload()); + pThis->m_matchStatus = match_status::waiting_for_remote_clients_to_upload_qos; + }); +} + +void +multiplayer_match_client::resubmit_matchmaking( + _In_ std::shared_ptr session + ) +{ + if (session == nullptr) return; + + std::shared_ptr primaryContext = m_multiplayerLocalUserManager->get_primary_context(); + if (primaryContext == nullptr) return; + + m_matchStatus = match_status::resubmitting; + session->set_matchmaking_resubmit(true); + std::weak_ptr thisWeakPtr = shared_from_this(); + primaryContext->multiplayer_service().write_session(session, multiplayer_session_write_mode::update_existing) + .then([thisWeakPtr](xbox_live_result> sessionResult) + { + if (sessionResult.err()) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->m_matchStatus = match_status::failed; + pThis->handle_find_match_completed(sessionResult.err(), sessionResult.err_message()); + } + } + }); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_member.cpp b/Source/Services/Multiplayer/Manager/multiplayer_member.cpp new file mode 100644 index 00000000..c7ea2fea --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_member.cpp @@ -0,0 +1,133 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +multiplayer_member::multiplayer_member() : + m_isLocal(false), + m_isGameHost(false), + m_isLobbyHost(false), + m_isInLobby(false), + m_isInGame(false), + m_status(multiplayer_session_member_status::inactive) +{ +} + +multiplayer_member::multiplayer_member( + _In_ std::shared_ptr member, + _In_ bool isLocal, + _In_ bool isGameHost, + _In_ bool isLobbyHost, + _In_ bool isInLobby, + _In_ bool isInGame + ): + m_memberId(member->member_id()), + m_teamId(member->team_id()), + m_xboxUserid(std::move(member->xbox_user_id())), + m_gamertag(std::move(member->gamertag())), + m_deviceToken(std::move(member->device_token())), + m_isLocal(isLocal), + m_isGameHost(isGameHost), + m_isLobbyHost(isLobbyHost), + m_isInLobby(isInLobby), + m_isInGame(isInGame), + m_status(member->status()), + m_jsonProperties(std::move(member->member_custom_properties_json())) +{ + std::vector base64ConnectionAddress(utility::conversions::from_base64(std::move(member->secure_device_base_address64()))); + m_connectionAddress = string_t(base64ConnectionAddress.begin(), base64ConnectionAddress.end()); +} + +uint32_t +multiplayer_member::member_id() const +{ + return m_memberId; +} + +const string_t& +multiplayer_member::team_id() const +{ + return m_teamId; +} + +const string_t& +multiplayer_member::xbox_user_id() const +{ + return m_xboxUserid; +} + +const string_t& +multiplayer_member::debug_gamertag() const +{ + return m_gamertag; +} + +const string_t& +multiplayer_member::_Device_token() const +{ + return m_deviceToken; +} + +bool +multiplayer_member::is_local() const +{ + return m_isLocal; +} + +bool +multiplayer_member::is_in_lobby() const +{ + return m_isInLobby; +} + +bool +multiplayer_member::is_in_game() const +{ + return m_isInGame; +} + +multiplayer_session_member_status +multiplayer_member::status() const +{ + return m_status; +} + +const string_t& +multiplayer_member::connection_address() const +{ + return m_connectionAddress; +} + +const web::json::value& +multiplayer_member::properties() const +{ + return m_jsonProperties; +} + +bool +multiplayer_member::is_member_on_same_device( + _In_ std::shared_ptr member + ) const +{ + if(member == nullptr) + { + return false; + } + + return utils::str_icmp(m_deviceToken, member->_Device_token()) == 0; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/multiplayer_session_writer.cpp b/Source/Services/Multiplayer/Manager/multiplayer_session_writer.cpp new file mode 100644 index 00000000..e09713a9 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/multiplayer_session_writer.cpp @@ -0,0 +1,565 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "multiplayer_manager_internal.h" +#if !XSAPI_U +#include "ppltasks_extra.h" +using namespace Concurrency::extras; +#endif + +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +const std::chrono::milliseconds TIME_PER_CALL_MS = +#if UNIT_TEST_SERVICES +std::chrono::milliseconds(1 * 1000); +#else +std::chrono::milliseconds(30 * 1000); +#endif + +multiplayer_session_writer::multiplayer_session_writer() : + m_isTapReceived(false), + m_numOfWritesInProgress(0), + m_tapChangeNumber(0), + m_sessionUpdateEventHandlerCounter(0), + m_handleResyncEventCounter(0), + m_isTaskInProgress(false) +{ +} + +multiplayer_session_writer::multiplayer_session_writer( + _In_ std::shared_ptr localUserManager + ) : + m_multiplayerLocalUserManager(localUserManager), + m_isTapReceived(false), + m_numOfWritesInProgress(0), + m_tapChangeNumber(0), + m_sessionUpdateEventHandlerCounter(0), + m_handleResyncEventCounter(0), + m_isTaskInProgress(false) +{ +} + +void +multiplayer_session_writer::destroy() +{ + m_session = nullptr; + m_isTapReceived = false; + m_numOfWritesInProgress = 0; + m_tapChangeNumber = 0; +} + +std::shared_ptr +multiplayer_session_writer::get_primary_context() +{ + return m_multiplayerLocalUserManager->get_primary_context(); +} + +const std::shared_ptr& +multiplayer_session_writer::session() const +{ + return m_session; +} + +void +multiplayer_session_writer::update_session( + _In_ const std::shared_ptr& updatedSession + ) +{ + if (updatedSession == nullptr) + { + destroy(); + } + else + { + m_session = updatedSession; + } +} + +function_context +multiplayer_session_writer::add_multiplayer_session_updated_handler( + _In_ std::function& )> handler + ) +{ + std::lock_guard lock(m_stateLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_sessionUpdateEventHandlerCounter; + m_sessionUpdateEventHandler[m_sessionUpdateEventHandlerCounter] = std::move(handler); + } + + return context; +} + +void +multiplayer_session_writer::on_resync_message_received() +{ + m_handleResyncEventCounter++; + resync(); +} + +void +multiplayer_session_writer::on_session_updated( + _In_ const std::shared_ptr& updatedSession + ) +{ + std::lock_guard lock(m_stateLock.get()); + + for (const auto& handler : m_sessionUpdateEventHandler) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(updatedSession); + } + catch (...) + { + LOG_ERROR("multiplayer_session_writer::on_session_updated call threw an exception"); + } + } + } +} + +bool +multiplayer_session_writer::is_tap_received() const +{ + return m_isTapReceived; +} + +void +multiplayer_session_writer::set_tap_received( + _In_ bool bReceived + ) +{ + m_isTapReceived = bReceived; +} + +bool +multiplayer_session_writer::is_write_in_progress() const +{ + return m_numOfWritesInProgress > 0; +} + +void +multiplayer_session_writer::set_write_in_progress( + _In_ bool writeInProgress + ) +{ + if (writeInProgress) + { + m_numOfWritesInProgress++; + } + else + { + m_numOfWritesInProgress--; + } +} + +uint64_t +multiplayer_session_writer::tap_change_number() const +{ + return m_tapChangeNumber; +} + +void +multiplayer_session_writer::set_tap_change_number( + _In_ uint64_t changeNumber + ) +{ + m_tapChangeNumber = changeNumber; +} + +pplx::task> +multiplayer_session_writer::commit_synchronized_changes( + _In_ std::shared_ptr sessionToCommit + ) +{ + // Retrieve the latest session and write the pending commit changes to it. + auto task = write_session(m_multiplayerLocalUserManager->get_primary_context(), sessionToCommit, multiplayer_session_write_mode::synchronized_update) + .then([](xbox_live_result> sessionResult) + { + return xbox_live_result(sessionResult.err(), sessionResult.err_message()); + }); + + return utils::create_exception_free_task(task); +} + +pplx::task>> +multiplayer_session_writer::commit_pending_synchronized_changes( + _In_ std::vector> processingQueue, + _In_ multiplayer_session_type sessionType + ) +{ + if (m_session == nullptr) + { + auto eventQueue = handle_events(processingQueue, xbox_live_error_code::generic_error, "Session no longer exists.", sessionType); + return pplx::task_from_result(xbox_live_result>(eventQueue, xbox_live_error_code::generic_error, "Session no longer exists.")); + } + + const auto& sessionToCommitCopy = m_session->_Create_deep_copy(); + + // Update any pending local user or lobby session properties. + for (auto& request : processingQueue) + { + request->append_pending_changes(sessionToCommitCopy, nullptr); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = write_session(get_primary_context(), sessionToCommitCopy, multiplayer_session_write_mode::synchronized_update) + .then([thisWeakPtr, processingQueue, sessionType](xbox_live_result> sessionResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + std::vector eventQueue; + if (pThis != nullptr) + { + std::lock_guard lock(pThis->m_stateLock.get()); + eventQueue = pThis->handle_events(processingQueue, sessionResult.err(), sessionResult.err_message(), sessionType); + } + return xbox_live_result>(eventQueue, sessionResult.err(), sessionResult.err_message()); + }); + + return utils::create_exception_free_task>(task); +} + +pplx::task>> +multiplayer_session_writer::commit_pending_changes( + _In_ std::vector> processingQueue, + _In_ multiplayer_session_type sessionType, + _In_ bool isGameInProgress /*= false */ + ) +{ + if (m_session == nullptr) + { + auto eventQueue = handle_events(processingQueue, xbox_live_error_code::generic_error, "Session no longer exists.", sessionType); + return pplx::task_from_result(xbox_live_result>(eventQueue, xbox_live_error_code::generic_error, "Session no longer exists.")); + } + + std::shared_ptr sessionToCommit = m_session->_Create_deep_copy(); + + // Update any pending local user or lobby session properties. + for (auto& request : processingQueue) + { + request->append_pending_changes(sessionToCommit, nullptr, isGameInProgress); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = write_session(m_multiplayerLocalUserManager->get_primary_context(), sessionToCommit, multiplayer_session_write_mode::update_existing) + .then([thisWeakPtr, processingQueue, sessionType](xbox_live_result> sessionResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + std::vector eventQueue; + if (pThis != nullptr) + { + std::lock_guard lock(pThis->m_stateLock.get()); + eventQueue = pThis->handle_events(processingQueue, sessionResult.err(), sessionResult.err_message(), sessionType); + } + return xbox_live_result>(eventQueue, sessionResult.err(), sessionResult.err_message()); + }); + + return utils::create_exception_free_task>(task); +} + +pplx::task>> +multiplayer_session_writer::write_session( + _In_ std::shared_ptr xboxLiveContext, + _In_ std::shared_ptr session, + _In_ multiplayer_session_write_mode mode, + _In_ bool updateLatest + ) +{ + RETURN_TASK_CPP_IF(xboxLiveContext == nullptr, std::shared_ptr, "Call add_local_user() first."); + + set_write_in_progress(true); + std::weak_ptr thisWeakPtr = shared_from_this(); + return xboxLiveContext->multiplayer_service().write_session(session, mode) + .then([thisWeakPtr, updateLatest](xbox_live_result> sessionResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "multiplayer_session_writer class was destroyed."); + + return pThis->write_session_helper(sessionResult, updateLatest); + }); +} + +pplx::task>> +multiplayer_session_writer::write_session_by_handle( + _In_ std::shared_ptr xboxLiveContext, + _In_ std::shared_ptr session, + _In_ multiplayer_session_write_mode mode, + _In_ const string_t& handleId, + _In_ bool updateLatest + ) +{ + RETURN_TASK_CPP_IF(xboxLiveContext == nullptr, std::shared_ptr, "Call add_local_user() first."); + + set_write_in_progress(true); + std::weak_ptr thisWeakPtr = shared_from_this(); + return xboxLiveContext->multiplayer_service().write_session_by_handle(session, mode, handleId) + .then([thisWeakPtr, updateLatest](xbox_live_result> sessionResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "multiplayer_session_writer class was destroyed."); + + return pThis->write_session_helper(sessionResult, updateLatest); + }); +} + +xbox_live_result> +multiplayer_session_writer::write_session_helper( + _In_ xbox_live_result> sessionResult, + _In_ bool updateLatest + ) +{ + std::lock_guard guard(m_synchronizeWriteWithTapLock); + + xbox_live_result> xboxLiveResult = sessionResult; + if (!xboxLiveResult.err() || xboxLiveResult.err() == xbox_live_error_condition::http_412_precondition_failed) + { + auto latestSession = xboxLiveResult.payload(); + if (updateLatest) + { + on_session_updated(latestSession); + } + } + + set_write_in_progress(false); + if (is_tap_received()) + { + set_tap_received(false); + auto latestSession = session(); // always check against the latest session(). + if(updateLatest && latestSession != nullptr && latestSession->change_number() < tap_change_number()) + { + return get_current_session_helper(m_multiplayerLocalUserManager->get_primary_context(), latestSession->session_reference()).get(); + } + } + + return xboxLiveResult; +} + +void +multiplayer_session_writer::on_session_changed( + _In_ const multiplayer_session_change_event_args& args + ) +{ + std::lock_guard guard(m_synchronizeWriteWithTapLock); + + multiplayer_session_reference sessionRef = args.session_reference(); + uint64_t argsChangeNumber = args.change_number(); + if (is_write_in_progress()) + { + if (argsChangeNumber > tap_change_number()) + { + set_tap_received(true); + set_tap_change_number(argsChangeNumber); + } + } + else + { + auto latestSession = session(); + if(latestSession != nullptr && argsChangeNumber > latestSession->change_number()) + { + get_current_session_helper(m_multiplayerLocalUserManager->get_primary_context(), latestSession->session_reference()); + } + } +} + +pplx::task>> +multiplayer_session_writer::get_current_session_helper( + _In_ std::shared_ptr xboxLiveContext, + _In_ const multiplayer_session_reference& sessionReference + ) +{ + RETURN_TASK_CPP_IF(xboxLiveContext == nullptr, std::shared_ptr, "Call add_local_user() first."); + + std::weak_ptr thisWeakPtr = shared_from_this(); + return xboxLiveContext->multiplayer_service().get_current_session(sessionReference) + .then([thisWeakPtr, sessionReference](xbox_live_result> sessionResult) + { + if (!sessionResult.err() || sessionResult.err() == xbox_live_error_code::http_status_412_precondition_failed) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "multiplayer_session_writer class was destroyed."); + + pThis->on_session_updated(sessionResult.payload()); + } + + return sessionResult; + }); +} + +void +multiplayer_session_writer::resync() +{ +#if !XSAPI_U + std::lock_guard lock(m_resyncLock.get()); + + auto cachedSession = session(); + if (cachedSession != nullptr && !m_isTaskInProgress && m_handleResyncEventCounter > 0) + { + m_isTaskInProgress = true; + m_handleResyncEventCounter = 0; + multiplayer_session_change_event_args changeEventArgs(cachedSession->session_reference(), string_t(), cachedSession->change_number() + 1); + on_session_changed(changeEventArgs); + + // You could get multiple resync events. To avoid fetching the session too often, check back after TIME_PER_CALL_MS secs + std::weak_ptr thisWeakPtr = shared_from_this(); + create_delayed_task( + TIME_PER_CALL_MS, + [thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + std::lock_guard lock(pThis->m_resyncLock.get()); + pThis->m_isTaskInProgress = false; + + // Call resync from another task to avoid m_resyncLock from deadlocking. + pplx::create_task([thisWeakPtr]() + { + std::shared_ptr pThis2(thisWeakPtr.lock()); + if (pThis2 != nullptr) + { + pThis2->resync(); + } + }); + } + }); + } +#endif +} + +pplx::task>> +multiplayer_session_writer::leave_remote_session( + _In_ std::shared_ptr session + ) +{ + RETURN_TASK_CPP_IF(session == nullptr, std::shared_ptr, "Session is null"); + + auto sessionRefToCommit = session->session_reference(); + std::weak_ptr thisWeakPtr = shared_from_this(); + auto task = pplx::create_task([thisWeakPtr, sessionRefToCommit]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + RETURN_CPP_IF(pThis == nullptr, std::shared_ptr, xbox_live_error_code::generic_error, "multiplayer_session_writer class was destroyed."); + + xbox_live_result> multiplayerSessionResult; + auto xboxLiveContextMap = pThis->m_multiplayerLocalUserManager->get_local_user_map(); + for (auto xboxLiveContext : xboxLiveContextMap) + { + auto localUser = xboxLiveContext.second; + if (localUser != nullptr) + { + auto sessionToCommit = std::make_shared(localUser->xbox_user_id(), sessionRefToCommit); + sessionToCommit->leave(); + + // Never update latest copy upon leaving. + multiplayerSessionResult = pThis->write_session(localUser->context(), sessionToCommit, multiplayer_session_write_mode::update_existing, false).get(); + if (multiplayerSessionResult.err()) + { + break; + } + } + } + + return multiplayerSessionResult; + }); + + return utils::create_exception_free_task>(task); +} + +std::vector +multiplayer_session_writer::handle_events( + _In_ std::vector> processingQueue, + _In_ const std::error_code& errorCode, + _In_ const std::string& errorMessage, + _In_ multiplayer_session_type sessionType + ) +{ + std::vector eventQueue; + for (auto& request : processingQueue) + { + if (request->joinability() != joinability::none) + { + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + multiplayer_event_type::joinability_state_changed, + std::make_shared(), + sessionType, + request->context() + ); + + eventQueue.push_back(multiplayerEvent); + } + + if (request->session_properties().size() > 0) + { + // Fire events for each of the properties + auto iter = request->session_properties().begin(); + for (iter; iter != request->session_properties().end(); ++iter) + { + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + multiplayer_event_type::session_property_write_completed, + std::make_shared(), + sessionType, + request->context() + ); + + eventQueue.push_back(multiplayerEvent); + } + } + + if (!request->synchronized_host_device_token().empty()) + { + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + multiplayer_event_type::synchronized_host_write_completed, + std::make_shared(), + sessionType, + request->context() + ); + + eventQueue.push_back(multiplayerEvent); + } + + if (request->synchronized_session_properties().size() > 0) + { + // Fire events for each of the properties + auto iter = request->synchronized_session_properties().begin(); + for (iter; iter != request->synchronized_session_properties().end(); ++iter) + { + multiplayer_event multiplayerEvent( + errorCode, + errorMessage, + multiplayer_event_type::session_synchronized_property_write_completed, + std::make_shared(), + sessionType, + request->context() + ); + + eventQueue.push_back(multiplayerEvent); + } + } + } + + return eventQueue; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/perform_qos_measurements_event_args.cpp b/Source/Services/Multiplayer/Manager/perform_qos_measurements_event_args.cpp new file mode 100644 index 00000000..1e003f87 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/perform_qos_measurements_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +perform_qos_measurements_event_args::perform_qos_measurements_event_args( + _In_ std::map addressDeviceTokenMap + ): + m_addressToDeviceTokenMap(std::move(addressDeviceTokenMap)) +{ +} + +const std::map& +perform_qos_measurements_event_args::connection_address_to_device_tokens() const +{ + return m_addressToDeviceTokenMap; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/session_property_changed_event_args.cpp b/Source/Services/Multiplayer/Manager/session_property_changed_event_args.cpp new file mode 100644 index 00000000..330d67fa --- /dev/null +++ b/Source/Services/Multiplayer/Manager/session_property_changed_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +session_property_changed_event_args::session_property_changed_event_args( + _In_ web::json::value jsonProperties + ): + m_properties(std::move(jsonProperties)) +{ +} + +const web::json::value& +session_property_changed_event_args::properties() +{ + return m_properties; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/tournament_game_session_ready_event_args.cpp b/Source/Services/Multiplayer/Manager/tournament_game_session_ready_event_args.cpp new file mode 100644 index 00000000..d78c4d3e --- /dev/null +++ b/Source/Services/Multiplayer/Manager/tournament_game_session_ready_event_args.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +tournament_game_session_ready_event_args::tournament_game_session_ready_event_args( + _In_ utility::datetime startTime + ): + m_startTime(std::move(startTime)) +{ +} + +const utility::datetime& +tournament_game_session_ready_event_args::start_time() const +{ + return m_startTime; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/tournament_registration_state_changed_event_args.cpp b/Source/Services/Multiplayer/Manager/tournament_registration_state_changed_event_args.cpp new file mode 100644 index 00000000..36bc01f2 --- /dev/null +++ b/Source/Services/Multiplayer/Manager/tournament_registration_state_changed_event_args.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +tournament_registration_state_changed_event_args::tournament_registration_state_changed_event_args( + _In_ tournament_registration_state state, + _In_ tournament_registration_reason reason + ): + m_registrationState(state), + m_registrationReason(reason) +{ +} + +tournament_registration_state +tournament_registration_state_changed_event_args::registration_state() const +{ + return m_registrationState; +} + +tournament_registration_reason +tournament_registration_state_changed_event_args::registration_reason() const +{ + return m_registrationReason; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/user_added_event_args.cpp b/Source/Services/Multiplayer/Manager/user_added_event_args.cpp new file mode 100644 index 00000000..aeb8af0d --- /dev/null +++ b/Source/Services/Multiplayer/Manager/user_added_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +user_added_event_args::user_added_event_args( + _In_ string_t xboxUserId + ): + m_xboxUserid(std::move(xboxUserId)) +{ +} + +const string_t& +user_added_event_args::xbox_user_id() const +{ + return m_xboxUserid; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/Manager/user_removed_event_args.cpp b/Source/Services/Multiplayer/Manager/user_removed_event_args.cpp new file mode 100644 index 00000000..dd52900b --- /dev/null +++ b/Source/Services/Multiplayer/Manager/user_removed_event_args.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "pch.h" +#include "xsapi/multiplayer_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_BEGIN + +user_removed_event_args::user_removed_event_args( + _In_ string_t xboxUserId + ): + m_xboxUserid(std::move(xboxUserId)) +{ +} + +const string_t& +user_removed_event_args::xbox_user_id() const +{ + return m_xboxUserid; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MatchmakingStatus_WinRT.h b/Source/Services/Multiplayer/WinRT/MatchmakingStatus_WinRT.h new file mode 100644 index 00000000..f9274cfc --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MatchmakingStatus_WinRT.h @@ -0,0 +1,49 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Defines values that indicate the current status of the matchmaking operation. +/// + +public enum class MatchmakingStatus +{ + /// + /// The server returned an unrecognized response. + /// + Unknown = xbox::services::multiplayer::matchmaking_status::unknown, + + /// + /// Indicates that the matchmaking search is not specified. This status is optional and requires the clientMatchmaking capability. + /// + None = xbox::services::multiplayer::matchmaking_status::none, + + /// + /// Indicates that the matchmaking search is still searching. + /// + Searching = xbox::services::multiplayer::matchmaking_status::searching, + + /// + /// Indicates that the matchmaking search has expired. + /// + Expired = xbox::services::multiplayer::matchmaking_status::expired, + + /// + /// Indicates that the matchmaking search has found a session. + /// + Found = xbox::services::multiplayer::matchmaking_status::found, + + /// + /// Indicates that the matchmaking search has been canceled. + /// + Canceled = xbox::services::multiplayer::matchmaking_status::canceled +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayMetrics_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayMetrics_WinRT.h new file mode 100644 index 00000000..8ce9ce8c --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayMetrics_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values used to indicate the host selection metrics for measuring matchmaking QoS for a session. +/// +public enum class MultiplayMetrics +{ + /// + /// Unknown metric. + /// + Unknown = xbox::services::multiplayer::multiplay_metrics::unknown, + + /// + /// Bandwidth up host selection metric. + /// + BandwidthUp = xbox::services::multiplayer::multiplay_metrics::bandwidth_up, + + /// + /// Bandwidth down host selection metric. + /// + BandwidthDown = xbox::services::multiplayer::multiplay_metrics::bandwidth_down, + + /// + /// Bandwidth host selection metric. + /// + Bandwidth = xbox::services::multiplayer::multiplay_metrics::bandwidth, + + /// + /// Latency host selection metric. + /// + Latency = xbox::services::multiplayer::multiplay_metrics::latency +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.cpp new file mode 100644 index 00000000..0bfd0cd9 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.cpp @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerActivityDetails_WinRT.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerActivityDetails::MultiplayerActivityDetails( + _In_ xbox::services::multiplayer::multiplayer_activity_details cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj.session_reference()); +} + +MultiplayerSessionReference^ +MultiplayerActivityDetails::SessionReference::get() +{ + return m_sessionReference; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.h new file mode 100644 index 00000000..36d300f9 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerActivityDetails_WinRT.h @@ -0,0 +1,79 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionVisibility_WinRT.h" +#include "MultiplayerSessionRestriction_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents a user's current multiplayer activity, along with some details about the corresponding session. +/// +public ref class MultiplayerActivityDetails sealed +{ +public: + /// + /// The multiplayer session reference that contains identifying information for the session. + /// + property MultiplayerSessionReference^ SessionReference { MultiplayerSessionReference^ get(); } + + /// + /// The identifier of the handles that corresponds to the multiplayer activity. + /// + DEFINE_PROP_GET_STR_OBJ(HandleId, handle_id); + + /// + /// The identifier of the title that must be launched in order to join the multiplayer activity. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The visibility state of the session, which indicates Whether other users can see, or join, etc. + /// + DEFINE_PROP_GET_ENUM_OBJ(Visibility, visibility, MultiplayerSessionVisibility); + + /// + /// The join restriction of the session, which applies if visiblity is "open". + /// + DEFINE_PROP_GET_ENUM_OBJ(JoinRestriction, join_restriction, MultiplayerSessionRestriction); + + /// + /// Indicates whether the session is temporarily closed for joining. + /// + DEFINE_PROP_GET_OBJ(Closed, closed, bool); + + /// + /// The Xbox User ID of the owner for the multiplayer activity. + /// + DEFINE_PROP_GET_STR_OBJ(OwnerXboxUserId, owner_xbox_user_id); + + /// + /// The number of total session member slots supported for the multiplayer activity. + /// + DEFINE_PROP_GET_OBJ(MaxMembersCount, max_members_count, uint32); + + /// + /// The number of slots occupied. + /// + DEFINE_PROP_GET_OBJ(MembersCount, members_count, uint32); + +internal: + MultiplayerActivityDetails( + _In_ xbox::services::multiplayer::multiplayer_activity_details cppObj + ); + +private: + xbox::services::multiplayer::multiplayer_activity_details m_cppObj; + MultiplayerSessionReference^ m_sessionReference; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.cpp new file mode 100644 index 00000000..40c62da4 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.cpp @@ -0,0 +1,62 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerGetSessionsRequest_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::multiplayer; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerGetSessionsRequest::MultiplayerGetSessionsRequest( + _In_ xbox::services::multiplayer::multiplayer_get_sessions_request cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +MultiplayerGetSessionsRequest::MultiplayerGetSessionsRequest( + _In_ Platform::String^ serviceConfigurationId, + _In_ uint32 maxItems + ) : + m_cppObj( + multiplayer_get_sessions_request( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + maxItems + ) + ) +{ +} + +IVectorView^ +MultiplayerGetSessionsRequest::XboxUserIdsFilter::get() +{ + return m_xboxUserIds; +} + +void +MultiplayerGetSessionsRequest::XboxUserIdsFilter::set( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ) +{ + m_xboxUserIds = std::move(xboxUserIds); + m_cppObj.set_xbox_user_ids_filter( + Microsoft::Xbox::Services::System::UtilsWinRT::CovertVectorViewToStdVectorString(m_xboxUserIds) + ); +} + +multiplayer_get_sessions_request +MultiplayerGetSessionsRequest::GetCppObj() +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.h new file mode 100644 index 00000000..787b9ff2 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerGetSessionsRequest_WinRT.h @@ -0,0 +1,105 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionVisibility_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Defines the search filters for retrieveing a collection of discoverable sessions. Used in MultiplayerService::GetSessionsAsync(). +/// + +public ref class MultiplayerGetSessionsRequest sealed +{ +public: + /// + /// Constructs a new MultiplayerGetSessionsRequest object. + /// + /// The service configuration id associated with the sessions. + /// The maximum number of sessions to return. + MultiplayerGetSessionsRequest( + _In_ Platform::String^ serviceConfigurationId, + _In_ uint32 maxItems + ); + + /// + /// The service configuration id that the sessions are part of. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The maximum number of sessions to return. + /// + DEFINE_PROP_GET_OBJ(MaxItems, max_items, uint32); + + /// + /// Indicates if private sessions are included in the results. + /// + DEFINE_PROP_GETSET_OBJ(IncludePrivateSessions, include_private_sessions, bool); + + /// + /// Indicates if sessions that the user hasn't accepted are included in the results. You must specify xboxUserIdFilter if this value is set to true. + /// + DEFINE_PROP_GETSET_OBJ(IncludeReservations, include_reservations, bool); + + /// + /// Indicates if inactive sessions are included in the results. You must specify xboxUserIdFilter if this value is set to true. + /// + DEFINE_PROP_GETSET_OBJ(IncludeInactiveSessions, include_inactive_sessions, bool); + + /// + /// Optional. Filter results to just sessions that contain this Xbox User ID. + /// You must specify one of XboxUserIdFilter, XboxUserIdsFilter, or KeywordFilter. + /// + DEFINE_PROP_GETSET_STR_OBJ(XboxUserIdFilter, xbox_user_id_filter); + + /// + /// Optional. Filter results to just sessions that contains these Xbox User IDs. + /// You must specify one of XboxUserIdFilter, XboxUserIdsFilter, or KeywordFilter. + /// + property Windows::Foundation::Collections::IVectorView^ XboxUserIdsFilter { + Windows::Foundation::Collections::IVectorView^ get(); + void set(_In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds); + } + + /// + /// Optional. Filter results to just sessions with this keyword. + /// You must specify one of XboxUserIdFilter, XboxUserIdsFilter, or KeywordFilter. + /// + DEFINE_PROP_GETSET_STR_OBJ(KeywordFilter, keyword_filter); + + /// + /// Optional. The name of the template for the multiplayer session to filter on. + /// + DEFINE_PROP_GETSET_STR_OBJ(SessionTemplateNameFilter, session_template_name_filter); + + /// + /// Filter results to just sessions with the specified visibility. + /// + DEFINE_PROP_GETSET_ENUM_OBJ(VisibilityFilter, visibility_filter, MultiplayerSessionVisibility, xbox::services::multiplayer::multiplayer_session_visibility); + + /// + /// Filter results to just sessions with this major version, or less, of the contract. Set to 0 to ignore the contract version. + /// + DEFINE_PROP_GETSET_OBJ(ContractVersionFilter, contract_version_filter, uint32); + +internal: + MultiplayerGetSessionsRequest( + _In_ xbox::services::multiplayer::multiplayer_get_sessions_request cppObj + ); + + xbox::services::multiplayer::multiplayer_get_sessions_request GetCppObj(); +private: + xbox::services::multiplayer::multiplayer_get_sessions_request m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_xboxUserIds; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerInitializationStage_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerInitializationStage_WinRT.h new file mode 100644 index 00000000..255daf5c --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerInitializationStage_WinRT.h @@ -0,0 +1,54 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values that indicate the current status during the initialization stage. +/// +public enum class MultiplayerInitializationStage +{ + /// + /// Unknown. + /// + Unknown = xbox::services::multiplayer::multiplayer_initialization_stage::unknown, + + /// + /// The initialization stage not set. + /// + None = xbox::services::multiplayer::multiplayer_initialization_stage::none, + + /// + /// Players are joining the initialization stage. Typically matchmaking creates the session and adds users to it. + /// Players have up to the joining timeout to join the session during this phase. + /// + Joining = xbox::services::multiplayer::multiplayer_initialization_stage::joining, + + /// + /// The measuring initialization stage for QoS measurement is active. This is the stage where QoS measurement happens. + /// The title must manually manage QoS during this stage. + /// + Measuring = xbox::services::multiplayer::multiplayer_initialization_stage::measuring, + + /// + /// The evaluating initialization stage is active. + /// If auto evaluate is true, then this stage is skipped; otherwise, the title will do its own evaluation. + /// + Evaluating = xbox::services::multiplayer::multiplayer_initialization_stage::evaluating, + + /// + /// Failed initialization stage. + /// If episode 1 didn't succeed, then it indicates failed permanently. + /// + Failed = xbox::services::multiplayer::multiplayer_initialization_stage::failed +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.cpp new file mode 100644 index 00000000..24a53ffb --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.cpp @@ -0,0 +1,28 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "Utils_WinRT.h" +#include "MultiplayerManagedInitialization_WinRT.h" + +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerManagedInitialization::MultiplayerManagedInitialization( + _In_ xbox::services::multiplayer::multiplayer_managed_initialization cppObj + ) : + m_cppObj(cppObj) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.h new file mode 100644 index 00000000..5fc018bd --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerManagedInitialization_WinRT.h @@ -0,0 +1,90 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Represents managed initialization for a session. +/// +/// +/// If using managed initialization, the session expects the system or the title to perform initialization +/// following the session creation and/or as new members join the session. The session automatically tracks +/// the timeouts and initialization stages, including QoS measurements if any metrics are set. +/// These timeouts override the session's reservation and ready timeouts for members that have the +/// MultiplayerSessionMember.InitializationEpisode Property set. +/// +/// In managed initialization, the initialization stage goes from "joining" to "measuring" to "evaluating". +/// If the MultiplayerManagedInitialization.AutoEvaluate Property is set to true, the evaluating stage is skipped. +/// If metrics are not set for the session, the measuring stage is skipped. +/// If the stage is set to "failed", the session cannot be initialized. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "managedInitialization": { +/// "joinTimeout": 4000, +/// "measurementTimeout" : 5000, +/// "evaluationTimeout" : 5000, +/// "autoEvaluate" : true, +/// "membersNeededToStart" : 2 +/// }, +/// +/// + +public ref class MultiplayerManagedInitialization sealed +{ +public: + /// + /// Indicates if the ManagedInitializion object is set, which means that the session is using + /// managed initialization. + /// + DEFINE_PROP_GET_OBJ(ManagedInitializationSet, managed_initialization_set, bool); + + /// + /// The period of time that the system waits for a member to join a session during the joining stage + /// of managed initialization. This stage is the first stage of the QoS process. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(JoinTimeout, join_timeout) + + /// + /// The period of time that the system waits for a measuring operation to occur during managed initialization. + /// This stage is the measurement stage of the QoS process. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(MeasurementTimeout, measurement_timeout) + + /// + /// The period of time that the Xbox system waits for evaluation to occur during managed initialization. + /// Returns the timeout for the evaluation stage of the QoS process. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(EvaluationTimeout, evaluation_timeout) + + /// + /// A value that indicates if the system should auto-evaluate during managed initialization. + /// This is an optional evaluate stage for a title. The title can do evaluation when set to false. + /// + DEFINE_PROP_GET_OBJ(AutoEvaluate, auto_evaluate, bool); + + /// + /// The number of session members needed to start a session, during managed initialization episode 0 only. + /// Defaults to 2. This number must be between 1 and maxMemberCount. + /// + DEFINE_PROP_GET_OBJ(MembersNeededToStart, members_need_to_start, uint32); + +internal: + MultiplayerManagedInitialization( + _In_ xbox::services::multiplayer::multiplayer_managed_initialization cppObj + ); +private: + xbox::services::multiplayer::multiplayer_managed_initialization m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerMeasurementFailure_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerMeasurementFailure_WinRT.h new file mode 100644 index 00000000..01c1465c --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerMeasurementFailure_WinRT.h @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values used to indicate points of measurement failure during the metric stage. +/// +public enum class MultiplayerMeasurementFailure +{ + /// + /// Unknown measurement failure. + /// + Unknown = xbox::services::multiplayer::multiplayer_measurement_failure::unknown, + + /// + /// This player has no measurement failure. + /// + None = xbox::services::multiplayer::multiplayer_measurement_failure::none, + + /// + /// This player failed because timeout measurement test failed. + /// + Timeout = xbox::services::multiplayer::multiplayer_measurement_failure::timeout, + + /// + /// This player failed because latency measurement test failed. + /// + Latency = xbox::services::multiplayer::multiplayer_measurement_failure::latency, + + /// + /// This player failed because bandwidth up measurement test failed. + /// + BandwidthUp = xbox::services::multiplayer::multiplayer_measurement_failure::bandwidth_up, + + /// + /// This player failed because bandwidth down measurement test failed. + /// + BandwidthDown = xbox::services::multiplayer::multiplayer_measurement_failure::bandwidth_down, + + /// + /// This player failed because another player in their group failed. + /// + Group = xbox::services::multiplayer::multiplayer_measurement_failure::group, + + /// + /// This player failed due to a network error, such as the member was unable to reach another member. + /// + Network = xbox::services::multiplayer::multiplayer_measurement_failure::network, + + /// + /// This player failed because your episode failed. This likely happened because there weren't enough users in the session. + /// + Episode = xbox::services::multiplayer::multiplayer_measurement_failure::episode +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.cpp new file mode 100644 index 00000000..8b76804b --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.cpp @@ -0,0 +1,28 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "Utils_WinRT.h" +#include "MultiplayerMemberInitialization_WinRT.h" + +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerMemberInitialization::MultiplayerMemberInitialization( + _In_ xbox::services::multiplayer::multiplayer_member_initialization cppObj +) : + m_cppObj(cppObj) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.h new file mode 100644 index 00000000..6a20af3d --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerMemberInitialization_WinRT.h @@ -0,0 +1,90 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Represents managed initialization for a session. +/// +/// +/// If using managed initialization, the session expects the system or the title to perform initialization +/// following the session creation and/or as new members join the session. The session automatically tracks +/// the timeouts and initialization stages, including QoS measurements if any metrics are set. +/// These timeouts override the session's reservation and ready timeouts for members that have the +/// MultiplayerSessionMember.InitializationEpisode Property set. +/// +/// In managed initialization, the initialization stage goes from "joining" to "measuring" to "evaluating". +/// If the MultiplayerMemberInitialization.AutoEvaluate Property is set to true, the evaluating stage is skipped. +/// If metrics are not set for the session, the measuring stage is skipped. +/// If the stage is set to "failed", the session cannot be initialized. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "memberInitialization": { +/// "joinTimeout": 4000, +/// "measurementTimeout" : 5000, +/// "evaluationTimeout" : 5000, +/// "externalEvaluation" : true, +/// "membersNeededToStart" : 2 +/// }, +/// +/// + +public ref class MultiplayerMemberInitialization sealed +{ +public: + /// + /// Indicates if the ManagedInitializion object is set, which means that the session is using + /// managed initialization. + /// + DEFINE_PROP_GET_OBJ(MemberInitializationSet, member_initialization_set, bool); + + /// + /// The period of time that the system waits for a member to join a session during the joining stage + /// of managed initialization. This stage is the first stage of the QoS process. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(JoinTimeout, join_timeout) + + /// + /// The period of time that the system waits for a measuring operation to occur during managed initialization. + /// This stage is the measurement stage of the QoS process. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(MeasurementTimeout, measurement_timeout) + + /// + /// The period of time that the Xbox system waits for evaluation to occur during managed initialization. + /// Returns the timeout for the evaluation stage of the QoS process. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(EvaluationTimeout, evaluation_timeout) + + /// + /// A value that indicates if the system should auto-evaluate during managed initialization. + /// This is an optional evaluate stage for a title. The title can do evaluation when set to false. + /// + DEFINE_PROP_GET_OBJ(ExternalEvaluation, external_evaluation, bool); + + /// + /// The number of session members needed to start a session, during managed initialization episode 0 only. + /// Defaults to 2. This number must be between 1 and maxMemberCount. + /// + DEFINE_PROP_GET_OBJ(MembersNeededToStart, members_need_to_start, uint32); + +internal: + MultiplayerMemberInitialization( + _In_ xbox::services::multiplayer::multiplayer_member_initialization cppObj + ); +private: + xbox::services::multiplayer::multiplayer_member_initialization m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.cpp new file mode 100644 index 00000000..cd96491f --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.cpp @@ -0,0 +1,26 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerPeerToHostRequirements_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerPeerToHostRequirements::MultiplayerPeerToHostRequirements( + _In_ xbox::services::multiplayer::multiplayer_peer_to_host_requirements cppObj + ) : + m_cppObj(cppObj) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.h new file mode 100644 index 00000000..68961b70 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToHostRequirements_WinRT.h @@ -0,0 +1,66 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "Macros_WinRT.h" +#include "MultiplayMetrics_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Sets threshold requirements that apply to each connection between a host candidate and a session member. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "peerToHostRequirements": { +/// "latencyMaximum": 250, +/// "bandwidthDownMinimum" : 100000, +/// "bandwidthUpMinimum" : 1000, +/// "hostSelectionMetric" : "bandwidthUp" +/// }, +/// +/// + +public ref class MultiplayerPeerToHostRequirements sealed +{ + +public: + /// + /// The maximum latency for the peer to host connection. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(LatencyMaximum, latency_maximum); + + /// + /// The minimum bandwidth in kilobits per second for information sent from the host to the peer. + /// + DEFINE_PROP_GET_OBJ(BandwidthDownMinimumInKilobitsPerSecond, bandwidth_down_minimum_in_kilobits_per_second, uint64); + + /// + /// The minimum bandwidth in kilobits per second for information sent from the peer to the host. + /// + DEFINE_PROP_GET_OBJ(BandwidthUpMinimumInKilobitsPerSecond, bandwidth_up_minimum_in_kilobits_per_second, uint64); + + /// + /// Indicates which metric was used to select the host. + /// + DEFINE_PROP_GET_ENUM_OBJ(HostSelectionMetric, host_selection_metric, MultiplayMetrics); + +internal: + MultiplayerPeerToHostRequirements( + _In_ xbox::services::multiplayer::multiplayer_peer_to_host_requirements cppObj + ); + +private: + xbox::services::multiplayer::multiplayer_peer_to_host_requirements m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.cpp new file mode 100644 index 00000000..a4dc793d --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.cpp @@ -0,0 +1,26 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerPeerToPeerRequirements_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerPeerToPeerRequirements::MultiplayerPeerToPeerRequirements( + _In_ xbox::services::multiplayer::multiplayer_peer_to_peer_requirements cppObj + ) : + m_cppObj(cppObj) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.h new file mode 100644 index 00000000..19304d56 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerPeerToPeerRequirements_WinRT.h @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Sets thresholds requirements that apply to each pairwise connection for all members in a session. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "peerToPeerRequirements": { +/// "latencyMaximum": 250, +/// "bandwidthMinimum" : 10000 +/// }, +/// +/// + +public ref class MultiplayerPeerToPeerRequirements sealed +{ +public: + /// + /// The maximum latency for the peer to peer connection. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(LatencyMaximum, latency_maximum); + + /// + /// The minimum bandwidth in kilobits per second for the peer to peer connection. + /// + DEFINE_PROP_GET_OBJ(BandwidthMinimumInKilobitsPerSecond, bandwidth_minimum_in_kilobits_per_second, uint64); + +internal: + MultiplayerPeerToPeerRequirements( + _In_ xbox::services::multiplayer::multiplayer_peer_to_peer_requirements cppObj + ); + +private: + xbox::services::multiplayer::multiplayer_peer_to_peer_requirements m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.cpp new file mode 100644 index 00000000..c839e2db --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.cpp @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "MultiplayerQualityOfServiceMeasurements_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerQualityOfServiceMeasurements::MultiplayerQualityOfServiceMeasurements( + _In_ xbox::services::multiplayer::multiplayer_quality_of_service_measurements cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +MultiplayerQualityOfServiceMeasurements::MultiplayerQualityOfServiceMeasurements( + _In_ Platform::String^ memberDeviceToken, + _In_ Windows::Foundation::TimeSpan latency, + _In_ uint64 bandwidthDownInKilobitsPerSecond, + _In_ uint64 bandwidthUpInKilobitsPerSecond, + _In_ Platform::String^ customJson + ) +{ + m_cppObj = xbox::services::multiplayer::multiplayer_quality_of_service_measurements( + STRING_T_FROM_PLATFORM_STRING(memberDeviceToken), + UtilsWinRT::ConvertTimeSpanToSeconds(latency), + bandwidthDownInKilobitsPerSecond, + bandwidthUpInKilobitsPerSecond, + STRING_T_FROM_PLATFORM_STRING(customJson) + ); +} + +const xbox::services::multiplayer::multiplayer_quality_of_service_measurements& +MultiplayerQualityOfServiceMeasurements::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.h new file mode 100644 index 00000000..c5df3dca --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerQualityOfServiceMeasurements_WinRT.h @@ -0,0 +1,87 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Represents matchmaking quality of service (QoS) measurements for the network used by a session member. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "measurement=": { +/// "latency": 5953, +/// "bandwidthDown" : 19342, +/// "bandwidthUp" : 944, +/// "custom" : {} +/// } +/// +/// + +public ref class MultiplayerQualityOfServiceMeasurements sealed +{ +public: + /// + /// Creates a new MultiplayerQualityOfServiceMeasurements object for a session member. + /// + /// The device token of the session member that this measurement is for. + /// The measured latency, in milliseconds, for the session member. + /// The minimum bandwidth down, in kilobits per second, for downloading data from the host to the session member. + /// The minimum bandwidth up, in kilobits per second, for uploading data from the session member to the host. + /// A JSON string that specifies the custom QoS properties. + MultiplayerQualityOfServiceMeasurements( + _In_ Platform::String^ memberDeviceToken, + _In_ Windows::Foundation::TimeSpan latency, + _In_ uint64 bandwidthDownInKilobitsPerSecond, + _In_ uint64 bandwidthUpInKilobitsPerSecond, + _In_ Platform::String^ customJson + ); + + /// + /// The device token of the session member that this measurement is for. + /// + DEFINE_PROP_GET_STR_OBJ(MemberDeviceToken, member_device_token); + + /// + /// The measured latency, in milliseconds, for the session member. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(Latency, latency); + + /// + /// The minimum bandwidth down, in kilobits per second, for downloading data from the host to the session member. + /// + DEFINE_PROP_GET_OBJ(BandwidthDownInKilobitsPerSecond, bandwidth_down_in_kilobits_per_second, uint64); + + /// + /// The minimum bandwidth up, in kilobits per second, for uploading data from the session member to the host. + /// + DEFINE_PROP_GET_OBJ(BandwidthUpInKilobitsPerSecond, bandwidth_up_in_kilobits_per_second, uint64); + + /// + /// A JSON string that specifies the custom QoS properties. + /// + DEFINE_PROP_GET_STR_FROM_JSON_OBJ(CustomJson, custom_json); + +internal: + MultiplayerQualityOfServiceMeasurements( + _In_ xbox::services::multiplayer::multiplayer_quality_of_service_measurements cppObj + ); + + const xbox::services::multiplayer::multiplayer_quality_of_service_measurements& GetCppObj() const; + +private: + xbox::services::multiplayer::multiplayer_quality_of_service_measurements m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.cpp new file mode 100644 index 00000000..f0f80d5a --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.cpp @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerQuerySearchHandleRequest_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::multiplayer; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerQuerySearchHandleRequest::MultiplayerQuerySearchHandleRequest( + _In_ xbox::services::multiplayer::multiplayer_query_search_handle_request cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +MultiplayerQuerySearchHandleRequest::MultiplayerQuerySearchHandleRequest( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName + ) : + m_cppObj( + multiplayer_query_search_handle_request( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(sessionTemplateName) + ) + ) +{ +} + +const multiplayer_query_search_handle_request& +MultiplayerQuerySearchHandleRequest::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.h new file mode 100644 index 00000000..4974e312 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerQuerySearchHandleRequest_WinRT.h @@ -0,0 +1,73 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Sets the search handle based on the configuration of this request. +/// +public ref class MultiplayerQuerySearchHandleRequest sealed +{ +public: + /// Creates a MultiplayerGetSearchHandleRequest object. + /// The scid within which to query for search handles. + /// The name of the template to query for search handles. + /// + MultiplayerQuerySearchHandleRequest( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName + ); + + /// + /// The service configuration id that the sessions part of. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The name of the template that the sessions part of. + /// + DEFINE_PROP_GET_STR_OBJ(SessionTemplateName, session_template_name); + + /// + /// The attribute to sort the search handles by. + /// Valid values are "Timestamp desc", "Timestamp asc" or any Numbers search attribute followed by 'asc or 'desc' (ex: 'Numbers/gamerank asc') + /// + DEFINE_PROP_GETSET_STR_OBJ(OrderBy, order_by); + + /// + /// The order to sort the search handles by. + /// + DEFINE_PROP_GETSET_OBJ(OrderAscending, order_ascending, bool); + + /// + /// The filter to search for. + /// + DEFINE_PROP_GETSET_STR_OBJ(SearchFilter, search_filter); + + /// + /// The social group to get the search handles for. + /// + DEFINE_PROP_GETSET_STR_OBJ(SocialGroup, social_group); + +internal: + MultiplayerQuerySearchHandleRequest( + _In_ xbox::services::multiplayer::multiplayer_query_search_handle_request cppObj + ); + + const xbox::services::multiplayer::multiplayer_query_search_handle_request& GetCppObj() const; + +private: + xbox::services::multiplayer::multiplayer_query_search_handle_request m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.cpp new file mode 100644 index 00000000..7bb87bcf --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.cpp @@ -0,0 +1,44 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerRoleInfo_WinRT.h" +#include "Macros_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerRoleInfo::MultiplayerRoleInfo() +{ +} + +MultiplayerRoleInfo::MultiplayerRoleInfo( + _In_ xbox::services::multiplayer::multiplayer_role_info cppObj +) : + m_cppObj(std::move(cppObj)) +{ + m_memberXboxUserIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.member_xbox_user_ids()); +} + +xbox::services::multiplayer::multiplayer_role_info +MultiplayerRoleInfo::GetCppObj() const +{ + return m_cppObj; +} + +IVectorView^ +MultiplayerRoleInfo::MemberXboxUserIds::get() +{ + return m_memberXboxUserIds->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.h new file mode 100644 index 00000000..819bb94c --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerRoleInfo_WinRT.h @@ -0,0 +1,67 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents role info for a multiplayer role. +/// +public ref class MultiplayerRoleInfo sealed +{ +public: + /// + /// Creates a MultiplayerRoleInfo object. + /// + MultiplayerRoleInfo(); + + /// + /// Member XboxUserIds currently assigned for this role. + /// + property Windows::Foundation::Collections::IVectorView^ MemberXboxUserIds + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// Number of slots occupied for this role. + /// + DEFINE_PROP_GET_OBJ(MembersCount, members_count, uint32); + + /// + /// Number of target slots assigned for this role. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + DEFINE_PROP_GETSET_OBJ(TargetCount, target_count, uint32); + + /// + /// Maximum number of slots available for this role. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + DEFINE_PROP_GETSET_OBJ(MaxMembersCount, max_members_count, uint32); + +internal: + MultiplayerRoleInfo( + _In_ xbox::services::multiplayer::multiplayer_role_info cppObj + ); + + xbox::services::multiplayer::multiplayer_role_info GetCppObj() const; + +private: + xbox::services::multiplayer::multiplayer_role_info m_cppObj; + Windows::Foundation::Collections::IVector^ m_memberXboxUserIds; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.cpp new file mode 100644 index 00000000..36fed0bf --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.cpp @@ -0,0 +1,63 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerRoleType_WinRT.h" +#include "Macros_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerRoleType::MultiplayerRoleType() +{ +} + +MultiplayerRoleType::MultiplayerRoleType( + _In_ xbox::services::multiplayer::multiplayer_role_type cppObj +) : + m_cppObj(std::move(cppObj)) +{ + m_roles = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj.roles())->GetView(); + + m_mutableRoleSettings = ref new Platform::Collections::Vector(); + for (const auto& setting : m_cppObj.mutable_role_settings()) + { + m_mutableRoleSettings->Append(static_cast(setting)); + } +} + +xbox::services::multiplayer::multiplayer_role_type +MultiplayerRoleType::GetCppObj() const +{ + return m_cppObj; +} + +IVectorView^ +MultiplayerRoleType::MutableRoleSettings::get() +{ + return m_mutableRoleSettings->GetView(); +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerRoleType::Roles::get() +{ + return m_roles; +} +void +MultiplayerRoleType::Roles::set( + _In_ Windows::Foundation::Collections::IMapView^ roles + ) +{ + m_cppObj.set_roles(UtilsWinRT::CreateStdMapObjectWithStringKeyFromPlatformMapObj(roles)); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.h new file mode 100644 index 00000000..20929a4c --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerRoleType_WinRT.h @@ -0,0 +1,63 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerRoleInfo_WinRT.h" +#include "MutableRoleSetting_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents a collection of roles for this role type. +/// +public ref class MultiplayerRoleType sealed +{ +public: + /// + /// Creates a MultiplayerRoleType object. + /// + MultiplayerRoleType(); + + /// + /// True if ownerManaged is set on the roleType. + /// + DEFINE_PROP_GET_OBJ(OwnerManaged, owner_managed, bool); + + /// + /// Mutable role settings for this role. + /// + property Windows::Foundation::Collections::IVectorView^ MutableRoleSettings + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// A collection of roles for this role type. + /// + property Windows::Foundation::Collections::IMapView^ Roles + { + Windows::Foundation::Collections::IMapView^ get(); + void set(_In_ Windows::Foundation::Collections::IMapView^ roles); + } + +internal: + MultiplayerRoleType( + _In_ xbox::services::multiplayer::multiplayer_role_type cppObj + ); + + xbox::services::multiplayer::multiplayer_role_type GetCppObj() const; + +private: + xbox::services::multiplayer::multiplayer_role_type m_cppObj; + Windows::Foundation::Collections::IVector^ m_mutableRoleSettings; + Windows::Foundation::Collections::IMapView^ m_roles; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.cpp new file mode 100644 index 00000000..8cb9dbad --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.cpp @@ -0,0 +1,81 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSearchHandleDetails_WinRT.h" +#include "MultiplayerRoleType_WinRT.h" +#include "Macros_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSearchHandleDetails::MultiplayerSearchHandleDetails( + _In_ xbox::services::multiplayer::multiplayer_search_handle_details cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj.session_reference()); + m_sessionOwnerXboxUserIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.session_owner_xbox_user_ids()); + m_tags = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.tags()); + + m_stringsMetadata = ref new Platform::Collections::Map(); + for (const auto& address : m_cppObj.strings_metadata()) + { + m_stringsMetadata->Insert(ref new Platform::String(address.first.c_str()), ref new Platform::String(address.second.c_str())); + } + + m_numbersMetadata = ref new Platform::Collections::Map(); + for (const auto& address : m_cppObj.numbers_metadata()) + { + m_numbersMetadata->Insert(ref new Platform::String(address.first.c_str()), address.second); + } + + m_roleTypes = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj.role_types()); +} + +MultiplayerSessionReference^ +MultiplayerSearchHandleDetails::SessionReference::get() +{ + return m_sessionReference; +} + +IVectorView^ +MultiplayerSearchHandleDetails::SessionOwnerXboxUserIds::get() +{ + return m_sessionOwnerXboxUserIds->GetView(); +} + +IVectorView^ +MultiplayerSearchHandleDetails::Tags::get() +{ + return m_tags->GetView(); +} + +IMapView^ +MultiplayerSearchHandleDetails::StringsMetadata::get() +{ + return m_stringsMetadata->GetView(); +} + +IMapView^ +MultiplayerSearchHandleDetails::NumbersMetadata::get() +{ + return m_numbersMetadata->GetView(); +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerSearchHandleDetails::RoleTypes::get() +{ + return m_roleTypes->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.h new file mode 100644 index 00000000..5c6bd2fa --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleDetails_WinRT.h @@ -0,0 +1,120 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionVisibility_WinRT.h" +#include "MultiplayerSessionRestriction_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MultiplayerRoleType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents a users current search handle, along with some details about the corresponding session. +/// +public ref class MultiplayerSearchHandleDetails sealed +{ +public: + /// + /// The multiplayer session reference that contains identifying information for the session. + /// + property MultiplayerSessionReference^ SessionReference { MultiplayerSessionReference^ get(); } + + /// + /// The identifier of the handles that corresponds to the multiplayer activity. + /// + DEFINE_PROP_GET_STR_OBJ(HandleId, handle_id); + + /// + /// Owners of the session. + /// + property Windows::Foundation::Collections::IVectorView^ SessionOwnerXboxUserIds + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The tags that are currently set on the session. + /// + property Windows::Foundation::Collections::IVectorView^ Tags + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The numbers metadata that is currently set on the session. + /// + property Windows::Foundation::Collections::IMapView^ NumbersMetadata + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// The strings metadata that is currently set on the session. + /// + property Windows::Foundation::Collections::IMapView^ StringsMetadata + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// A collection of role types. + /// + property Windows::Foundation::Collections::IMapView^ RoleTypes + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// The visibility state of the session, which indicates Whether other users can see, or join, etc. + /// + DEFINE_PROP_GET_ENUM_OBJ(Visibility, visibility, MultiplayerSessionVisibility); + + /// + /// The join restriction of the session, which applies if visiblity is "open". + /// + DEFINE_PROP_GET_ENUM_OBJ(JoinRestriction, join_restriction, MultiplayerSessionRestriction); + + /// + /// Indicates whether the session is temporarily closed for joining. + /// + DEFINE_PROP_GET_OBJ(Closed, closed, bool); + + /// + /// The number of total session member slots supported for the multiplayer activity. + /// + DEFINE_PROP_GET_OBJ(MaxMembersCount, max_members_count, uint32); + + /// + /// The number of slots occupied. + /// + DEFINE_PROP_GET_OBJ(MembersCount, members_count, uint32); + + /// + /// The time when the search handle was posted. + /// + DEFINE_PROP_GET_DATETIME_OBJ(HandleCreationTime, handle_creation_time); + +internal: + MultiplayerSearchHandleDetails( + _In_ xbox::services::multiplayer::multiplayer_search_handle_details cppObj + ); + +private: + xbox::services::multiplayer::multiplayer_search_handle_details m_cppObj; + MultiplayerSessionReference^ m_sessionReference; + Windows::Foundation::Collections::IVector^ m_sessionOwnerXboxUserIds; + Windows::Foundation::Collections::IVector^ m_tags; + Platform::Collections::Map^ m_stringsMetadata; + Platform::Collections::Map^ m_numbersMetadata; + Platform::Collections::Map^ m_roleTypes; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.cpp new file mode 100644 index 00000000..c452df41 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.cpp @@ -0,0 +1,102 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSearchHandleRequest_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::multiplayer; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSearchHandleRequest::MultiplayerSearchHandleRequest( + _In_ xbox::services::multiplayer::multiplayer_search_handle_request cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +MultiplayerSearchHandleRequest::MultiplayerSearchHandleRequest( + _In_ MultiplayerSessionReference^ sessionReference + ) : m_cppObj( + multiplayer_search_handle_request(sessionReference->GetCppObj()) + ) +{ +} + +multiplayer_search_handle_request +MultiplayerSearchHandleRequest::GetCppObj() +{ + return m_cppObj; +} + +MultiplayerSessionReference^ +MultiplayerSearchHandleRequest::SessionReference::get() +{ + if (m_sessionReference == nullptr) + { + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj.session_reference()); + } + return m_sessionReference; +} + +IVectorView^ +MultiplayerSearchHandleRequest::Tags::get() +{ + return m_tags; +} + +void +MultiplayerSearchHandleRequest::Tags::set( + _In_ Windows::Foundation::Collections::IVectorView^ tags +) +{ + m_tags = tags; + m_cppObj.set_tags( + Microsoft::Xbox::Services::System::UtilsWinRT::CovertVectorViewToStdVectorString(m_tags) + ); +} + +IMapView^ +MultiplayerSearchHandleRequest::StringsMetadata::get() +{ + return m_stringsMetadata; +} + +void +MultiplayerSearchHandleRequest::StringsMetadata::set( + _In_ IMapView^ metadata + ) +{ + m_stringsMetadata = metadata; + m_cppObj.set_strings_metadata( + UtilsWinRT::CreateStdUnorderedMapStringFromMapObj(m_stringsMetadata) + ); +} + +IMapView^ +MultiplayerSearchHandleRequest::NumbersMetadata::get() +{ + return m_numbersMetadata; +} + +void +MultiplayerSearchHandleRequest::NumbersMetadata::set( + _In_ IMapView^ metadata +) +{ + m_numbersMetadata = metadata; + m_cppObj.set_numbers_metadata( + UtilsWinRT::CreateStdUnorderedMapObjectWithStringKeyFromPlatformMapObj(m_numbersMetadata) + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.h new file mode 100644 index 00000000..8dd4c694 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSearchHandleRequest_WinRT.h @@ -0,0 +1,78 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Sets the search handle based on the configuration of this request. +/// +public ref class MultiplayerSearchHandleRequest sealed +{ +public: + /// + /// Creates a MultiplayerSearchHandleRequest object. + /// + /// The session referenceid that the sessions part of. + MultiplayerSearchHandleRequest( + _In_ MultiplayerSessionReference^ sessionReference + ); + + /// + /// The session reference that the sessions part of. + /// + property MultiplayerSessionReference^ SessionReference { MultiplayerSessionReference^ get(); } + + /// + /// Filter result to just sessions with the tags set. + /// + property Windows::Foundation::Collections::IVectorView^ Tags + { + Windows::Foundation::Collections::IVectorView^ get(); + void set(_In_ Windows::Foundation::Collections::IVectorView^ tags); + } + + /// + /// Filter result to just sessions with the numbers metadata. + /// + property Windows::Foundation::Collections::IMapView^ NumbersMetadata + { + Windows::Foundation::Collections::IMapView^ get(); + void set(_In_ Windows::Foundation::Collections::IMapView^ metadata); + } + + /// + /// Filter result to just sessions with the strings metadata. + /// + property Windows::Foundation::Collections::IMapView^ StringsMetadata + { + Windows::Foundation::Collections::IMapView^ get(); + void set(_In_ Windows::Foundation::Collections::IMapView^ metadata); + } + +internal: + MultiplayerSearchHandleRequest( + _In_ xbox::services::multiplayer::multiplayer_search_handle_request cppObj + ); + + xbox::services::multiplayer::multiplayer_search_handle_request GetCppObj(); + +private: + xbox::services::multiplayer::multiplayer_search_handle_request m_cppObj; + MultiplayerSessionReference^ m_sessionReference; + Windows::Foundation::Collections::IVectorView^ m_tags; + Windows::Foundation::Collections::IMapView^ m_stringsMetadata; + Windows::Foundation::Collections::IMapView^ m_numbersMetadata; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.cpp new file mode 100644 index 00000000..e969bea2 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerServiceMatchmakingServer_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionMatchmakingServer::MultiplayerSessionMatchmakingServer( + _In_ xbox::services::multiplayer::multiplayer_session_matchmaking_server cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + if (!m_cppObj.target_session_ref().is_null()) + { + m_targetSessionReference = ref new MultiplayerSessionReference(m_cppObj.target_session_ref()); + } +} + +MultiplayerSessionReference^ +MultiplayerSessionMatchmakingServer::TargetSessionRef::get() +{ + return m_targetSessionReference; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.h new file mode 100644 index 00000000..7b772253 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerServiceMatchmakingServer_WinRT.h @@ -0,0 +1,52 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "MatchmakingStatus_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents the server that allows multiplayer session discovery to collaborate in a matchmaking session. +/// +public ref class MultiplayerSessionMatchmakingServer sealed +{ +public: + /// + /// The matchmaking status of the multiplayer session server. + /// + DEFINE_PROP_GET_ENUM_OBJ(Status, status, MatchmakingStatus); + + /// + /// The matchmaking status details of the multiplayer session server. + /// + DEFINE_PROP_GET_STR_OBJ(StatusDetails, status_details); + + /// + /// The typical wait time of the multiplayer session server. + /// + DEFINE_PROP_GET_TIMESPAN_OBJ(TypicalWait, typical_wait); + + /// + /// The target session reference of the multiplayer session server. + /// + property MultiplayerSessionReference^ TargetSessionRef { MultiplayerSessionReference^ get(); } + +internal: + MultiplayerSessionMatchmakingServer(_In_ xbox::services::multiplayer::multiplayer_session_matchmaking_server cppObj); + +private: + xbox::services::multiplayer::multiplayer_session_matchmaking_server m_cppObj; + MultiplayerSessionReference^ m_targetSessionReference; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.cpp new file mode 100644 index 00000000..9dd4dc32 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.cpp @@ -0,0 +1,756 @@ +////********************************************************* +//// +//// Copyright (c) Microsoft. All rights reserved. +//// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +//// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +//// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +//// +////********************************************************* + +#include "pch.h" +#include "MultiplayerService_WinRT.h" +#include "Utils_WinRT.h" +#include "user_context.h" +#include "utils.h" +#include "MultiplayerSessionWriteMode_WinRT.h" +#include "XboxLiveContextSettings_WinRT.h" + +using namespace pplx; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace Platform::Collections; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::multiplayer; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerService::MultiplayerService( + _In_ multiplayer_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_sessionChangeEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + m_subscriptionLostEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + + m_sessionChangeEventBind->AddMultiplayerSessionChangeEvent(); + m_subscriptionLostEventBind->AddMultiplayerSubscriptionLostEvent(); +} + +MultiplayerService::~MultiplayerService() +{ + m_sessionChangeEventBind->RemoveMultiplayerSessionChangeEvent(m_cppObj); + m_subscriptionLostEventBind->RemoveMultiplayerSubscriptionLostEvent(m_cppObj); +} + +MultiplayerSessionChangeEventBind::MultiplayerSessionChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ multiplayer_service& cppObj + ) : + m_setting(setting), + m_cppObj(cppObj), + m_functionContext(0) +{ +} + +void +MultiplayerSessionChangeEventBind::RemoveMultiplayerSessionChangeEvent( + _In_ xbox::services::multiplayer::multiplayer_service& cppObj + ) +{ + cppObj.remove_multiplayer_session_changed_handler(m_functionContext); +} + +void +MultiplayerSessionChangeEventBind::MultiplayerSessionChangeRouter( + _In_ const multiplayer_session_change_event_args& sessionChangeEventArgs + ) +{ + MultiplayerService^ multiplayerService = m_setting.Resolve(); + + if (multiplayerService != nullptr) + { +#if !TV_API + if (m_cppObj._Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([multiplayerService, sessionChangeEventArgs]() + { + multiplayerService->RaiseMultiplayerSessionChange(ref new MultiplayerSessionChangeEventArgs(sessionChangeEventArgs)); + })); + } + else +#endif + { + multiplayerService->RaiseMultiplayerSessionChange(ref new MultiplayerSessionChangeEventArgs(sessionChangeEventArgs)); + } + } +} + +void MultiplayerSessionChangeEventBind::AddMultiplayerSessionChangeEvent() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_cppObj.add_multiplayer_session_changed_handler([thisWeakPtr](_In_ const multiplayer_session_change_event_args& sessionChangeEventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->MultiplayerSessionChangeRouter(sessionChangeEventArgs); + } + }); +} + +MultiplayerSubscriptionLostEventBind::MultiplayerSubscriptionLostEventBind( + _In_ Platform::WeakReference setting, + _In_ multiplayer_service& cppObj + ) : + m_setting(setting), + m_cppObj(cppObj), + m_functionContext(0) +{ +} + +void +MultiplayerSubscriptionLostEventBind::RemoveMultiplayerSubscriptionLostEvent( + _In_ xbox::services::multiplayer::multiplayer_service& cppObj + ) +{ + cppObj.remove_multiplayer_subscription_lost_handler(m_functionContext); +} + +void +MultiplayerSubscriptionLostEventBind::MultiplayerSubscriptionLostRouter() +{ + MultiplayerService^ multiplayerService = m_setting.Resolve(); + if (multiplayerService != nullptr) + { + if (m_cppObj._Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([multiplayerService]() + { + multiplayerService->RaiseMultiplayerSubscriptionLost(ref new MultiplayerSubscriptionLostEventArgs()); + })); + } + else + { + multiplayerService->RaiseMultiplayerSubscriptionLost(ref new MultiplayerSubscriptionLostEventArgs()); + } + } +} + +void MultiplayerSubscriptionLostEventBind::AddMultiplayerSubscriptionLostEvent() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_cppObj.add_multiplayer_subscription_lost_handler([thisWeakPtr](void) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->MultiplayerSubscriptionLostRouter(); + } + }); +} + +void +MultiplayerService::RaiseMultiplayerSessionChange( + _In_ MultiplayerSessionChangeEventArgs^ args + ) +{ + MultiplayerSessionChanged(this, args); +} + +void +MultiplayerService::RaiseMultiplayerSubscriptionLost( + _In_ MultiplayerSubscriptionLostEventArgs^ args + ) +{ + MultiplayerSubscriptionLost(this, args); +} + +IAsyncOperation^ +MultiplayerService::WriteSessionAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(multiplayerSession); + + auto task = m_cppObj.write_session( + multiplayerSession->GetCppObj(), + static_cast(multiplayerSessionWriteMode) + ) + .then([](xbox_live_result> multiplayerSession) + { + THROW_IF_ERR(multiplayerSession); + + MultiplayerSession^ session = nullptr; + if (multiplayerSession.payload() != nullptr) + { + session = ref new MultiplayerSession(multiplayerSession.payload()); + } + return session; + }); + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MultiplayerService::TryWriteSessionAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode +) +{ + THROW_INVALIDARGUMENT_IF_NULL(multiplayerSession); + + auto task = m_cppObj.write_session( + multiplayerSession->GetCppObj(), + static_cast(multiplayerSessionWriteMode) + ) + .then([this](xbox_live_result> multiplayerSession) + { + return TryWriteSessionHelper(multiplayerSession); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MultiplayerService::WriteSessionByHandleAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode, + _In_ String^ handleId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(multiplayerSession); + THROW_INVALIDARGUMENT_IF_NULL(handleId); + + auto task = m_cppObj.write_session_by_handle( + multiplayerSession->GetCppObj(), + static_cast(multiplayerSessionWriteMode), + STRING_T_FROM_PLATFORM_STRING(handleId) + ) + .then([](xbox_live_result> multiplayerSession) + { + THROW_IF_ERR(multiplayerSession); + MultiplayerSession^ session = nullptr; + if (multiplayerSession.payload() != nullptr) + { + session = ref new MultiplayerSession(multiplayerSession.payload()); + } + return session; + }); + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +MultiplayerService::TryWriteSessionByHandleAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode, + _In_ Platform::String^ handleId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(multiplayerSession); + THROW_INVALIDARGUMENT_IF_NULL(handleId); + + auto task = m_cppObj.write_session_by_handle( + multiplayerSession->GetCppObj(), + static_cast(multiplayerSessionWriteMode), + STRING_T_FROM_PLATFORM_STRING(handleId) + ) + .then([this](xbox_live_result> multiplayerSession) + { + return TryWriteSessionHelper(multiplayerSession); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MultiplayerService::GetCurrentSessionAsync( + _In_ MultiplayerSessionReference^ sessionReference + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(sessionReference); + auto task = m_cppObj.get_current_session(sessionReference->GetCppObj()) + .then([](xbox_live_result> multiplayerSession) + { + THROW_IF_ERR(multiplayerSession); + MultiplayerSession^ session = nullptr; + if (multiplayerSession.payload() != nullptr) + { + session = ref new MultiplayerSession(multiplayerSession.payload()); + } + return session; + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MultiplayerService::GetCurrentSessionByHandleAsync( + _In_ String^ handleId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(handleId); + auto task = m_cppObj.get_current_session_by_handle(STRING_T_FROM_PLATFORM_STRING(handleId)) + .then([](xbox_live_result> multiplayerSession) + { + THROW_IF_ERR(multiplayerSession); + MultiplayerSession^ session = nullptr; + if (multiplayerSession.payload() != nullptr) + { + session = ref new MultiplayerSession(multiplayerSession.payload()); + } + return session; + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::GetSessionsAsync( + _In_ MultiplayerGetSessionsRequest^ getSessionsRequest + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(getSessionsRequest); + + auto task = m_cppObj.get_sessions(getSessionsRequest->GetCppObj()) + .then([](xbox_live_result> states) + { + THROW_IF_ERR(states); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(states.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::GetSessionsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ sessionTemplateNameFilter, + _In_opt_ Platform::String^ xboxUserIdFilter, + _In_opt_ Platform::String^ keywordFilter, + _In_ MultiplayerSessionVisibility visibilityFilter, + _In_ uint32 contractVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ uint32 maxItems + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + + return GetSessionsHelper( + serviceConfigurationId, + sessionTemplateNameFilter, + xboxUserIdFilter, + nullptr, + keywordFilter, + visibilityFilter, + contractVersionFilter, + includePrivateSessions, + includeReservations, + includeInactiveSessions, + maxItems + ); +} + +IAsyncOperation^>^ +MultiplayerService::GetSessionsForUsersFilterAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ sessionTemplateNameFilter, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIdsFilter, + _In_opt_ Platform::String^ keywordFilter, + _In_ MultiplayerSessionVisibility visibilityFilter, + _In_ uint32 contractVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ uint32 maxItems + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + + return GetSessionsHelper( + serviceConfigurationId, + sessionTemplateNameFilter, + nullptr, + xboxUserIdsFilter, + keywordFilter, + visibilityFilter, + contractVersionFilter, + includePrivateSessions, + includeReservations, + includeInactiveSessions, + maxItems + ); +} + +IAsyncAction^ +MultiplayerService::SetActivityAsync( + _In_ MultiplayerSessionReference^ sessionReference + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(sessionReference); + auto task = m_cppObj.set_activity(sessionReference->GetCppObj()) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +MultiplayerService::SetTransferHandleAsync( + _In_ MultiplayerSessionReference^ targetSessionReference, + _In_ MultiplayerSessionReference^ originSessionReference + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(targetSessionReference); + THROW_INVALIDARGUMENT_IF_NULL(originSessionReference); + + auto task = m_cppObj.set_transfer_handle( + targetSessionReference->GetCppObj(), + originSessionReference->GetCppObj() + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + return ref new Platform::String(result.payload().c_str()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +MultiplayerService::SetSearchHandleAsync( + _In_ MultiplayerSearchHandleRequest^ searchHandleRequest + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(searchHandleRequest); + + auto task = m_cppObj.set_search_handle(searchHandleRequest->GetCppObj()) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncAction^ +MultiplayerService::ClearActivityAsync( + _In_ String^ serviceConfigurationId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + auto task = m_cppObj.clear_activity(STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId)) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncAction^ +MultiplayerService::ClearSearchHandleAsync( + _In_ String^ handleId +) +{ + THROW_INVALIDARGUMENT_IF_NULL(handleId); + auto task = m_cppObj.clear_search_handle(STRING_T_FROM_PLATFORM_STRING(handleId)) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::SendInvitesAsync( + _In_ MultiplayerSessionReference^ sessionReference, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ uint32 titleId + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(sessionReference); + THROW_INVALIDARGUMENT_IF_NULL(xboxUserIds); + + auto task = m_cppObj.send_invites( + sessionReference->GetCppObj(), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds), + titleId) + .then([](xbox_live_result> invites) + { + THROW_IF_ERR(invites); + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(invites.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::SendInvitesAsync( + _In_ MultiplayerSessionReference^ sessionReference, + _In_ IVectorView^ xboxUserIds, + _In_ uint32 titleId, + _In_ Platform::String^ contextStringId, + _In_ Platform::String^ activationContext + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(sessionReference); + THROW_INVALIDARGUMENT_IF_NULL(xboxUserIds); + + auto task = m_cppObj.send_invites( + sessionReference->GetCppObj(), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds), + titleId, + STRING_T_FROM_PLATFORM_STRING(contextStringId), + STRING_T_FROM_PLATFORM_STRING(activationContext) + ) + .then([](xbox_live_result> invites) + { + THROW_IF_ERR(invites); + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(invites.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::GetActivitiesForSocialGroupAsync( + _In_ String^ serviceConfigurationId, + _In_ String^ socialGroupOwnerXboxUserId, + _In_ String^ socialGroup + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + THROW_INVALIDARGUMENT_IF_NULL(socialGroupOwnerXboxUserId); + THROW_INVALIDARGUMENT_IF_NULL(socialGroup); + + auto task = m_cppObj.get_activities_for_social_group( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(socialGroupOwnerXboxUserId), + STRING_T_FROM_PLATFORM_STRING(socialGroup) + ) + .then([](xbox_live_result> activities) + { + THROW_IF_ERR(activities); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(activities.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::GetActivitiesForUsersAsync( + _In_ String^ serviceConfigurationId, + _In_ IVectorView^ xboxUserIds + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + THROW_INVALIDARGUMENT_IF_NULL(xboxUserIds); + + auto task = m_cppObj.get_activities_for_users( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds) + ) + .then([](xbox_live_result> activities) + { + THROW_IF_ERR(activities); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(activities.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +MultiplayerService::GetSearchHandlesAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName, + _In_ Platform::String^ orderBy, + _In_ bool orderAscending, + _In_ Platform::String^ searchFilter + ) +{ + auto searchHandleRequest = ref new MultiplayerQuerySearchHandleRequest(serviceConfigurationId, sessionTemplateName); + searchHandleRequest->OrderBy = orderBy; + searchHandleRequest->OrderAscending = orderAscending; + searchHandleRequest->SearchFilter = searchFilter; + + return GetSearchHandlesAsync(searchHandleRequest); +} + +IAsyncOperation^>^ +MultiplayerService::GetSearchHandlesAsync( + _In_ MultiplayerQuerySearchHandleRequest^ searchHandleRequest + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(searchHandleRequest); + THROW_INVALIDARGUMENT_IF_NULL(searchHandleRequest->ServiceConfigurationId); + THROW_INVALIDARGUMENT_IF_NULL(searchHandleRequest->SessionTemplateName); + + auto task = m_cppObj.get_search_handles(searchHandleRequest->GetCppObj()) + .then([](xbox_live_result> activities) + { + THROW_IF_ERR(activities); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(activities.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +void +MultiplayerService::EnableMultiplayerSubscriptions() +{ + auto result = m_cppObj.enable_multiplayer_subscriptions(); + THROW_ON_ERR_CODE(result); +} + +void +MultiplayerService::DisableMultiplayerSubscriptions() +{ + CONVERT_STD_EXCEPTION( + m_cppObj.disable_multiplayer_subscriptions(); + ); +} + +WriteSessionResult^ +MultiplayerService::TryWriteSessionHelper( + _In_ xbox_live_result> multiplayerSessionResult + ) +{ + std::shared_ptr multiplayerSession = multiplayerSessionResult.payload(); + WriteSessionStatus writeSessionStatus = WriteSessionStatus::Unknown; + std::error_code errorCode = multiplayerSessionResult.err(); + + if (multiplayerSession == nullptr && errorCode == xbox_live_error_code::no_error) + { + writeSessionStatus = WriteSessionStatus::SessionDeleted; + } + else if (errorCode == xbox_live_error_code::http_status_401_unauthorized) + { + writeSessionStatus = WriteSessionStatus::AccessDenied; + } + else if (errorCode == xbox_live_error_code::http_status_404_not_found) + { + writeSessionStatus = WriteSessionStatus::HandleNotFound; + } + else if (errorCode == xbox_live_error_code::http_status_409_conflict) + { + writeSessionStatus = WriteSessionStatus::Conflict; + } + else if (errorCode == xbox_live_error_code::http_status_412_precondition_failed) + { + writeSessionStatus = WriteSessionStatus::OutOfSync; + } + else + { + if (multiplayerSession != nullptr) + { + writeSessionStatus = static_cast(multiplayerSession->write_status()); + if (writeSessionStatus == WriteSessionStatus::Unknown && multiplayerSessionResult.err()) + { + THROW_ON_ERR_CODE(multiplayerSessionResult.err()); + } + } + else + { + THROW_ON_ERR_CODE(multiplayerSessionResult.err()); + } + } + + bool didSucceed = (writeSessionStatus != WriteSessionStatus::AccessDenied && + writeSessionStatus != WriteSessionStatus::Conflict && + writeSessionStatus != WriteSessionStatus::OutOfSync && + writeSessionStatus != WriteSessionStatus::HandleNotFound); + + return ref new WriteSessionResult( + didSucceed, + multiplayerSession != nullptr ? ref new MultiplayerSession(multiplayerSession) : nullptr, + writeSessionStatus + ); +} + +IAsyncOperation^>^ +MultiplayerService::GetSessionsHelper( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ sessionTemplateNameFilter, + _In_opt_ Platform::String^ xboxUserIdFilter, + _In_opt_ Windows::Foundation::Collections::IVectorView^ xboxUserIdsFilter, + _In_opt_ Platform::String^ keywordFilter, + _In_ MultiplayerSessionVisibility visibilityFilter, + _In_ uint32 contractVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ uint32 maxItems + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + + auto sessionsRequest = multiplayer_get_sessions_request( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + maxItems + ); + + sessionsRequest.set_session_template_name_filter( + STRING_T_FROM_PLATFORM_STRING(sessionTemplateNameFilter) + ); + + if (xboxUserIdFilter != nullptr) + { + sessionsRequest.set_xbox_user_id_filter( + STRING_T_FROM_PLATFORM_STRING(xboxUserIdFilter) + ); + } + else + { + sessionsRequest.set_xbox_user_ids_filter( + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIdsFilter) + ); + } + + sessionsRequest.set_keyword_filter( + STRING_T_FROM_PLATFORM_STRING(keywordFilter) + ); + + sessionsRequest.set_visibility_filter( + static_cast(visibilityFilter) + ); + + sessionsRequest.set_contract_version_filter( + contractVersionFilter + ); + + sessionsRequest.set_include_private_sessions( + includePrivateSessions + ); + + sessionsRequest.set_include_reservations( + includeReservations + ); + + sessionsRequest.set_include_inactive_sessions( + includeInactiveSessions + ); + + auto task = m_cppObj.get_sessions(sessionsRequest) + .then([](xbox_live_result> states) + { + THROW_IF_ERR(states); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(states.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.h new file mode 100644 index 00000000..9cc2006a --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerService_WinRT.h @@ -0,0 +1,613 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "xsapi/xbox_live_context_settings.h" +#include "Macros_WinRT.h" +#include "MultiplayerSessionStates_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MultiplayerSession_WinRT.h" +#include "MultiplayerSessionVisibility_WinRT.h" +#include "MultiplayerSessionWriteMode_WinRT.h" +#include "MultiplayerActivityDetails_WinRT.h" +#include "MultiplayerSessionChangeEventArgs_WinRT.h" +#include "MultiplayerGetSessionsRequest_WinRT.h" +#include "MultiplayerQuerySearchHandleRequest_WinRT.h" +#include "MultiplayerSearchHandleRequest_WinRT.h" +#include "MultiplayerSearchHandleDetails_WinRT.h" +#include "WriteSessionResult_WinRT.h" +#include "MultiplayerSubscriptionLostEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +ref class MultiplayerService; + +class MultiplayerSessionChangeEventBind : public std::enable_shared_from_this +{ +public: + MultiplayerSessionChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::multiplayer::multiplayer_service& cppObj + ); + + void AddMultiplayerSessionChangeEvent(); + + void RemoveMultiplayerSessionChangeEvent( + _In_ xbox::services::multiplayer::multiplayer_service& cppObj + ); + + void MultiplayerSessionChangeRouter(_In_ const xbox::services::multiplayer::multiplayer_session_change_event_args& sessionChangeEventArgs); + +private: + function_context m_functionContext; + xbox::services::multiplayer::multiplayer_service m_cppObj; + Platform::WeakReference m_setting; +}; + +class MultiplayerSubscriptionLostEventBind : public std::enable_shared_from_this +{ +public: + MultiplayerSubscriptionLostEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::multiplayer::multiplayer_service& cppObj + ); + + void AddMultiplayerSubscriptionLostEvent(); + + void RemoveMultiplayerSubscriptionLostEvent( + _In_ xbox::services::multiplayer::multiplayer_service& cppObj + ); + + void MultiplayerSubscriptionLostRouter(); + +private: + function_context m_functionContext; + xbox::services::multiplayer::multiplayer_service m_cppObj; + Platform::WeakReference m_setting; +}; + +/// +/// Handles interactions with an Xbox Live service endpoint on a server. +/// +public ref class MultiplayerService sealed +{ +public: + /// + /// Registers for multiplayer session change notifications. Event handlers receive MultiplayerSessionChangeEventArgs^. + /// + event Windows::Foundation::EventHandler^ MultiplayerSessionChanged; + + /// + /// Notification sent when a multiplayer connectivity via RTA is lost or stopped. + /// Event handlers receive Windows::Networking::Sockets::RealTimeActivityMultiplayerSubscriptionsLostEventArgs^. + /// + event Windows::Foundation::EventHandler^ MultiplayerSubscriptionLost; + + /// + /// Writes a new or updated multiplayer session to the multiplayer service. + /// + /// A MultiplayerSession object that has been modified with the changes to write. + /// An enumeration value indicating the type of write operation. + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a MultiplayerSession object containing the response returned from the server. + /// The attributes in it might be different from the attributes in the passed-in MultiplayerSession object. + /// Calls V102 PUT /serviceconfigs/{serviceConfigurationId}/sessionTemplates/{sessiontemplateName}/sessions/{sessionName}. + /// + /// If your client needs to pass a handle ID when writing the session, it should call the MultiplayerService.WriteSessionByHandleAsync Method. + /// + /// If the client calls the MultiplayerSession.Leave Method for the last member of the session, when the session is + /// using a sessionEmptyTimeout value of 0, the session is deleted immediately. After the call to MultiplayerSession.Leave, + /// the client calls WriteSessionAsync to write local changes. This call returns a null pointer with an HTTP/204 status code, + /// since the session has been deleted. + /// + Windows::Foundation::IAsyncOperation^ WriteSessionAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode + ); + + /// + /// Attempts to write a new or updated multiplayer session to the service. + /// The passed multiplayerSession must have a valid MultiplayerSessionReference set on it. The purpose of this method is to give the caller + /// additional details on the failure or success of the operation. + /// + /// This method returns a WriteSessionResult instead of throwing an exception, but only in cases where the write failed for a reason that is expected to occur + /// during normal operation. + /// + /// A MultiplayerSession object that has been modified with the changes to write. + /// An enumeration value indicating the type of write operation. + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is an object representing a WriteSessionResult object that contains the response returned from the server, + /// a status with the result, as well as if the status was successful. The attributes in it may be different + /// from the attributes in the passed in MultiplayerSessionRequest object. + /// + /// If you leave a session that you are the last member of, and the sessionEmptyTimeout is equal to 0, then the session is deleted immediately + /// and a nullptr is returned. + /// + /// Calls V105 PUT /serviceconfigs/{serviceConfigurationId}/sessionTemplates/{sessiontemplateName}/sessions/{sessionName}. + Windows::Foundation::IAsyncOperation^ TryWriteSessionAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode + ); + + /// + /// Writes a new or updated multiplayer session to the service, using the specified handle to the session. + /// A handle is a service-side pointer to a session. The handleid is a GUID identifier of the handle. Callers will + /// usually get the handleid either from another player's MultiplayerActivityDetails, or from a protocol + /// activation after a user has accepted an invite. + /// + /// A MultiplayerSession object that has been modified with the changes to write. + /// An enumeration value indicating the type of write operation. + /// The ID (GUID) of the handle that should be used when writing the session. + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is an object representing the new or updated MultiplayerSession object that contains the response returned from the server. + /// The returned MultiplayerSession contains a MultiplayerSessionReference, so it can be used when calling WriteSessionAsync. + /// + /// + /// Use this method only if your MultiplayerSession object doesn't have a MultiplayerSessionReference, as + /// a handle's lifetime may be shorter than that of the session it points to. + /// + /// Calls V105 PUT /handles/{handleid}/session. + Windows::Foundation::IAsyncOperation^ WriteSessionByHandleAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode, + _In_ Platform::String^ handleId + ); + + /// + /// Attempts to write a new or updated multiplayer session to the service, using the specified handle to the session. + /// A handle is a service-side pointer to a session. The handleid is a GUID identifier of the handle. Callers will + /// usually get the handleid either from another player's MultiplayerActivityDetails, or from a protocol + /// activation after a user has accepted an invite. + /// The purpose of this method is to give the caller additional details on the failure or success. + /// + /// This method returns a WriteSessionResult instead of throwing an exception, but only in cases where the write failed for a reason that is expected to occur + /// during normal operation. + /// + /// A MultiplayerSession object that has been modified with the changes to write. + /// An enumeration value indicating the type of write operation. + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is an object representing a WriteSessionResult object that contains the response returned from the server, + /// a status with the result, as well as if the status was successful. The attributes in it may be different + /// from the attributes in the passed in MultiplayerSessionRequest object. + /// + /// Use this method only if your MultiplayerSession object doesn't have a MultiplayerSessionReference, as + /// a handle's lifetime may be shorter than that of the session it points to. + /// + /// If you leave a session that you are the last member of, and the sessionEmptyTimeout is equal to 0, then the session is deleted immediately + /// and a nullptr is returned. + /// + /// Calls V105 PUT /serviceconfigs/{serviceConfigurationId}/sessionTemplates/{sessiontemplateName}/sessions/{sessionName} + Windows::Foundation::IAsyncOperation^ TryWriteSessionByHandleAsync( + _In_ MultiplayerSession^ multiplayerSession, + _In_ MultiplayerSessionWriteMode multiplayerSessionWriteMode, + _In_ Platform::String^ handleId + ); + + /// + /// Gets a session object, with all of its attributes, from the server. + /// + /// A MultiplayerSessionReference object that contains identifying information for the session. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a MultiplayerSession object containing the response returned from the server. + /// + /// + /// If the client tries to get a session that does not exist, this method returns an HTTP/204 status code. + /// Additionally an exception is thrown for trying to retrieve a nonexistent session. + /// + /// Calls V102 GET /serviceconfigs/{serviceConfigurationId}/sessionTemplates/{sessiontemplateName}/sessions/{sessionName} + Windows::Foundation::IAsyncOperation^ GetCurrentSessionAsync( + _In_ MultiplayerSessionReference^ sessionReference + ); + + /// + /// Gets a session object with all its attributes from the server, given a session handle id. + /// A handle is a service-side pointer to a session. The handleid is a GUID identifier of the handle. Callers will + /// usually get the handleid either from another player's MultiplayerActivityDetails, or from a protocol + /// activation after a user has accepted an invite. + /// + /// A multiplayer handle id, which uniquely identifies the session. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a MultiplayerSession object that contains the response returned from the server. + /// + /// If the client tries to get a session that does not exist, this method returns an HTTP/204 status code. + /// Additionally an exception is thrown for trying to retrieve a nonexistent session. + /// + /// Calls GET /handles/{handleId}/session + Windows::Foundation::IAsyncOperation^ GetCurrentSessionByHandleAsync( + _In_ Platform::String^ handleId + ); + + /// + /// Retrieve a list of sessions with various filters. You can use this method to filter sessions for a single Xbox User ID, + /// a collection of Xbox User IDs, or for a keyword. + /// + /// An object that defines the search filters for retrieveing a collection of discoverable sessions. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a collection of SessionStates objects where each object contains metadata about one session. + /// + /// + /// You can use this method to filter sessions for a collection of Xbox User IDs. + /// + /// Calls V102 GET /serviceconfigs/{scid}/sessions or /serviceconfigs/{scid}/sessiontemplates/{session-template-name}/sessions + /// + Windows::Foundation::IAsyncOperation^>^ GetSessionsAsync( + _In_ MultiplayerGetSessionsRequest^ getSessionsRequest + ); + + /// + /// Retrieve a list of sessions with various filters + /// + /// The service configuration id that contains the sessions. + /// (Optional) The name of the template for the multiplayer session to filter on. + /// (Optional) An Xbox user ID to use for filtering results to sessions for that user. + /// You must specify either xboxUserIdFilter or keywordFilter. + /// (Optional) A keyword to use for filtering results to sessions with that keyword. + /// You must specify either xboxUserIdFilter or keywordFilter. + /// An enumeration value specifying the visibilty to use for filtering results. + /// A value specifying the major version, or less, of the contract to use for filtering results. + /// Set to 0 to ignore the contract version. + /// True to include private sessions in the results, and false otherwise. + /// True to include sessions that the user has not accepted in the results, and false otherwise. + /// For a setting of true, xboxUserIdFilter must be specified. + /// True to include inactive sessions in the results, and false otherwise. + /// For a setting of true, xboxUserIdFilter must be specified. + /// The maximum number of sessions to return. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a collection of SessionStates objects where each object contains metadata about one session. + /// + /// Calls V105 GET /serviceconfigs/{scid}/sessions or /serviceconfigs/{scid}/sessiontemplates/{session-template-name}/sessions +#if _MSC_VER >= 1800 + [Windows::Foundation::Metadata::Deprecated("Call GetSessionsAsync(MultiplayerGetSessionsRequest^) instead", Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0)] +#endif + Windows::Foundation::IAsyncOperation^>^ GetSessionsAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ sessionTemplateNameFilter, + _In_opt_ Platform::String^ xboxUserIdFilter, + _In_opt_ Platform::String^ keywordFilter, + _In_ MultiplayerSessionVisibility visibilityFilter, + _In_ uint32 contractVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ uint32 maxItems + ); + + /// + /// Retrieve a list of sessions with various filters for multiple users. + /// + /// The service configuration id that contains the sessions. + /// (Optional) The name of the template for the multiplayer session to filter on. + /// (Optional) A collection of Xbox user IDs to use for filtering results to sessions containing these Ids. + /// You must specify either xboxUserIdsFilter or keywordFilter. + /// (Optional) A keyword to use for filtering results to sessions with that keyword. + /// You must specify either xboxUserIdsFilter or keywordFilter. + /// An enumeration value specifying the visibilty to use for filtering results. + /// A value specifying the major version, or less, of the contract to use for filtering results. + /// Set to 0 to ignore the contract version. + /// True to include private sessions in the results, and false otherwise. + /// True to include sessions that the user has not accepted in the results, and false otherwise. + /// For a setting of true, xboxUserIdFilter must be specified. + /// True to include inactive sessions in the results, and false otherwise. + /// For a setting of true, xboxUserIdFilter must be specified. + /// The maximum number of sessions to return. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a collection of SessionStates objects where each object contains metadata about one session. + /// + /// Calls V105 POST /serviceconfigs/{scid}/batch or /serviceconfigs/{scid}/sessiontemplates/{session-template-name}/batch +#if _MSC_VER >= 1800 + [Windows::Foundation::Metadata::Deprecated("Call GetSessionsAsync(MultiplayerGetSessionsRequest^) instead", Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0)] +#endif + Windows::Foundation::IAsyncOperation^>^ GetSessionsForUsersFilterAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ sessionTemplateNameFilter, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIdsFilter, + _In_opt_ Platform::String^ keywordFilter, + _In_ MultiplayerSessionVisibility visibilityFilter, + _In_ uint32 contractVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ uint32 maxItems + ); + + /// + /// Sets the passed session as the user's current activity, which will be displayed in Xbox + /// dashboard user experiences (e.g. friends and gamercard) as associated with the currently + /// running title. If the session is joinable, it may also be displayed as joinable in those + /// user experiences. + /// + /// A MultiplayerSessionReference for the session of the activity. + /// Returns an IAsyncAction object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncAction.Completed property. + Windows::Foundation::IAsyncAction^ SetActivityAsync(_In_ MultiplayerSessionReference^ sessionReference); + + /// + /// Extends the access rights for the caller from the origin session to the target session. + /// For example, in a title with a lobby session and a game session, the title could put a transfer handle + /// linking the lobby to the game inside the lobby session. Users invited to the lobby can use the handle to join the game session as well. + /// The transfer handle is deleted once the target session is deleted. + /// + /// Target multiplayer_session_reference for the session you want to extend the access rights to. + /// Origin multiplayer_session_reference for the session that grants access to the target session. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a string that contains the transfer handle ID. + Windows::Foundation::IAsyncOperation^ SetTransferHandleAsync( + _In_ MultiplayerSessionReference^ targetSessionReference, + _In_ MultiplayerSessionReference^ originSessionReference + ); + + /// + /// Creates a search handle associated with the session. The visibility of the session is dependent on its search handle. + /// While you can create an searchable session, it is not queryable and visible to others unless you have the associated search handle committed as well. + /// + /// A search handle request object for the associated session + /// The async object for notifying when the operation is completed. + Windows::Foundation::IAsyncAction^ SetSearchHandleAsync( + _In_ MultiplayerSearchHandleRequest^ searchHandleRequest + ); + + /// + /// Clears the user's current activity session for the specified service configuration ID. + /// + /// A string containing the service configuration ID in which to clear activity. + /// Returns an IAsyncAction object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncAction.Completed property. + Windows::Foundation::IAsyncAction^ ClearActivityAsync(_In_ Platform::String^ serviceConfigurationId); + + /// + /// Clears the search handle that is associated with the session. + /// + /// The handleId associated with the session to clear. + /// The async object for notifying when the operation is completed. + Windows::Foundation::IAsyncAction^ ClearSearchHandleAsync(_In_ Platform::String^ handleId); + + /// + /// Invites the specified users to a session. + /// + /// A MultiplayerSessionReference object representing the session the target users will be invited to. + /// The list of Xbox user IDs to invite. + /// The ID of the title that the invited user will activate in order to join the session. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a vectorview of handle ID strings corresponding to the invites that have been sent. + /// + /// Calling this method results in a notification being shown to each invited user. + /// If a user accepts the notification, then the title is activated for that user. + /// + Windows::Foundation::IAsyncOperation^>^ SendInvitesAsync( + _In_ MultiplayerSessionReference^ sessionReference, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ uint32 titleId + ); + + /// + /// Invites the specified users to a session. + /// + /// A MultiplayerSessionReference object representing the session the target users will be invited to. + /// The list of Xbox user IDs to invite. + /// The ID of the title that the invited user will activate in order to join the session. + /// + /// The ID of the custom invite string that is displayed with the invite notification. The ID must match the ID that is + /// assigned to the custom invite string in the title's multiplayer service configuration. + /// + /// The format of the parameter is "///{id}", where {id} is replaced with the ID of the custom string. + /// + /// For example, if the ID of the custom string "Play Capture the Flag" is 1, then you would set this parameter + /// to "///1" in order to display the "Play Capture the Flag" custom string in the game invite. + /// + /// Pass an empty string if you don't want a custom string added to the invite. + /// + /// The custom activation contest. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a vectorview of handle ID strings corresponding to the invites that have been sent. + /// + /// Calling this method results in a notification being shown to each invited user. + /// If a user accepts the notification, then the title is activated for that user. + /// + Windows::Foundation::IAsyncOperation^>^ SendInvitesAsync( + _In_ MultiplayerSessionReference^ sessionReference, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ uint32 titleId, + _In_ Platform::String^ contextStringId, + _In_ Platform::String^ activationContext + ); + + /// + /// Gets the current activity for a social group of users associated with a user that is designated as + /// the owner of the session. + /// + /// The service configuration ID to query for activities. + /// The Xbox user ID of the person whose social group will be used for the query. + /// The social group ID to use in order to get the list of users. (e.g. "friends" or "favorites"). + /// The async object for notifying when the operation is completed. + /// This contains a vectorview of MultiplayerActivityDetails objects, containing the details of the activities of the targeted users. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a vectorview of MultiplayerActivityDetails objects, containing the details of the activities for the social group of users. + /// + /// There is no paging or continuation, and the multiplayer service limit the number of items returned to 100. + /// + Windows::Foundation::IAsyncOperation^>^ GetActivitiesForSocialGroupAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ socialGroupOwnerXboxUserId, + _In_ Platform::String^ socialGroup + ); + + /// + /// Gets the current activity for a set of users specified by Xbox user IDs. + /// + /// The service configuration ID to query for activities. + /// The list of Xbox user IDs to find activities for. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. + /// When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method. + /// + /// The result is a vectorview of MultiplayerActivityDetails objects, containing the details of the activities for the specified users. + /// + /// There is no paging or continuation, and the multiplayer service limit the number of items returned to 100. + /// + Windows::Foundation::IAsyncOperation^>^ GetActivitiesForUsersAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ); + + /// + /// Queries for the all search handles that references the searchable sessions given the specific query. + /// There is no paging or continuation, and the multiplayer service will limit the number of items returned to 100. + /// Call GetSearchHandlesAsync(MultiplayerQuerySearchHandleRequest^ ) instead. + /// + /// The scid within which to query for search handles. + /// The name of the template to query for search handles. + /// This specifies the attribute to sort the search handles by. Pass empty string to default to ordering by 'Timestamp asc' + /// Pass true to order ascending, false to order descending + /// The query string to get the search handles for. + /// The search query. + /// The query syntax is an OData like syntax with only the following operators supported EQ, NE, GE, GT, LE and LT along with the logical operators of AND and OR. + /// + /// Example 1: + /// To search for search handles for a specific XboxUserId use + /// "MemberXuids/any(d:d eq 12345678)" or "OwnerXuids/any(d:d eq 12345678)" + /// + /// Example 2: + /// To search for search handles for a title defined string metadata use + /// "Strings/stringMetadataType eq value" + /// + /// Example 3: + /// To search for search handles for a title defined numbers metadata AND a tag type value use + /// Numbers/numberMetadataType eq 53 AND Tags/tagType eq value + /// + /// The async object for notifying when the operation is completed. This contains a vectorview of MultiplayerSearchHandleDetails objects, containing the details of the search handles. + Windows::Foundation::IAsyncOperation^>^ GetSearchHandlesAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName, + _In_ Platform::String^ orderBy, + _In_ bool orderAscending, + _In_ Platform::String^ searchFilter + ); + + /// + /// Queries for the all search handles that references the searchable sessions given the specific query. + /// There is no paging or continuation, and the multiplayer service will limit the number of items returned to 100. + /// + /// + /// The async object for notifying when the operation is completed. This contains a vectorview of MultiplayerSearchHandleDetails objects, containing the details of the search handles. + Windows::Foundation::IAsyncOperation^>^ GetSearchHandlesAsync( + _In_ MultiplayerQuerySearchHandleRequest^ searchHandleRequest + ); + + /// + /// Starts multiplayerservice connectivity via Real Time Activity (RTA), for two purposes: + /// 1. Subscriptions to changes on specific sessions, using the MultiplayerSession object. + /// 2. Automatic removal of members from sessions when the collection underlying this multiplayer subscription is broken. + /// + /// This method does not actually make the connection, but enables the connection, and helps track its lifetime. + /// + /// + /// This method fails if called twice, unless the multiplayerconnection has been lost or stopped in the interim. + /// This can be detected by listening for the MultiplayerSubscriptionsLost event. + /// + void EnableMultiplayerSubscriptions(); + + /// + /// Stops multiplayerservice connectivity via Real Time Activity (RTA). + /// + /// + /// When stopping multiplayer is complete, a MultiplayerSubscriptionsLost event is fired. + /// It is not necessary to wait for this event to fire, unless you intend to call EnableMultiplayerSubscriptions() to restart it, + /// in which case you must wait for the stop to complete. + /// + void DisableMultiplayerSubscriptions(); + + /// + /// Indicates whether multiplayer subscriptions are currently enabled. + /// + DEFINE_PROP_GET_OBJ(MultiplayerSubscriptionsEnabled, subscriptions_enabled, bool); + +internal: + MultiplayerService( + _In_ xbox::services::multiplayer::multiplayer_service cppObj + ); + + void RaiseMultiplayerSessionChange(_In_ MultiplayerSessionChangeEventArgs^ args); + + void RaiseMultiplayerSubscriptionLost(_In_ MultiplayerSubscriptionLostEventArgs^ args); + +private: + ~MultiplayerService(); + + WriteSessionResult^ TryWriteSessionHelper(_In_ xbox::services::xbox_live_result> multiplayerSession); + Windows::Foundation::IAsyncOperation^>^ GetSessionsHelper( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ sessionTemplateNameFilter, + _In_opt_ Platform::String^ xboxUserIdFilter, + _In_opt_ Windows::Foundation::Collections::IVectorView^ xboxUserIdsFilter, + _In_opt_ Platform::String^ keywordFilter, + _In_ MultiplayerSessionVisibility visibilityFilter, + _In_ uint32 contractVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ uint32 maxItems + ); + + xbox::services::multiplayer::multiplayer_service m_cppObj; + std::shared_ptr m_sessionChangeEventBind; + std::shared_ptr m_subscriptionLostEventBind; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.cpp new file mode 100644 index 00000000..99dba2da --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionArbitrationServer_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace concurrency; +using namespace xbox::services; +using namespace xbox::services::tournaments; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionArbitrationServer::MultiplayerSessionArbitrationServer( + _In_ xbox::services::multiplayer::multiplayer_session_arbitration_server cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_results = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj.results()); +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerSessionArbitrationServer::Results::get() +{ + return m_results->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.h new file mode 100644 index 00000000..4680d209 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionArbitrationServer_WinRT.h @@ -0,0 +1,54 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "TournamentTeamResult_WinRT.h" +#include "TournamentArbitrationState_WinRT.h" +#include "TournamentGameResultSource_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents the server that holds info about a tournament games result. +/// +public ref class MultiplayerSessionArbitrationServer sealed +{ +public: + /// + /// The state of the result + /// + DEFINE_PROP_GET_ENUM_OBJ(ResultState, result_state, Microsoft::Xbox::Services::Tournaments::TournamentArbitrationState); + + /// + /// The source of the result + /// + DEFINE_PROP_GET_ENUM_OBJ(ResultSource, result_source, Microsoft::Xbox::Services::Tournaments::TournamentGameResultSource); + + /// + /// A value from 0-100 that indicates the confidence level of this result + /// + DEFINE_PROP_GET_OBJ(ResultConfidenceLevel, result_confidence_level, uint32) + + /// + /// The results of the game + /// + property Windows::Foundation::Collections::IMapView^ Results { Windows::Foundation::Collections::IMapView^ get(); } + +internal: + MultiplayerSessionArbitrationServer(_In_ xbox::services::multiplayer::multiplayer_session_arbitration_server cppObj); + +private: + xbox::services::multiplayer::multiplayer_session_arbitration_server m_cppObj; + Platform::Collections::Map^ m_results; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.cpp new file mode 100644 index 00000000..c34ab420 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "MultiplayerSessionCapabilities_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionCapabilities::MultiplayerSessionCapabilities( + _In_ xbox::services::multiplayer::multiplayer_session_capabilities cppObj + ) : + m_cppObj(cppObj) +{ +} + +MultiplayerSessionCapabilities::MultiplayerSessionCapabilities() +{ + m_cppObj = xbox::services::multiplayer::multiplayer_session_capabilities(); +} + +xbox::services::multiplayer::multiplayer_session_capabilities +MultiplayerSessionCapabilities::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.h new file mode 100644 index 00000000..c9113888 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionCapabilities_WinRT.h @@ -0,0 +1,117 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Represents the capabilities for a MultiplayerSession Class object. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "capabilities": { +/// "clientMatchmaking": true, +/// "connectivity" : true, +/// "suppressPresenceActivityCheck" : true, +/// "gameplay" : true, +/// "large" : false +/// } +/// +/// + +public ref class MultiplayerSessionCapabilities sealed +{ +public: + /// + /// Creates a MultiplayerSessionCapabilities object. + /// + MultiplayerSessionCapabilities(); + + /// + /// A value that indicates if the session supports connectivity. + /// If false, the session can't enable any metrics and the session members can't set their SecureDeviceAddress. + /// This value can't be set for large sessions. + /// + DEFINE_PROP_GETSET_OBJ(Connectivity, connectivity, bool); + + /// + /// A value that indicates if active users of the session are demoted to inactive status. + /// By default (false), active users are required to remain online playing the title, otherwise they get demoted to + /// inactive status. Setting this flag to true disables this check so that members stay active indefinitely. + /// + DEFINE_PROP_GETSET_OBJ(SuppressPresenceActivityCheck, suppress_presence_activity_check, bool); + + /// + /// A value that indicates whether the session represents actual gameplay, as opposed to setup/menu time + /// such as a lobby or matchmaking. + /// If true, then the session is in gameplay mode. + /// + DEFINE_PROP_GETSET_OBJ(Gameplay, gameplay, bool); + + /// + /// A value that indicates if the session can host a large number of users, which has impact on other session properties. + /// If true, this session can host a large number of users. + /// + DEFINE_PROP_GETSET_OBJ(Large, large, bool); + + /// + /// Aa Boolean value that determines whether a connection is required for active members in a multiplayer session. + /// If true, a connection is required for active members in the multiplayer session; otherwise, false. + /// + DEFINE_PROP_GETSET_OBJ(ConnectionRequiredForActiveMembers, connection_required_for_active_members, bool); + + /// + /// a Boolean value that determines whether a multiplayer session uses user authorization style, which means that + /// the session supports calls from platforms without strong title identity. + /// This calue can't be set on large sessions. + /// + DEFINE_PROP_GETSET_OBJ(UserAuthorizationStyle, user_authorization_style, bool); + + /// + /// A Boolean value that determines whether a multiplayer session supports crossplay between Xbox One and Windows 10. + /// True indicates that crossplay is supported. + /// + DEFINE_PROP_GETSET_OBJ(Crossplay, crossplay, bool); + + /// + /// True if the session supports team capability used for a tournament. + /// + DEFINE_PROP_GETSET_OBJ(Team, team, bool); + + /// + /// True if the session supports arbitration used for a tournament. + /// + DEFINE_PROP_GETSET_OBJ(Arbitration, arbitration, bool); + + /// + /// True, if the session can be linked to a search handle for searching. + /// + DEFINE_PROP_GETSET_OBJ(Searchable, searchable, bool); + + /// + /// True, if the session has owners. If you have user_authorization_style set, then in order to be searchable, you must have owners set. + /// + DEFINE_PROP_GETSET_OBJ(HasOwners, has_owners, bool); + +internal: + MultiplayerSessionCapabilities( + _In_ xbox::services::multiplayer::multiplayer_session_capabilities cppObj + ); + + xbox::services::multiplayer::multiplayer_session_capabilities GetCppObj() const; +private: + xbox::services::multiplayer::multiplayer_session_capabilities m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.cpp new file mode 100644 index 00000000..8081be40 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.cpp @@ -0,0 +1,29 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionChangeEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionChangeEventArgs::MultiplayerSessionChangeEventArgs( + _In_ xbox::services::multiplayer::multiplayer_session_change_event_args cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_sessionRef = ref new MultiplayerSessionReference(m_cppObj.session_reference()); +} + +MultiplayerSessionReference^ +MultiplayerSessionChangeEventArgs::SessionReference::get() +{ + return m_sessionRef; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.h new file mode 100644 index 00000000..a05e993b --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeEventArgs_WinRT.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Indicates the session that triggered the event. +/// +public ref class MultiplayerSessionChangeEventArgs sealed +{ +public: + /// + /// The session that triggered this event. + /// + property MultiplayerSessionReference^ SessionReference { Multiplayer::MultiplayerSessionReference^ get(); } + + /// + /// The branch of the session used to scope change numbers. + /// + DEFINE_PROP_GET_STR_OBJ(Branch, branch) + + /// + /// The change number of the session. + /// + DEFINE_PROP_GET_OBJ(ChangeNumber, change_number, uint64 ) + +internal: + MultiplayerSessionChangeEventArgs( + _In_ xbox::services::multiplayer::multiplayer_session_change_event_args cppObj + ); + +private: + xbox::services::multiplayer::multiplayer_session_change_event_args m_cppObj; + MultiplayerSessionReference^ m_sessionRef; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeTypes.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeTypes.h new file mode 100644 index 00000000..869cb9a7 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionChangeTypes.h @@ -0,0 +1,79 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines enumberation values that indicate the types of changes to a session that can be subscribed to. +/// +public enum class MultiplayerSessionChangeTypes +{ + /// + /// None. + /// + None = xbox::services::multiplayer::multiplayer_session_change_types::none, + + /// + /// Changes to anything in the session. + /// + Everything = xbox::services::multiplayer::multiplayer_session_change_types::everything, + + /// + /// Changes to the host device token. + /// + HostDeviceTokenChange = xbox::services::multiplayer::multiplayer_session_change_types::host_device_token_change, + + /// + /// Changes to the stage of initialization has changed. + /// + InitializationStateChange = xbox::services::multiplayer::multiplayer_session_change_types::initialization_state_change, + + /// + /// Changes to the matchmaking status (e.g. match found or expired) occured. + /// + MatchmakingStatusChange = xbox::services::multiplayer::multiplayer_session_change_types::matchmaking_status_change, + + /// + /// A member joined or left the session. + /// + MemberListChange = xbox::services::multiplayer::multiplayer_session_change_types::member_list_change, + + /// + /// Changes to the status of a member. + /// + MemberStatusChange = xbox::services::multiplayer::multiplayer_session_change_types::member_status_change, + + /// + /// Changes to the joinability of the session. + /// + SessionJoinabilityChange = xbox::services::multiplayer::multiplayer_session_change_types::session_joinability_change, + + /// + /// Changes within the /properties/custom object. + /// + CustomPropertyChange = xbox::services::multiplayer::multiplayer_session_change_types::custom_property_change, + + /// + /// Changed within the /member/properties/custom object, for any of the members. + /// + MemberCustomPropertyChange = xbox::services::multiplayer::multiplayer_session_change_types::member_custom_property_change, + + /// + /// Changes within tournament server properties. Such as next game, last game, or registration. + /// + TournamentPropertyChange = xbox::services::multiplayer::multiplayer_session_change_types::tournament_property_change, + + /// + /// Changes within tournament server properties. Such as next game, last game, or registration. + /// + ArbitrationPropertyChange = xbox::services::multiplayer::multiplayer_session_change_types::arbitration_property_change +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.cpp new file mode 100644 index 00000000..35677a89 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.cpp @@ -0,0 +1,59 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "MultiplayerSessionConstants_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionConstants::MultiplayerSessionConstants( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + THROW_INVALIDARGUMENT_IF_NULL(m_cppObj); +} + +IVectorView^ +MultiplayerSessionConstants::InitiatorXboxUserIds::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj->initiator_xbox_user_ids())->GetView(); +} + +MultiplayerManagedInitialization^ +MultiplayerSessionConstants::ManagedInitialization::get() +{ +#pragma warning(suppress: 4996) + return ref new MultiplayerManagedInitialization(m_cppObj->managed_initialization()); +} + +MultiplayerMemberInitialization^ +MultiplayerSessionConstants::MemberInitialization::get() +{ + return ref new MultiplayerMemberInitialization(m_cppObj->member_initialization()); +} + +MultiplayerPeerToPeerRequirements^ +MultiplayerSessionConstants::PeerToPeerRequirements::get() +{ + return ref new MultiplayerPeerToPeerRequirements(m_cppObj->peer_to_peer_requirements()); +} + +MultiplayerPeerToHostRequirements^ +MultiplayerSessionConstants::PeerToHostRequirements::get() +{ + return ref new MultiplayerPeerToHostRequirements(m_cppObj->peer_to_host_requirements()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.h new file mode 100644 index 00000000..b20e0240 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionConstants_WinRT.h @@ -0,0 +1,293 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerPeerToPeerRequirements_WinRT.h" +#include "MultiplayerPeerToHostRequirements_WinRT.h" +#include "MultiplayerManagedInitialization_WinRT.h" +#include "MultiplayerMemberInitialization_WinRT.h" +#include "MultiplayerSessionVisibility_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Represents constant values for a multiplayer session. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "constants": { +/// "system": { +/// "capabilities": { +/// "clientMatchmaking": true, +/// "connectivity": true, +/// "suppressPresenceActivityCheck": true, +/// "gameplay": true, +/// "large": false +/// }, +/// "version": 1, +/// "maxMembersCount": 100, +/// "visibility": "Open", +/// "initiators": [ +/// "3456" +/// ], +/// "inviteProtocol": "party", +/// "reservedRemovalTimeout": 30000, +/// "inactiveRemovalTimeout": 7200000, +/// "readyRemovalTimeout": 180000, +/// "sessionEmptyTimeout": 0, +/// "metrics": { +/// "latency": true, +/// "bandwidthDown": true, +/// "bandwidthUp": true, +/// "custom": true +/// }, +/// "memberInitialization": { +/// "joinTimeout": 4000, +/// "measurementTimeout": 5000, +/// "evaluationTimeout": 5000, +/// "externalEvaluation": false, +/// "membersNeededToStart": 2 +/// }, +/// "peerToPeerRequirements": { +/// "latencyMaximum": 250, +/// "bandwidthMinimum": 10000 +/// }, +/// "peerToHostRequirements": { +/// "latencyMaximum": 250, +/// "bandwidthDownMinimum": 100000, +/// "bandwidthUpMinimum": 1000, +/// "hostSelectionMetric": "bandwidthUp" +/// }, +/// "measurementServerAddresses": { +/// "east.azure.com": { +/// "secureDeviceAddress": "r5Y=" +/// }, +/// "west.azure.com": { +/// "secureDeviceAddress": "rwY=" +/// } +/// } +/// }, +/// "custom": {} +/// } +/// +/// + +public ref class MultiplayerSessionConstants sealed +{ +public: + + /// + /// The maximum number of members in this session. + /// + /// + /// To accommodate a maximum number of members that is over 100, the session must be considered large + /// and have the MultiplayerSessionConstants.CapabilitiesLarge Property set to true. + /// + DEFINE_PTR_PROP_GETSET_OBJ(MaxMembersInSession, max_members_in_session, uint32); + + /// + /// The visibility of this session. + /// + DEFINE_PTR_PROP_GETSET_ENUM_OBJ(MultiplayerSessionVisibility, visibility, Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionVisibility, xbox::services::multiplayer::multiplayer_session_visibility); + + /// + /// A collection of Xbox User IDs indicating who initiated the session (Optional). + /// + property Windows::Foundation::Collections::IVectorView^ InitiatorXboxUserIds { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// A JSON string that specifies the custom constants for the session. These can not be changed after the session is created (Optional). + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(CustomConstantsJson, session_custom_constants_json); + + /// + /// The period of time, in milliseconds, that the session holds a member reservation, after which the member is removed. + /// The default value is 10 seconds. A value of 0 is allowed and indicates an immediate timeout. + /// If the timeout is not specified, it is considered infinite. + /// + DEFINE_PTR_PROP_GET_TIMESPAN_OBJ(MemberReservationTimeout, member_reserved_time_out); + + /// + /// The period of time, in milliseconds, that the session waits for an inactive member reservation + /// to become active, after which the session removes the member. + /// The default value is 2 hours. A value of 0 is allowed and indicates an immediate timeout. + /// If the timeout is not specified, it is considered infinite. + /// + DEFINE_PTR_PROP_GET_TIMESPAN_OBJ(MemberInactiveTimeout, member_inactive_timeout); + + /// + /// The period of time, in milliseconds, that the session waits for a member marked as ready by the + /// shell to be set as active. + /// When the shell launches the title to start a multiplayer game, the member is marked as ready. + /// The default value is 1 minute. A value of 0 is allowed and indicates an immediate timeout. + /// If the timeout is not specified, it is considered infinite. + /// + DEFINE_PTR_PROP_GET_TIMESPAN_OBJ(MemberReadyTimeout, member_ready_timeout); + + /// + /// The period of time, in milliseconds, that the session is empty before the session is deleted. + /// If the session is empty for this timeout, then the session is deleted. + /// The default value is 0, which indicates an immediate timeout. + /// If the timeout is not specified, it is considered infinite. + /// + DEFINE_PTR_PROP_GET_TIMESPAN_OBJ(SessionEmptyTimeout, session_empty_timeout); + + /// + /// Delta from start time representing the point at which results are finalized. + /// If no one has reported (client or server) at this point, we declare the match results incomplete. + /// + DEFINE_PTR_PROP_GET_TIMESPAN_OBJ(ArbitrationTimeout, arbitration_timeout); + + /// + /// Delta from start time representing the point at which, if the session has no active users, the match is canceled. + /// + DEFINE_PTR_PROP_GET_TIMESPAN_OBJ(ForfeitTimeout, forfeit_timeout); + + /// + /// A value that indicates if the session has connectivity capabilities. + /// True if the session has connectivity capabilities, and false otherwise. + /// If false, the session can't enable any metrics and the session members can not set their SecureDeviceAddress. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesConnectivity, capabilities_connectivity, bool); + + /// + /// A value that indicates if active users of the session are demoted to inactive status. + /// By default (if false), active users are required to remain online playing the title, otherwise they get demoted to + /// inactive status. Setting this flag to true disables this check so that members stay active indefinitely. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesSuppressPresenceActivityCheck, capabilities_suppress_presence_activity_check, bool); + + /// + /// A value that indicates whether the session represents actual gameplay, as opposed to setup/menu time + /// such as a lobby or matchmaking. + /// If true, then the session is in gameplay mode. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesGameplay, capabilities_gameplay, bool); + + /// + /// A value that indicates if the session can host a large number of users, which has impact on other session properties. + /// If true, this session can host a large number of users. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesLarge, capabilities_large, bool); + + /// + /// A Boolean value that indicates whether a connection is required for active members in a multiplayer session. + /// If true, this connection is required to have a member be active. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesConnectionRequiredForActiveMember, capabilities_connection_required_for_active_member, bool); + + /// + /// A Boolean value that indicates whether a multiplayer session supports crossplay between Xbox One and Windows 10. + /// True if the multiplayer session supports crossplay. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesCrossplay, capabilities_crossplay, bool); + + /// + /// Aa Boolean value that indicates whether a multiplayer session uses user authorization style, which indicates + /// that the session supports calls from platforms without strong title identity. This capability can't be set on large sessions. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesUserAuthorizationStyle, capabilities_user_authorization_style, bool); + + /// + /// True if team capability is set on the session for a tournament. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesTeam, capabilities_team, bool); + + /// + /// True, if the session can be linked to a search handle for searching. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesSearchable, capabilities_searchable, bool); + + /// + /// True if arbitration capability is set on the session for a tournament. + /// + DEFINE_PTR_PROP_GET_OBJ(CapabilitiesArbitration, capabilities_arbitration, bool); + + /// + /// Indicates if the title wants latency measured for determining connectivity. + /// Requires CapabilitiesConnectivity capability. + /// + DEFINE_PTR_PROP_GET_OBJ(EnableMetricsLatency, enable_metrics_latency, bool); + + /// + /// Indicates if the title wants bandwidth down (host to session members) measured for determining connectivity. + /// Requires CapabilitiesConnectivity capability. + /// + DEFINE_PTR_PROP_GET_OBJ(EnableMetricsBandwidthDown, enable_metrics_bandwidth_down, bool); + + /// + /// Indicates if the title wants bandwidth up (session members to host) measured for determining connectivity. + /// Requires CapabilitiesConnectivity capability. + /// + DEFINE_PTR_PROP_GET_OBJ(EnableMetricsBandwidthUp, enable_metrics_bandwidth_up, bool); + + /// + /// Indicates if the title wants a custom measurement measured for determining connectivity. + /// Requires CapabilitiesConnectivity capability. + /// + DEFINE_PTR_PROP_GET_OBJ(EnableMetricsCustom, enable_metrics_custom, bool); + +#if _MSC_VER >= 1800 + [Windows::Foundation::Metadata::Deprecated("Call MemberInitialization instead", Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0)] +#endif + /// + /// Information about managed initialization for the session. + /// If a ManagedInitialization object is set, the session expects the client system or title to perform + /// initialization following session creation. The timeouts and initialization stages are automatically tracked by + /// the session, including initial QoS if any metrics are set. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerManagedInitialization^ ManagedInitialization + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerManagedInitialization^ get(); + } + + /// + /// Information about managed initialization for the session. + /// If a MemberInitialization object is set, the session expects the client system or title to perform + /// initialization following session creation. The timeouts and initialization stages are automatically tracked by + /// the session, including initial QoS if any metrics are set. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerMemberInitialization^ MemberInitialization + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerMemberInitialization^ get(); + } + + /// + /// An object that contains QoS requirements for the connection between session members. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerPeerToPeerRequirements^ PeerToPeerRequirements + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerPeerToPeerRequirements^ get(); + } + + /// + /// An object that contains QoS requirements for the connection between the host and session members. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerPeerToHostRequirements^ PeerToHostRequirements + { + Microsoft::Xbox::Services::Multiplayer::MultiplayerPeerToHostRequirements^ get(); + } + + /// + /// A JSON string specifying the servers that can be used for QoS measurements. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(MeasurementServerAddressesJson, measurement_server_addresses_json); + +internal: + MultiplayerSessionConstants( + _In_ std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionMemberStatus_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionMemberStatus_WinRT.h new file mode 100644 index 00000000..393d7de6 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionMemberStatus_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Defines values used to indicate status for member of a session. +/// + +public enum class MultiplayerSessionMemberStatus +{ + /// + /// The member slot is reserved for a specific Xbox User ID. + /// This specific member must join the session to fill the reservation before + /// the JoinTimeout or they will be removed. + /// + Reserved = xbox::services::multiplayer::multiplayer_session_member_status::reserved, + + /// + /// The member is inactive in the current title. + /// The member may be active in another title as specified by ActiveTitleId, + /// If a inactive member doesn't mark themselves as Active within the MemberInactiveTimeout they will be removed from the session. + /// + Inactive = xbox::services::multiplayer::multiplayer_session_member_status::inactive, + + /// + /// When the shell launches the title to start a multiplayer game, the member is marked as ready. + /// If a ready member doesn't mark themselves as Active within the MemberReadyTimeout they will be marked as inactive. + /// + Ready = xbox::services::multiplayer::multiplayer_session_member_status::ready, + + /// + /// The member is active in the current title. + /// + Active = xbox::services::multiplayer::multiplayer_session_member_status::active +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.cpp new file mode 100644 index 00000000..de14c7f7 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.cpp @@ -0,0 +1,109 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionMember_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionMember::MultiplayerSessionMember( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + THROW_INVALIDARGUMENT_IF_NULL(cppObj); + THROW_INVALIDARGUMENT_IF_NULL(m_cppObj->member_measurements()); + + m_roles = ref new Platform::Collections::Map(); + for (const auto& role : m_cppObj->roles()) + { + m_roles->Insert(ref new Platform::String(role.first.c_str()), ref new Platform::String(role.second.c_str())); + } + + m_memberMeasurements = UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + *m_cppObj->member_measurements() + ); + + if (!m_cppObj->tournament_team_session_reference().is_null()) + { + m_tournamentTeamSessionRef = ref new MultiplayerSessionReference(m_cppObj->tournament_team_session_reference()); + } + + m_results = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj->results()); +} + +IVector^ +MultiplayerSessionMember::MembersInGroup::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj>( + m_cppObj->members_in_group() + ); +} + +IVector^ +MultiplayerSessionMember::MemberMeasurements::get() +{ + return m_memberMeasurements; +} + +IVector^ +MultiplayerSessionMember::Groups::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj->groups()); +} + +void +MultiplayerSessionMember::Groups::set(_In_ IVector^ value) +{ + m_cppObj->set_groups(UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(value->GetView())); +} + +IVector^ +MultiplayerSessionMember::Encounters::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj->encounters()); +} + +void +MultiplayerSessionMember::Encounters::set(_In_ IVector^ value) +{ + m_cppObj->set_encounters(UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(value->GetView())); +} + +Windows::Foundation::Collections::IMap^ +MultiplayerSessionMember::Results::get() +{ + return m_results; +} + +std::shared_ptr +MultiplayerSessionMember::GetCppObj() const +{ + return m_cppObj; +} + +MultiplayerSessionReference^ +MultiplayerSessionMember::TournamentTeamSessionRef::get() +{ + return m_tournamentTeamSessionRef; +} + +IMapView^ +MultiplayerSessionMember::Roles::get() +{ + return m_roles->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.h new file mode 100644 index 00000000..13e814a5 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionMember_WinRT.h @@ -0,0 +1,342 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionMemberStatus_WinRT.h" +#include "MultiplayerQualityOfServiceMeasurements_WinRT.h" +#include "NetworkAddressTranslationSetting_WinRT.h" +#include "MultiplayerMeasurementFailure_WinRT.h" +#include "TournamentRegistrationReason_WinRT.h" +#include "TournamentRegistrationState_WinRT.h" +#include "TournamentGameResultState_WinRT.h" +#include "TournamentGameResultSource_WinRT.h" +#include "TournamentArbitrationStatus_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "TournamentTeamResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +// Example snippet of response +// +// "members": +// { +// "1": +// { +// "constants": +// { +// "system": +// { +// "index": 0, +// "xuid": "12345678", +// +// // Run initialization for this user. Defaults to false. +// // Ignored if no "memberInitialization" section is set for the session. +// "initialize": true, +// +// // When match adds a user to a session, it can provide some context around how and why they were matched into the session. +// "matchmakingResult": +// { +// // This is a copy of the user's serverMeasurements from the matchmaking session. +// "serverMeasurements": +// { +// "east.azure.com": +// { +// "latency": 233 // Milliseconds +// } +// } +// } +// } +// "custom": +// { +// } +// } +// "properties": +// { +// "system": +// { +// // These flags control the member status and "activeTitle", and are mutually exclusive (it's an error to set both to true). +// // For each, false is the same as not present. The default status is "inactive", i.e. neither present. +// "ready": true, +// "active": false, +// +// "secureDeviceAddress": "ryY=", // Base64 blob, or not present. Empty-string is the same as not present. +// +// // List of members in my group, by index. +// // If a "initializationGroup" list is set, the member's own index will always be added if it isn't already present. +// // During managed initialization, if any members in the list fail, this member will also fail. +// "initializationGroup": [ 5 ], +// +// // QoS measurements by secure device address. Like all fields, "measurements" must be updated as a whole. It should be set once when measurement is complete, not incrementally. +// // If a "measurements" object is set, it can't contain an entry for the member's own address. +// "measurements": +// { +// "e6Kv5zY=": +// { +// "latency": 5953, // Milliseconds +// "bandwidthDown": 19342, // Kilobits per second +// "bandwidthUp": 944, // Kilobits per second +// "custom": { } +// } +// }, +// +// // QoS measurements by game-server connection string. Like all fields, "serverMeasurements" must be updated as a whole, so it should be set once when measurement is complete. +// // If empty, it means that none of the measurements completed within the "serverMeasurementTimeout". +// "serverMeasurements": +// { +// "east.azure.com": +// { +// "latency": 233 // Milliseconds +// } +// } +// } +// "custom": +// { +// } +// } +// +// // Only if the member has accepted. Optional (not set if no gamertag claim was found). +// "gamertag": "stacy", +// +// // This is set when the member uploads a secure device address. It's a case-insensitive string that can be used for equality comparisons. +// "deviceToken": "9f4032ba7", +// +// // This is set to "open", "moderate", or "strict" when the member uploads a secure device address. +// "nat": "strict", +// +// // This value is removed once the user does their first PUT to the session. +// "reserved": true, +// +// // If the member is active, this is the title in which they are active, in decimal. +// "activeTitleId": "8397267", +// +// // The time the user joined the session. If "reserved" is true, the time the reservation was made. +// "joinTime": "2009-06-15T13:45:30.0900000Z", +// +// Present if this member is in the properties/system/turn array, otherwise not. +// "turn": true, +// +// // Set when transitioning out of the "joining" or "measuring" stage if this member doesn't pass. +// // In order of precedence, could be set to "timeout", "latency", "bandwidthDown", "bandwidthUp", or "group". +// // The only possible value at the end of "joining" is "group". (On timeout from "joining", the reservation is removed.) +// "failedMetric": "latency", +// +// // If "memberInitialization" is set and the member was added with "initialize": true, this is set to the initialization episode that the member will participate in. +// // Zero is a special value used for the members added to a new session at create time. +// "initializationEpisode": 0, +// +// // The next member's index, which is the same as 'next' below if there's no more. +// "next": 4 +// }, +// "4": { "next": 5 /* etc */ } +// }, + +/// +/// Represents a reference to a member in a multiplayer session. +/// +public ref class MultiplayerSessionMember sealed +{ +public: + /// + /// The Id for this multiplayer session member. + /// + DEFINE_PTR_PROP_GET_OBJ(MemberId, member_id, uint32); + + /// + /// The Id of this members' team in a tournament. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(TeamId, team_id); + + /// + /// The Xbox User ID of the member. This value is only known if the member has accepted. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// A JSON string that specifies the custom player constants for the member. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(MemberCustomConstantsJson, member_custom_constants_json); + + /// + /// (Optional) The base64 encoded secure device address of the member. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(SecureDeviceAddressBase64, secure_device_base_address64); + + /// + /// A collection of role types to role names for this member. (Optional) + /// + property Windows::Foundation::Collections::IMapView^ Roles + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// A JSON string that specifies the custom player properties for the member. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(MemberCustomPropertiesJson, member_custom_properties_json); + + // Other properties + + /// + /// (Optional) The Gamertag of the member. This value is only known if the member has accepted. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(Gamertag, gamertag); + + /// + /// The status of this member. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(Status, status, Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionMemberStatus); + + /// + /// A value that indicates if this member has an available turn in the session. + /// + DEFINE_PTR_PROP_GET_OBJ(IsTurnAvailable, is_turn_available, bool); + + /// + /// A value that indicates if this multiplayer session member is the player whose Xbox Live context was used to + /// create or retrieve the current MultiplayerSession object. + /// + DEFINE_PTR_PROP_GET_OBJ(IsCurrentUser, is_current_user, bool); + + /// + /// A value that indicates if a QoS initialization stage has been requested for this user during managed initialization. + /// Ignored if there is not a "memberInitialization" section for the session. + /// Defaults to false. + /// + DEFINE_PTR_PROP_GET_OBJ(InitializeRequested, initialize_requested, bool); + + /// + /// A JSON string id that defines items that provide some matchmaking context around how and why they were matched into the session. + /// This is a copy of the user's QoS serverMeasurements from the matchmaking session. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(MatchmakingResultServerMeasurementsJson, matchmaking_result_server_measurements_json); + + /// + /// Identifier of a JSON string defining the QoS measurements for the multiplayer session member in a session. + /// + /// + /// Like all fields, "serverMeasurements" must be updated as a whole, so it should be set once when measurement is complete. + /// If it is empty, it means that none of the measurements completed within the "serverMeasurementTimeout". + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(MemberServerMeasurementsJson, member_server_measurements_json); + + /// + /// A collection of members in any groups to which the session member belongs. + /// + /// + /// If a "initializationGroup" list is set, the member's own index is always added if it isn't already present. + /// During managed initialization, if any members in the list fail, this member will also fail. + /// + property Windows::Foundation::Collections::IVector^ MembersInGroup { Windows::Foundation::Collections::IVector^ get(); } + + /// + /// QoS measurements for the member's secure device address. + /// + /// + /// Like all fields, "measurements" must be updated as a whole. It should be set once when measurement is complete, not incrementally. + /// If a "measurements" object is set, it can't contain an entry for the member's own address. + /// + property Windows::Foundation::Collections::IVector^ MemberMeasurements { Windows::Foundation::Collections::IVector^ get(); } + + /// + /// The case-insensitive device token string for the multiplayer session member, which can be used for equality comparisons. + /// The token is set when the member uploads a secure device address. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(DeviceToken, device_token); + + /// + /// The device's NAT setting when the member uploads a secure device address. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(Nat, nat, Microsoft::Xbox::Services::Multiplayer::NetworkAddressTranslationSetting); + + /// + /// The identifier of the title for the game being played in the session, if the member is active. + /// + DEFINE_PTR_PROP_GET_OBJ(ActiveTitleId, active_title_id, uint32); + + /// + /// The number of the initialization episode that the member participates in during managed initialization. + /// This value is only useful to read when the title is manually managing its own QoS. + /// + /// + /// Users join sessions in batches. Each batch of users is assigned to a new initialization episode. + /// The initialization episode number indicates the set of users that require QoS. + /// Initialization episode 0 indicates that the member is not taking part in managed initialization. + /// Initialization episode 1 is a special value used for the members added to a new session at create time. + /// + /// If the "memberInitialization" section is set and the member was added with "initialize":true, + /// this is set to the initialization episode that the member will participate in; otherwise it is 0. + /// + DEFINE_PTR_PROP_GET_OBJ(InitializationEpisode, initialization_episode, uint32); + + /// + /// The time the user joined the session. If "reserved" is true, this is the time when the reservation was made. + /// + DEFINE_PTR_PROP_GET_DATETIME_OBJ(JoinTime, join_time); + + /// + /// The cause of why the initialization failed for the member. + /// If there is no failure, this value is MultiplayerMeasurementFailure::None. + /// Set when transitioning out of the "joining" or "measuring" stage if this member doesn't pass. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(InitializationFailureCause, initialization_failure_cause, Microsoft::Xbox::Services::Multiplayer::MultiplayerMeasurementFailure); + + /// + /// The tournament team session reference. + /// + property MultiplayerSessionReference^ TournamentTeamSessionRef { MultiplayerSessionReference^ get(); } + + /// + /// Gets or sets a string vector of group names for the current user indicating which groups that user + /// was part of during a multiplayer session. + /// + property Windows::Foundation::Collections::IVector^ Groups + { + Windows::Foundation::Collections::IVector^ get(); + void set(_In_ Windows::Foundation::Collections::IVector^ value); + } + + /// + /// Gets a list of group names for the current user indicating which groups that user encountered during a multiplayer session. + /// + property Windows::Foundation::Collections::IVector^ Encounters + { + Windows::Foundation::Collections::IVector^ get(); + void set(_In_ Windows::Foundation::Collections::IVector^ value); + } + + /// + /// The arbitration results submitted by the member. + /// + property Windows::Foundation::Collections::IMap^ Results + { + Windows::Foundation::Collections::IMap^ get(); + } + + /// + /// The current status/state of the results. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(ArbitrationStatus, arbitration_status, Microsoft::Xbox::Services::Tournaments::TournamentArbitrationStatus); + +internal: + MultiplayerSessionMember( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; +private: + std::shared_ptr m_cppObj; + Platform::Collections::Map^ m_roles; + Windows::Foundation::Collections::IVector^ m_memberMeasurements; + Windows::Foundation::Collections::IMap^ m_results; + MultiplayerSessionReference^ m_tournamentTeamSessionRef; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.cpp new file mode 100644 index 00000000..97793fbb --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.cpp @@ -0,0 +1,77 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionProperties_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionProperties::MultiplayerSessionProperties( + std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + THROW_INVALIDARGUMENT_IF_NULL(m_cppObj); + m_turnCollection = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->turn_collection())->GetView(); + + Vector^ responseVector = ref new Vector(); + const std::vector& cppSessionOwners = m_cppObj->session_owner_indices(); + for (auto& owner : cppSessionOwners) + { + responseVector->Append(owner); + } + m_sessionOwnerIndices = responseVector->GetView(); +} + + +IVectorView^ +MultiplayerSessionProperties::Keywords::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj->keywords())->GetView(); +} + +void +MultiplayerSessionProperties::Keywords::set(_In_ IVectorView^ value) +{ + m_cppObj->set_keywords( UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(value) ); +} + +IVectorView^ +MultiplayerSessionProperties::TurnCollection::get() +{ + return m_turnCollection; +} + +void +MultiplayerSessionProperties::TurnCollection::set(_In_ IVectorView^ value) +{ + m_cppObj->set_turn_collection(UtilsWinRT::CreateStdVectorObjectFromPlatformVectorObj>(value)); + m_turnCollection = value; +} + +IVectorView^ +#pragma warning(suppress: 28251) +MultiplayerSessionProperties::ServerConnectionStringCandidates::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj->server_connection_string_candidates())->GetView(); +} + +IVectorView^ +MultiplayerSessionProperties::SessionOwnerIndices::get() +{ + return m_sessionOwnerIndices; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.h new file mode 100644 index 00000000..f5532f03 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionProperties_WinRT.h @@ -0,0 +1,178 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionRestriction_WinRT.h" +#include "MultiplayerSessionMember_WinRT.h" +#include "MatchmakingStatus_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "Utils_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents multiplayer session properties. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +///"properties": { +/// "system": { +/// "keywords": [ +/// "hello" +/// ], +/// "turn": [ +/// 0 +/// ], +/// "host": "99e4c701", +/// "initializationSucceeded": true, +/// "joinRestriction": "None", +/// "readRestriction": "None", +/// "serverConnectionStringCandidates": [ +/// "west.azure.com", +/// "east.azure.com" +/// ], +/// "matchmaking": { +/// "clientResult": { +/// "status": "Searching", +/// "statusDetails": "Description", +/// "typicalWait": 30, +/// "targetSessionRef": { +/// "scid": "1ECFDB89-36EB-4E59-8901-11F7393689AE", +/// "templateName": "capture-the-flag", +/// "name": "2D58F65F-0E3C-4F1F-8277-2BC9873FDB23" +/// } +/// }, +/// "targetSessionConstants": {}, +/// "serverConnectionString": "west.azure.com" +/// }, +/// "matchmakingResubmit": true +/// }, +/// "custom": {} +/// }, +/// +/// +public ref class MultiplayerSessionProperties sealed +{ +public: + /// + /// (Optional) A collection of case-insensitive keywords associated with the session. This value can be empty. + /// When changing keywords, call MultiplayerService::WriteSessionAsync to write the changes to the service. + /// + property Windows::Foundation::Collections::IVectorView^ Keywords + { + Windows::Foundation::Collections::IVectorView^ get(); + void set(_In_ Windows::Foundation::Collections::IVectorView^ value); + } + + /// + /// Gets or sets the restriction that is applied to members when joining an open session. + /// Defaults to "none". + /// + /// + /// The join restriction has no effect on reservations, which means that it has no impact on "private" and "visible" sessions. + /// + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can join without a reservation. + /// + /// The join restriction must be at least as closed as the ReadRestriction restriction. + /// For example, ReadRestriction cannot be set to MultiplayerSessionReadRestriction.Local without also setting + /// JoinRestriction to MultiplayerSessionJoinRestriction.Local. + /// + DEFINE_PTR_PROP_GETSET_ENUM_OBJ(JoinRestriction, join_restriction, Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionRestriction, xbox::services::multiplayer::multiplayer_session_restriction); + + /// + /// Gets or sets the restriction that is applied to members when reading an open session. + /// Defaults to "none". + /// + /// + /// The read restriction has no effect on reservations, which means that it has no impact on "private" and "visible" sessions. + /// + /// If "local", only users whose token's DeviceId matches someone else already in the session and "active": true. + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can read without a reservation. + /// + /// The read restriction must be at least as open as the JoinRestriction restriction. + /// For example, JoinRestriction cannot be set to MultiplayerSessionJoinRestriction.Followed without also setting + /// ReadRestriction to MultiplayerSessionReadRestriction.Followed. + /// + DEFINE_PTR_PROP_GETSET_ENUM_OBJ(ReadRestriction, read_restriction, Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionRestriction, xbox::services::multiplayer::multiplayer_session_restriction); + + /// + /// A collection of MultiplayerSessionMember objects indicating who has played turns in the sessions. + /// When changing, call MultiplayerService::WriteSessionAsync to write the changes to the service. + /// + property Windows::Foundation::Collections::IVectorView^ TurnCollection + { + Windows::Foundation::Collections::IVectorView^ get(); + void set(_In_ Windows::Foundation::Collections::IVectorView^ value); + } + + /// + /// A JSON string of title-defined constants for the target session to use in matchmaking. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(MatchmakingTargetSessionConstantsJson, matchmaking_target_session_constants_json); + + /// + /// A JSON string that specifies the custom properties for the session. These can be changed anytime. + /// When changing, call MultiplayerService::WriteSessionAsync to write the changes to the service. + /// + DEFINE_PTR_PROP_GET_STR_FROM_JSON_OBJ(SessionCustomPropertiesJson, session_custom_properties_json); + + /// + /// Force a specific connection string to be used, which is useful for join in progress scenarios. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(MatchmakingServerConnectionString, matchmaking_server_connection_string); + + /// + /// The ordered list of connection strings that the session can use to connect to a game server. Generally titles should use the first on + /// the list, but sophisticated titles could use a custom mechanism for choosing one of the others (e.g. based on load). + /// + property Windows::Foundation::Collections::IVectorView^ ServerConnectionStringCandidates + { + _In_ Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// Member index of owners of the session. + /// + property Windows::Foundation::Collections::IVectorView^ SessionOwnerIndices + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// A token representing the host device. + /// Must match the "deviceToken" of at least one member, otherwise this field is deleted. + /// If "peerToHostRequirements" is set and "host" is set, the measurement stage assumes that + /// the given host is the correct host and only measures metrics to that host. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(HostDeviceToken, host_device_token); + + /// + /// A value that indicates if the session is closed. + /// Thsi value controls whether a session is joinable, independent of visibility, joinrestriction, and available space in the session. + /// Does not affect reservations. Defaults to false. + /// + DEFINE_PTR_PROP_GET_OBJ(Closed, closed, bool); + +internal: + MultiplayerSessionProperties( + std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_turnCollection; + Windows::Foundation::Collections::IVectorView^ m_sessionOwnerIndices; + MultiplayerSessionReference^ m_matchmakingTargetSessionReference; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.cpp new file mode 100644 index 00000000..ab646c60 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.cpp @@ -0,0 +1,70 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionReference::MultiplayerSessionReference( +xbox::services::multiplayer::multiplayer_session_reference cppObj + ) : + m_cppObj(cppObj) +{ +} + +MultiplayerSessionReference::MultiplayerSessionReference( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName, + _In_ Platform::String^ sessionName + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(serviceConfigurationId); + THROW_INVALIDARGUMENT_IF_NULL(sessionTemplateName); + THROW_INVALIDARGUMENT_IF_NULL(sessionName); + + m_cppObj = xbox::services::multiplayer::multiplayer_session_reference( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(sessionTemplateName), + STRING_T_FROM_PLATFORM_STRING(sessionName) + ); +} + +Platform::String^ +MultiplayerSessionReference::ToUriPath() +{ + CONVERT_STD_EXCEPTION( + return ref new Platform::String(m_cppObj.to_uri_path().c_str()) + ); +} + +MultiplayerSessionReference^ +MultiplayerSessionReference::ParseFromUriPath( + _In_ Platform::String^ uriPath + ) +{ + CONVERT_STD_EXCEPTION( + return ref new MultiplayerSessionReference( + xbox::services::multiplayer::multiplayer_session_reference::parse_from_uri_path( + STRING_T_FROM_PLATFORM_STRING(uriPath) + ) + ) + ); +} + +const xbox::services::multiplayer::multiplayer_session_reference& +MultiplayerSessionReference::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.h new file mode 100644 index 00000000..70e22bf7 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionReference_WinRT.h @@ -0,0 +1,91 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "Macros_WinRT.h" +#include "user_context.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents a reference to a multiplayer session. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "sessionRef": { +/// "scid": "foo", +/// "templateName" : "bar", +/// "name" : "session-seven" +/// } +/// +/// +public ref class MultiplayerSessionReference sealed +{ +public: + /// + /// Constructs the MultiplayerSession object with data about the session. + /// + /// A service configuration ID appropriate for the title. + /// The name of the template for the session to be based on. + /// A unique name for the session. + MultiplayerSessionReference( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ sessionTemplateName, + _In_ Platform::String^ sessionName + ); + + /// + /// The service configuration ID specific to the title. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The name of the template for the session. + /// + DEFINE_PROP_GET_STR_OBJ(SessionTemplateName, session_template_name); + + /// + /// The unique name of the session. + /// + DEFINE_PROP_GET_STR_OBJ(SessionName, session_name); + + /// + /// Returns a URI path representation of the session reference. + /// + /// + /// A string indicating the URI path. + /// + Platform::String^ ToUriPath(); + + /// + /// Returns the session reference parsed from the specified URI. + /// + /// A string indicating the parsed URI path. + /// + /// An object representing the multiplayer session reference. + /// + static MultiplayerSessionReference^ MultiplayerSessionReference::ParseFromUriPath( + _In_ Platform::String^ uriPath + ); + +internal: + MultiplayerSessionReference( + xbox::services::multiplayer::multiplayer_session_reference cppObj + ); + + const xbox::services::multiplayer::multiplayer_session_reference& GetCppObj() const; +private: + xbox::services::multiplayer::multiplayer_session_reference m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionRestriction_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionRestriction_WinRT.h new file mode 100644 index 00000000..6015725f --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionRestriction_WinRT.h @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Defines values used to indicate restrictions on the users who can join a session. +/// + +public enum class MultiplayerSessionRestriction +{ + /// + /// The unrecognized restriction type. This value should never be used because it causes an exception to be thrown. + /// + Unknown = xbox::services::multiplayer::multiplayer_session_restriction::unknown, + + /// + /// Default value, no restriction. + /// + None = xbox::services::multiplayer::multiplayer_session_restriction::none, + + /// + /// Only the following users can read/join the session: + /// * members of the session + /// * Users that have been invited to the session + /// * Users that are signed in to the same console as a someone already in the session + /// + /// This means that only users whose token's DeviceId matches someone else already in the session and have "active" set to true + /// can access the session. + /// + Local = xbox::services::multiplayer::multiplayer_session_restriction::local, + + /// + /// If "followed", only local users (as defined above) and users who are followed by an existing (not reserved) member of the session can join without a reservation. + /// + Followed = xbox::services::multiplayer::multiplayer_session_restriction::followed, + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.cpp new file mode 100644 index 00000000..ea4e209f --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.cpp @@ -0,0 +1,34 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionRoleTypes_WinRT.h" +#include "Macros_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionRoleTypes::MultiplayerSessionRoleTypes( + _In_ std::shared_ptr cppObj +) : + m_cppObj(std::move(cppObj)) +{ + m_roleTypes = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj->role_types()); +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerSessionRoleTypes::RoleTypes::get() +{ + return m_roleTypes->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.h new file mode 100644 index 00000000..82ce278e --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionRoleTypes_WinRT.h @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" +#include "MultiplayerRoleType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents session role type values for a multiplayer session. +/// +public ref class MultiplayerSessionRoleTypes sealed +{ +public: + /// + /// A collection of role types. + /// + property Windows::Foundation::Collections::IMapView^ RoleTypes + { + Windows::Foundation::Collections::IMapView^ get(); + } + +internal: + MultiplayerSessionRoleTypes( + _In_ std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; + Platform::Collections::Map^ m_roleTypes; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.cpp new file mode 100644 index 00000000..a114213d --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.cpp @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "MultiplayerSessionStates_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionStates::MultiplayerSessionStates( + _In_ xbox::services::multiplayer::multiplayer_session_states cppObj + ) : + m_cppObj(cppObj) +{ + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj.session_reference()); + m_keywords = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.keywords())->GetView(); +} + +MultiplayerSessionReference^ +MultiplayerSessionStates::SessionReference::get() +{ + return m_sessionReference; +} + +IVectorView^ +MultiplayerSessionStates::Keywords::get() +{ + return m_keywords; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.h new file mode 100644 index 00000000..6d8407e8 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionStates_WinRT.h @@ -0,0 +1,115 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "Macros_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MultiplayerSessionStatus_WinRT.h" +#include "MultiplayerSessionVisibility_WinRT.h" +#include "MultiplayerSessionRestriction_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +//Example: + + +/// +/// Represents high-level information about the state of a session. +/// +/// +/// The following example shows the format of the JSON object that represents +/// this class: +/// +/// "results": [ +/// { +/// "xuid": "9876", +/// "startTime": "2013-02-01T00:00:00Z", +/// "sessionRef": { +/// "scid": "foo", +/// "templateName": "bar", +/// "name": "session-seven" +/// }, +/// "accepted": 4, +/// "status": "Active", +/// "visibility": "Open", +/// "joinRestriction": "Local", +/// "myTurn": true, +/// "keywords": [ +/// "one", +/// "two" +/// ] +/// } +/// ] +/// +/// +public ref class MultiplayerSessionStates sealed +{ +public: + /// + /// The data and time that the session began. + /// + DEFINE_PROP_GET_DATETIME_OBJ(StartTime, start_time); + + /// + /// A reference to the object that contains identifying information for the session. + /// + property MultiplayerSessionReference^ SessionReference { MultiplayerSessionReference^ get(); } + + /// + /// The current status of the session. + /// + DEFINE_PROP_GET_ENUM_OBJ(Status, status, MultiplayerSessionStatus); + + /// + /// The visibility state of the session. Whether other users can see, or join, etc. + /// + DEFINE_PROP_GET_ENUM_OBJ(Visibility, visibility, MultiplayerSessionVisibility); + + /// + /// Indicates if it is the session member's turn. + /// + DEFINE_PROP_GET_OBJ(IsMyTurn, is_my_turn, bool); + + /// + /// The Xbox User ID of the member. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// Approximate number of non-reserved members that have been accepted into the session. + /// + DEFINE_PROP_GET_OBJ(AcceptedMemberCount, accepted_member_count, uint32); + + /// + /// The restriction applied to the member when joining the session. + /// + DEFINE_PROP_GET_ENUM_OBJ(JoinRestriction, join_restriction, MultiplayerSessionRestriction); + + /// + /// (Optional) A collection of case-insensitive keywords associated with the session. This value might be empty. + /// + property Windows::Foundation::Collections::IVectorView^ Keywords + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + MultiplayerSessionStates( + _In_ xbox::services::multiplayer::multiplayer_session_states cppObj + ); + +private: + xbox::services::multiplayer::multiplayer_session_states m_cppObj; + MultiplayerSessionReference^ m_sessionReference; + Windows::Foundation::Collections::IVectorView^ m_keywords; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionStatus_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionStatus_WinRT.h new file mode 100644 index 00000000..a8502985 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionStatus_WinRT.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values that indicate the current status of a session. +/// +public enum class MultiplayerSessionStatus +{ + /// + /// The server returned an unrecognized response. + /// + Unknown = xbox::services::multiplayer::multiplayer_session_status::unknown, + + /// + /// The session is active and there is at least one user. + /// + Active = xbox::services::multiplayer::multiplayer_session_status::active, + + /// + /// The session is inactive. This means that no users in the session are + /// active or all users left the session. + /// + Inactive = xbox::services::multiplayer::multiplayer_session_status::inactive, + + /// + /// The session is reserved. This means one for more users have not + /// accepted the session invite. + /// + Reserved = xbox::services::multiplayer::multiplayer_session_status::reserved +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.cpp new file mode 100644 index 00000000..1cbb32ed --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.cpp @@ -0,0 +1,63 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSessionTournamentsServer_WinRT.h" +#include "TournamentReference_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSessionTournamentsServer::MultiplayerSessionTournamentsServer( + _In_ xbox::services::multiplayer::multiplayer_session_tournaments_server cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + if (!m_cppObj.next_game_session_reference().is_null()) + { + m_nextGameSessionRef = ref new MultiplayerSessionReference(m_cppObj.next_game_session_reference()); + } + + if (!m_cppObj.tournament_reference().is_null()) + { + m_tournamentRef = ref new Microsoft::Xbox::Services::Tournaments::TournamentReference(m_cppObj.tournament_reference()); + } + + m_lastTeamResult = ref new Microsoft::Xbox::Services::Tournaments::TournamentTeamResult(m_cppObj.last_team_result()); + + m_teams = UtilsWinRT::CreatePlatformMapObjectWithStringKeyFromStdMapObj(m_cppObj.teams()); +} + +MultiplayerSessionReference^ +MultiplayerSessionTournamentsServer::NextGameSessionRef::get() +{ + return m_nextGameSessionRef; +} + +TournamentReference^ +MultiplayerSessionTournamentsServer::TournamentReference::get() +{ + return m_tournamentRef; +} + +TournamentTeamResult^ +MultiplayerSessionTournamentsServer::LastTeamResult::get() +{ + return m_lastTeamResult; +} + +Windows::Foundation::Collections::IMapView^ +MultiplayerSessionTournamentsServer::Teams::get() +{ + return m_teams->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.h new file mode 100644 index 00000000..d6d92d91 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionTournamentsServer_WinRT.h @@ -0,0 +1,94 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "TournamentRegistrationState_WinRT.h" +#include "TournamentRegistrationReason_WinRT.h" +#include "TournamentGameResultState_WinRT.h" +#include "TournamentGameResultSource_WinRT.h" +#include "TournamentReference_WinRT.h" +#include "TournamentTeamResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents the server that allows multiplayer session discovery to collaborate in a matchmaking session. +/// +public ref class MultiplayerSessionTournamentsServer sealed +{ +public: + /// + /// The tournament reference. + /// + property Microsoft::Xbox::Services::Tournaments::TournamentReference^ TournamentReference + { + Microsoft::Xbox::Services::Tournaments::TournamentReference^ get(); + } + + /// + /// The teams in the tournament + /// + property Windows::Foundation::Collections::IMapView^ Teams + { + Windows::Foundation::Collections::IMapView^ get(); + } + + /// + /// The tournament registration state of the team. + /// + DEFINE_PROP_GET_ENUM_OBJ(RegistrationState, registration_state, Microsoft::Xbox::Services::Tournaments::TournamentRegistrationState); + + /// + /// The tournament registration reaon for the certain state. + /// + DEFINE_PROP_GET_ENUM_OBJ(RegistrationReason, registration_reason, Microsoft::Xbox::Services::Tournaments::TournamentRegistrationReason); + + /// + /// The next tournament game start time. + /// + DEFINE_PROP_GET_DATETIME_OBJ(NextGameStartTime, next_game_start_time); + + /// + /// The next tournament game session reference. + /// + property MultiplayerSessionReference^ NextGameSessionRef { MultiplayerSessionReference^ get(); } + + /// + /// The last tournament game end time. + /// + DEFINE_PROP_GET_DATETIME_OBJ(LastGameEndTime, last_game_end_time); + + /// + /// The last game's state for the tournament. + /// + property Microsoft::Xbox::Services::Tournaments::TournamentTeamResult^ LastTeamResult + { + Microsoft::Xbox::Services::Tournaments::TournamentTeamResult^ get(); + } + + /// + /// The source for the last game's state of the tournament. + /// + DEFINE_PROP_GET_ENUM_OBJ(LastGameResultSource, last_game_result_source, Microsoft::Xbox::Services::Tournaments::TournamentGameResultSource); + +internal: + MultiplayerSessionTournamentsServer(_In_ xbox::services::multiplayer::multiplayer_session_tournaments_server cppObj); + +private: + xbox::services::multiplayer::multiplayer_session_tournaments_server m_cppObj; + MultiplayerSessionReference^ m_nextGameSessionRef; + Microsoft::Xbox::Services::Tournaments::TournamentReference^ m_tournamentRef; + Microsoft::Xbox::Services::Tournaments::TournamentTeamResult^ m_lastTeamResult; + Platform::Collections::Map^ m_teams; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionVisibility_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionVisibility_WinRT.h new file mode 100644 index 00000000..83bf47e4 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionVisibility_WinRT.h @@ -0,0 +1,52 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values that indicate how visible a session is. +/// +public enum class MultiplayerSessionVisibility +{ + /// + /// Unknown. + /// + Unknown = xbox::services::multiplayer::multiplayer_session_visibility::unknown, + + /// + /// Ignore the SessionVisibility filter. + /// + Any = xbox::services::multiplayer::multiplayer_session_visibility::any, + + /// + /// The session is private and it's not visible to other users who + /// aren't in the session. Attempting to join a private session causes the server to return HTTP_E_STATUS_FORBIDDEN. + /// + Private = xbox::services::multiplayer::multiplayer_session_visibility::private_session, + + /// + /// The session is visible to other users who aren't in the session, but the session is read-only to them and they can't join. + /// Attempting to join a visible session causes the service to return HTTP_E_STATUS_FORBIDDEN. + /// + Visible = xbox::services::multiplayer::multiplayer_session_visibility::visible, + + /// + /// The session is full and cannot be joined by anyone. + /// Joining an open but full session causes the service to return HTTP_E_STATUS_BAD_REQUEST (400). + /// + Full = xbox::services::multiplayer::multiplayer_session_visibility::full, + + /// + /// The session is open and can be joined by anyone. + /// + Open = xbox::services::multiplayer::multiplayer_session_visibility::open +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSessionWriteMode_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSessionWriteMode_WinRT.h new file mode 100644 index 00000000..7398fef1 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSessionWriteMode_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values used to indicate modes in MultiplayerService.WriteSessionAsync calls. +/// +public enum class MultiplayerSessionWriteMode +{ + /// + /// Create a new multiplayer session. Fails with HTTP_E_STATUS_PRECOND_FAILED if the session already exists. + /// + CreateNew = xbox::services::multiplayer::multiplayer_session_write_mode::create_new, + + /// + /// Either update or create a new session. It doesn't matter whether the session exists or not. + /// + UpdateOrCreateNew = xbox::services::multiplayer::multiplayer_session_write_mode::update_or_create_new, + + /// + /// Updates an existing multiplayer session. Fails with HTTP_E_STATUS_PRECOND_FAILED if the session doesn't exist. + /// + UpdateExisting = xbox::services::multiplayer::multiplayer_session_write_mode::update_existing, + + /// + /// Updates an existing multiplayer session to resolve any conflict between two devices trying to perform an operation + /// at the same time. Fails with HTTP_E_STATUS_PRECOND_FAILED (HTTP status 412) if eTag on the local session doesn't match + /// the eTag on the server. Fails with the same error code if the session does not exist. + /// + SynchronizedUpdate = xbox::services::multiplayer::multiplayer_session_write_mode::synchronized_update, +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.cpp new file mode 100644 index 00000000..58d64179 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.cpp @@ -0,0 +1,767 @@ +////********************************************************* +//// +//// Copyright (c) Microsoft. All rights reserved. +//// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +//// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +//// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +//// +////********************************************************* + +#include "pch.h" +#include "MultiplayerSession_WinRT.h" +#include "Utils_WinRT.h" +#include "XboxLiveContext_WinRT.h" +#include "user_context.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::GameServerPlatform; +using namespace Microsoft::Xbox::Services::Tournaments; +using namespace xbox::services; +using namespace xbox::services::multiplayer; +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSession::MultiplayerSession( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + THROW_INVALIDARGUMENT_IF_NULL(m_cppObj); + + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj->session_reference()); + m_sessionProperties = ref new MultiplayerSessionProperties(m_cppObj->session_properties()); + m_sessionRoleTypes = ref new MultiplayerSessionRoleTypes(m_cppObj->session_role_types()); + m_sessionConstants = ref new MultiplayerSessionConstants(m_cppObj->session_constants()); + m_matchmakingServer = ref new MultiplayerSessionMatchmakingServer(m_cppObj->matchmaking_server()); + m_tournamentsServer = ref new MultiplayerSessionTournamentsServer(m_cppObj->tournaments_server()); + m_arbitrationServer = ref new MultiplayerSessionArbitrationServer(m_cppObj->arbitration_server()); +} + +MultiplayerSession::MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(xboxLiveContext); + m_cppObj = std::make_shared( + STRING_T_FROM_PLATFORM_STRING(xboxLiveContext->User->XboxUserId) + ); +} + +#if TV_API +MultiplayerSession::MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference, + _In_ uint32 maxMembersInSession, + _In_ bool reserved, + _In_ MultiplayerSessionVisibility multiplayerSessionVisibility, + _In_opt_ Windows::Foundation::Collections::IVectorView^ initiatorXboxUserIds, + _In_opt_ Platform::String^ sessionCustomConstantsJson + ) +{ + UNREFERENCED_PARAMETER(reserved); + _Init(xboxLiveContext, multiplayerSessionReference, maxMembersInSession, multiplayerSessionVisibility, initiatorXboxUserIds, sessionCustomConstantsJson); +} +#endif + +MultiplayerSession::MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference, + _In_ uint32 maxMembersInSession, + _In_ MultiplayerSessionVisibility multiplayerSessionVisibility, + _In_opt_ Windows::Foundation::Collections::IVectorView^ initiatorXboxUserIds, + _In_opt_ Platform::String^ sessionCustomConstantsJson + ) +{ + _Init(xboxLiveContext, multiplayerSessionReference, maxMembersInSession, multiplayerSessionVisibility, initiatorXboxUserIds, sessionCustomConstantsJson); +} + +void +MultiplayerSession::_Init( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference, + _In_ uint32 maxMembersInSession, + _In_ MultiplayerSessionVisibility multiplayerSessionVisibility, + _In_opt_ Windows::Foundation::Collections::IVectorView^ initiatorXboxUserIds, + _In_opt_ Platform::String^ sessionCustomConstantsJson + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(xboxLiveContext); + THROW_INVALIDARGUMENT_IF_NULL(multiplayerSessionReference); + + std::vector intitiatorIds; + if (initiatorXboxUserIds != nullptr) + { + intitiatorIds = UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(initiatorXboxUserIds); + } + + CONVERT_STD_EXCEPTION( + auto sessionCustomConstantsValueString = UtilsWinRT::JsonValueFromPlatformString(sessionCustomConstantsJson); + m_cppObj = std::make_shared( + STRING_T_FROM_PLATFORM_STRING(xboxLiveContext->User->XboxUserId), + multiplayerSessionReference->GetCppObj(), + maxMembersInSession, + static_cast(multiplayerSessionVisibility), + intitiatorIds, + sessionCustomConstantsValueString + ); + ); +} + +MultiplayerSession::MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(xboxLiveContext); + CONVERT_STD_EXCEPTION( + m_cppObj = std::make_shared( + STRING_T_FROM_PLATFORM_STRING(xboxLiveContext->User->XboxUserId), + multiplayerSessionReference->GetCppObj() + ); + ); +} + +std::shared_ptr +MultiplayerSession::GetCppObj() const +{ + return m_cppObj; +} + +IVectorView^ +MultiplayerSession::HostCandidates::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj->host_candidates())->GetView(); +} + +MultiplayerSessionReference^ +MultiplayerSession::SessionReference::get() +{ + if (m_sessionReference == nullptr) + { + m_sessionReference = ref new MultiplayerSessionReference(m_cppObj->session_reference()); + } + return m_sessionReference; +} + +MultiplayerSessionConstants^ +MultiplayerSession::SessionConstants::get() +{ + if (m_sessionConstants == nullptr) + { + m_sessionConstants = ref new MultiplayerSessionConstants(m_cppObj->session_constants()); + } + return m_sessionConstants; +} + +MultiplayerSessionProperties^ +MultiplayerSession::SessionProperties::get() +{ + if (m_sessionProperties == nullptr) + { + m_sessionProperties = ref new MultiplayerSessionProperties(m_cppObj->session_properties()); + } + return m_sessionProperties; +} + +MultiplayerSessionRoleTypes^ +MultiplayerSession::SessionRoleTypes::get() +{ + if (m_sessionRoleTypes == nullptr) + { + m_sessionRoleTypes = ref new MultiplayerSessionRoleTypes(m_cppObj->session_role_types()); + } + return m_sessionRoleTypes; +} + +IVectorView^ +MultiplayerSession::Members::get() +{ + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj->members())->GetView(); +} + +MultiplayerSessionMatchmakingServer^ +MultiplayerSession::MatchmakingServer::get() +{ + return m_matchmakingServer; +} + +MultiplayerSessionTournamentsServer^ +MultiplayerSession::TournamentsServer::get() +{ + return m_tournamentsServer; +} + +MultiplayerSessionArbitrationServer^ +MultiplayerSession::ArbitrationServer::get() +{ + return m_arbitrationServer; +} + +MultiplayerSessionMember^ +MultiplayerSession::CurrentUser::get() +{ + if (m_cppObj->current_user()) + { + return ref new MultiplayerSessionMember(m_cppObj->current_user()); + } + else + { + return nullptr; + } +} + +void +MultiplayerSession::AddMemberReservation( + _In_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ memberCustomConstantsJson + ) +{ + auto memberCustomConstantsJsonString = UtilsWinRT::JsonValueFromPlatformString(memberCustomConstantsJson); + auto result = m_cppObj->add_member_reservation( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + memberCustomConstantsJsonString + ); + THROW_ON_ERR_CODE(result); +} + +void +MultiplayerSession::AddMemberReservation( + _In_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested + ) +{ + auto memberCustomConstantsJsonString = UtilsWinRT::JsonValueFromPlatformString(memberCustomConstantsJson); + auto result = m_cppObj->add_member_reservation( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + memberCustomConstantsJsonString, + initializeRequested + ); + THROW_ON_ERR_CODE(result); +} + +MultiplayerSessionMember^ +MultiplayerSession::Join() +{ + return JoinHelper(nullptr, false, false, false); +} + +MultiplayerSessionMember^ +MultiplayerSession::Join( + _In_opt_ Platform::String^ memberCustomConstantsJson + ) +{ + return JoinHelper(memberCustomConstantsJson, false, false, false); +} + +MultiplayerSessionMember^ +MultiplayerSession::Join( + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested + ) +{ + return JoinHelper(memberCustomConstantsJson, initializeRequested, false, true); +} + +MultiplayerSessionMember^ +MultiplayerSession::Join( + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus + ) +{ + return JoinHelper(memberCustomConstantsJson, initializeRequested, joinWithActiveStatus, true); +} + +MultiplayerSessionMember^ +MultiplayerSession::JoinHelper( + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus, + _In_ bool addInitializePropertyToRequest + ) +{ + auto memberCustomConstantsJsonString = web::json::value::null(); + if (memberCustomConstantsJson) + { + memberCustomConstantsJsonString = UtilsWinRT::JsonValueFromPlatformString(memberCustomConstantsJson); + } + auto result = m_cppObj->join( + memberCustomConstantsJsonString, + initializeRequested, + joinWithActiveStatus, + addInitializePropertyToRequest + ); + + THROW_IF_ERR(result); + MultiplayerSessionMember^ member = ref new MultiplayerSessionMember( + result.payload() + ); + + m_currentUser = member; + return member; +} + +void +MultiplayerSession::SetVisibility( + _In_ MultiplayerSessionVisibility visibility + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_visibility( + static_cast(visibility) + ); + ); +} + +void +MultiplayerSession::SetMaxMembersInSession( + _In_ uint32 maxMembersInSession + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_max_members_in_session( + maxMembersInSession + ); + ); +} + +void +MultiplayerSession::SetMutableRoleSettings( + _In_ Windows::Foundation::Collections::IMapView^ roleTypes +) +{ + auto errc = m_cppObj->set_mutable_role_settings( + UtilsWinRT::CreateStdMapObjectWithStringKeyFromPlatformMapObj(roleTypes) + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetTimeouts( + _In_ Windows::Foundation::TimeSpan memberReservedTimeout, + _In_ Windows::Foundation::TimeSpan memberInactiveTimeout, + _In_ Windows::Foundation::TimeSpan memberReadyTimeout, + _In_ Windows::Foundation::TimeSpan sessionEmptyTimeout + ) +{ + auto errc = m_cppObj->set_timeouts( + UtilsWinRT::ConvertTimeSpanToSeconds(memberReservedTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(memberInactiveTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(memberReadyTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(sessionEmptyTimeout) + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetArbitrationTimeouts( + _In_ Windows::Foundation::TimeSpan arbitrationTimeout, + _In_ Windows::Foundation::TimeSpan forfeitTimeout + ) +{ + auto errc = m_cppObj->set_arbitration_timeouts( + UtilsWinRT::ConvertTimeSpanToSeconds(arbitrationTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(forfeitTimeout) + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetQualityOfServiceConnectivityMetrics( + _In_ bool enableLatencyMetric, + _In_ bool enableBandwidthDownMetric, + _In_ bool enableBandwidthUpMetric, + _In_ bool enableCustomMetric + ) +{ + auto errc = m_cppObj->set_quality_of_service_connectivity_metrics( + enableLatencyMetric, + enableBandwidthDownMetric, + enableBandwidthUpMetric, + enableCustomMetric + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetManagedInitialization( + _In_ Windows::Foundation::TimeSpan joinTimeout, + _In_ Windows::Foundation::TimeSpan measurementTimeout, + _In_ Windows::Foundation::TimeSpan evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32 membersNeededToStart + ) +{ +#pragma warning(suppress: 4996) + auto errc = m_cppObj->set_managed_initialization( + UtilsWinRT::ConvertTimeSpanToSeconds(joinTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(measurementTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(evaluationTimeout), + autoEvalute, + membersNeededToStart + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetMemberInitialization( + _In_ Windows::Foundation::TimeSpan joinTimeout, + _In_ Windows::Foundation::TimeSpan measurementTimeout, + _In_ Windows::Foundation::TimeSpan evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32 membersNeededToStart + ) +{ + auto errc = m_cppObj->set_member_initialization( + UtilsWinRT::ConvertTimeSpanToSeconds(joinTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(measurementTimeout), + UtilsWinRT::ConvertTimeSpanToSeconds(evaluationTimeout), + autoEvalute, + membersNeededToStart + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetPeerToPeerRequirements( + _In_ Windows::Foundation::TimeSpan latencyMaximum, + _In_ uint32 bandwidthMinimumInKilobitsPerSecond + ) +{ + auto errc = m_cppObj->set_peer_to_peer_requirements( + UtilsWinRT::ConvertTimeSpanToSeconds(latencyMaximum), + bandwidthMinimumInKilobitsPerSecond + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetPeerToHostRequirements( + _In_ Windows::Foundation::TimeSpan latencyMaximum, + _In_ uint32 bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32 bandwidthUpMinimumInKilobitsPerSecond, + _In_ MultiplayMetrics hostSelectionMetric + ) +{ + auto errc = m_cppObj->set_peer_to_host_requirements( + UtilsWinRT::ConvertTimeSpanToSeconds(latencyMaximum), + bandwidthDownMinimumInKilobitsPerSecond, + bandwidthUpMinimumInKilobitsPerSecond, + static_cast(hostSelectionMetric) + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetMeasurementServerAddresses( + _In_ IVectorView^ measurementServerAddresses + ) +{ + auto errc = m_cppObj->set_measurement_server_addresses( + UtilsWinRT::CreateStdVectorObjectFromPlatformVectorObj( + measurementServerAddresses + ) + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetSessionCapabilities( + _In_ MultiplayerSessionCapabilities^ capabilities + ) +{ + auto errc = m_cppObj->set_session_capabilities( + capabilities->GetCppObj() + ); + + THROW_ON_ERR_CODE(errc); +} + +void +MultiplayerSession::SetInitializationStatus( + _In_ bool initializationSucceeded + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_initialization_status( + initializationSucceeded + ); + ); +} + +void +MultiplayerSession::SetHostDeviceToken( + _In_ Platform::String^ hostDeviceToken + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_host_device_token( + STRING_T_FROM_PLATFORM_STRING(hostDeviceToken) + ); + ); +} + +void +MultiplayerSession::SetMatchmakingServerConnectionPath( + _In_ Platform::String^ serverConnectionPath + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_matchmaking_server_connection_path( + STRING_T_FROM_PLATFORM_STRING(serverConnectionPath) + ); + ); +} + +void +MultiplayerSession::SetClosed( + _In_ bool closed + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_closed(closed); + ); +} + +void +MultiplayerSession::SetMatchmakingResubmit( + _In_ bool matchResubmit + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_matchmaking_resubmit( + matchResubmit + ); + ) +} + +void +MultiplayerSession::SetServerConnectionStringCandidates( + _In_ Windows::Foundation::Collections::IVectorView^ serverConnectionStringCandidates + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_server_connection_string_candidates( + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(serverConnectionStringCandidates) + ); + ); +} + +void +MultiplayerSession::SetSessionChangeSubscription( + _In_ MultiplayerSessionChangeTypes changeTypes + ) +{ + auto result = m_cppObj->set_session_change_subscription( + static_cast(changeTypes) + ); + + THROW_ON_ERR_CODE(result); +} + +void +MultiplayerSession::Leave() +{ + auto result = m_cppObj->leave(); + THROW_ON_ERR_CODE(result); +} + +void +MultiplayerSession::SetCurrentUserStatus( + _In_ MultiplayerSessionMemberStatus status + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_current_user_status( + static_cast(status) + ); + ); +} + +void +MultiplayerSession::SetCurrentUserSecureDeviceAddressBase64( + _In_ Platform::String^ value + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_current_user_secure_device_address_base64( + STRING_T_FROM_PLATFORM_STRING(value) + ); + ); +} + +void +MultiplayerSession::SetCurrentUserRoleInfo( + _In_ IMapView^ roles + ) +{ + m_roles = roles; + CONVERT_STD_EXCEPTION( + m_cppObj->set_current_user_role_info( + UtilsWinRT::CreateStdUnorderedMapStringFromMapObj(m_roles) + ); + ); +} + +void +MultiplayerSession::SetCurrentUserMembersInGroup( + _In_ IVectorView^ membersInGroup + ) +{ + CONVERT_STD_EXCEPTION( + THROW_INVALIDARGUMENT_IF_NULL(membersInGroup); + m_cppObj->set_current_user_members_in_group( + UtilsWinRT::CreateStdVectorObjectFromPlatformVectorObj>(membersInGroup) + ); + ); +} + +void +MultiplayerSession::SetCurrentUserQualityOfServiceMeasurements( + _In_ IVectorView^ measurements + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->set_current_user_quality_of_service_measurements( + std::make_shared>( + UtilsWinRT::CreateStdVectorObjectFromPlatformVectorObj( + measurements + ) + ) + ) + ); +} + +void MultiplayerSession::SetCurrentUserQualityOfServiceServerMeasurementsJson( + _In_ Platform::String^ valueJson + ) +{ + CONVERT_STD_EXCEPTION( + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + m_cppObj->set_current_user_quality_of_service_measurements_json( + valueJsonString + ); + ); +} + +void +MultiplayerSession::SetCurrentUserArbitrationResults( + _In_ Windows::Foundation::Collections::IMapView^ results + ) +{ + m_cppObj->set_current_user_member_arbitration_results( + UtilsWinRT::CreateStdMapObjectWithStringKeyFromPlatformMapObj(results) + ); +} + +void +MultiplayerSession::SetCurrentUserMemberCustomPropertyJson( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson + ) +{ + CONVERT_STD_EXCEPTION( + auto valueJsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + m_cppObj->set_current_user_member_custom_property_json( + STRING_T_FROM_PLATFORM_STRING(name), + valueJsonString + ); + ); +} + +void +MultiplayerSession::DeleteCurrentUserMemberCustomPropertyJson( + _In_ Platform::String^ name + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->delete_current_user_member_custom_property_json( + STRING_T_FROM_PLATFORM_STRING(name) + ); + ); +} + +void MultiplayerSession::SetMatchmakingTargetSessionConstantsJson( + _In_ Platform::String^ matchmakingTargetSessionConstants + ) +{ + CONVERT_STD_EXCEPTION( + auto jsonString = UtilsWinRT::JsonValueFromPlatformString(matchmakingTargetSessionConstants); + m_cppObj->set_matchmaking_target_session_constants_json( + jsonString + ); + ) +} + +void +MultiplayerSession::SetSessionCustomPropertyJson( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson + ) +{ + CONVERT_STD_EXCEPTION( + auto jsonString = UtilsWinRT::JsonValueFromPlatformString(valueJson); + m_cppObj->set_session_custom_property_json( + STRING_T_FROM_PLATFORM_STRING(name), + jsonString + ); + ); +} + +void +MultiplayerSession::DeleteSessionCustomPropertyJson( + _In_ Platform::String^ name + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj->delete_session_custom_property_json( + STRING_T_FROM_PLATFORM_STRING(name) + ); + ); +} + +MultiplayerSessionChangeTypes +MultiplayerSession::CompareMultiplayerSessions( + _In_ MultiplayerSession^ currentSession, + _In_ MultiplayerSession^ oldSession + ) +{ + auto result = xbox::services::multiplayer::multiplayer_session::compare_multiplayer_sessions( + currentSession->GetCppObj(), + oldSession->GetCppObj() + ); + THROW_IF_ERR(result); + + return MultiplayerSessionChangeTypes(result.payload()); +} + +WriteSessionStatus +MultiplayerSession::ConvertHttpStatusToWriteSessionStatus( + _In_ int32 httpStatusCode + ) +{ + CONVERT_STD_EXCEPTION( + auto result = xbox::services::multiplayer::multiplayer_session::convert_http_status_to_write_session_status( + httpStatusCode + ); + + return static_cast(result); + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.h new file mode 100644 index 00000000..f0d533a9 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSession_WinRT.h @@ -0,0 +1,1300 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "Macros_WinRT.h" +#include "MultiplayerSessionConstants_WinRT.h" +#include "MultiplayerSessionMember_WinRT.h" +#include "MultiplayerInitializationStage_WinRT.h" +#include "MultiplayerSessionProperties_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" +#include "MatchmakingStatus_WinRT.h" +#include "MultiplayerSessionCapabilities_WinRT.h" +#include "MultiplayerSessionChangeTypes.h" +#include "QualityOfServiceServer_WinRT.h" +#include "MultiplayerServiceMatchmakingServer_WinRT.h" +#include "WriteSessionStatus_WinRT.h" +#include "MultiplayerSessionTournamentsServer_WinRT.h" +#include "MultiplayerSessionArbitrationServer_WinRT.h" +#include "MultiplayerSessionRoleTypes_WinRT.h" +#include "MultiplayerRoleType_WinRT.h" +#include "TournamentTeamResult_WinRT.h" + +namespace Microsoft{ namespace Xbox{ namespace Services { + ref class XboxLiveContext; +}}} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN +/// +/// Represents a multiplayer session. +/// + +// Response Structure +// +// { +// // The contract version of this rendering of the session. A function of the contract version of the request and constants/system/version. +// "contractVersion": 105, +// +// // Use for tracing. +// "correlationId": "0FE81338-EE96-46E3-A3B5-2DBBD6C41C3B", +// +// // The time that the session began. +// // If an empty session is deleted and then restarted, this time will be the time of the restart. +// "startTime": "2009-06-15T13:45:30.0900000Z", +// +// // If any timeouts are in progress, this is the time that the next one will fire. +// "nextTimer": "2009-06-15T13:45:30.0900000Z", +// +// // Present during managed initialization. +// // The "stage" goes from "joining" to "measuring" to "evaluating". +// // If episode 1 fails, then "stage" is set to "failed" and the session cannot be initialized. +// // Otherwise, when an initialization episode completes, the "initialization" object is removed. +// // If "externalEvaluation" is not set, "evaluating" is skipped. If "metrics" isn't set, "measuring" is skipped. +// "initializing": +// { +// "stage": "measuring", +// "stageStartTime": "2009-06-15T13:45:30.0900000Z", +// "episode": 0 +// }, +// +// // Set after the "measuring" stage of initialization episode 1, if "peerToHostRequirements" is set and no /properties/system/host is set. +// // Cleared once a /properties/system/host is set. +// // Host candidates are device tokens listed in order, order of preference. +// "hostCandidates": [ "ab90a362", "99582e67" ], +// +// "constants": { /* Property Bag */ }, +// "properties": { /* Property Bag */ }, +// +// "members": +// { +// "1": +// { +// "constants": { /* Property Bag */ }, +// "properties": { /* Property Bag */ }, +// +// // Only if the member has accepted. Optional (not set if no gamertag claim was found). +// "gamertag": "stacy", +// +// // This is set when the member uploads a secure device address. It's a case-insensitive string that can be used for equality comparisons. +// "deviceToken": "9f4032ba7", +// +// // This value is removed once the user does their first PUT to the session. +// "reserved": true, +// +// // If the member is active, this is the title in which they are active, in decimal. +// "activeTitleId": "8397267", +// +// // The time the user joined the session. If "reserved" is true, the time the reservation was made. +// "joinTime": "2009-06-15T13:45:30.0900000Z", +// +// // Present if this member is in the properties/system/turn array, otherwise not. +// "turn": true, +// +// // Set when transitioning out of the "joining" or "measuring" stage if this member doesn't pass. +// // In order of precedence, could be set to "timeout", "latency", "bandwidthDown", "bandwidthUp", "network", "group", or "quorum". +// // The "network" value means the network configuration and/or conditions (such as conflicting NAT) prevented the QoS metrics from being measured. +// // The only possible value at the end of "joining" is "group". (On timeout from "joining", the reservation is removed.) +// // The "quorum" value is set after a failed "evaluation" stage on all members of the initialization episode that didn't fail during "joining" or "measuring". +// "failedMetric": "latency", +// +// // If "memberInitialization" is set and the member was added with "initialize": true, this is set to the initialization episode that the member will participate in. +// // Zero is a special value used for the members added to a new session at create time. +// "initializationEpisode": 0, +// +// // The next member's index, which is the same as 'next' below if there's no more. +// "next": 4 +// }, +// "4": { "next": 5 /* etc */ } +// }, +// +// "membersInfo": +// { +// "first": 1, // The first member's index. +// "next": 5, // The index that the next member added will get. +// "count": 2, // The number of members. +// "accepted": 1 // The number of members that are no longer 'pending'. +// }, +// +// "servers": +// { +// "name": +// { +// "constants": { /* Property Bag */ }, +// "properties": { /* Property Bag */ } +// } +// } +// } +// +// +// // Property Bags Each of the above objects marked as a property bag consists of two optional inner objects, system and custom. +// // The custom objects can contain any JSON. +// +// "custom": +// { +// "myField1": true, +// "myField2": "string", +// "myField3": 5.5, +// "myField4": { "myObject": null }, +// "myField5": [ "my", "array" ] +// } +// +// // System Objects Each of the system objects in the session document has a fixed schema that is enforced and interpreted by MPSD. +// // Within the body of PUT requests, the system objects are validated and merged just like the custom objects. +// // But unlike custom objects, once merged the system objects are further validated and acted upon based on these schemas. +// +// /constants/system +// { +// "version": 1, +// "maxMembersCount": 100, // Defaults to 100 if not set on creation. Must be between 1 and 100. +// "visibility": "private", // Or "visible" or "open", defaults to "open" if not set on creation. +// "initiators": [ "1234" ], // If specified on a new session, the creator's xuid must be in the list (or the creator must be a server). +// "inviteProtocol": "party", // Optional URI scheme of the launch URI for invite toasts. +// +// // Timeouts are specified in Milliseconds. Zero is allowed and means to immediately time out. If a given timeout isn't specified, it's considered infinite. +// // Specified as a group for usability, to allow 'unspecified' to be meaningful, and because timeouts are often related. +// +// "reservedRemovalTimeout": 10000, // Default is 10 seconds. Member is removed from the session. +// "inactiveRemovalTimeout": 7200000, // Default is two hours. Member is removed from the session. +// "readyRemovalTimeout": 60000, // Default is one minute. Member becomes inactive. +// "sessionEmptyTimeout": 0, // Default is zero. Session is deleted. +// +// // Capabilities are boolean values that are optionally set in the session template. If no capabilities +// // are needed, an empty "capabilities" object should be in the template in order to prevent capabilities from +// // being specified on session creation, unless the title desires dynamic session capabilities. +// "capabilities": +// { +// "clientMatchmaking": true, +// "connectivity": true, +// "suppressPresenceActivityCheck": false, +// "gameplay" : true, +// "large" : false +// }, +// +// // Requires "connectivity" capability. +// // If no "metrics" are specified, they default to what are needed to satisfy the QoS requirements. +// // If they are specified, they must be sufficient to satisfy the QoS requirements. +// "metrics": +// { +// "latency": true, +// "bandwidthDown": true, +// "bandwidthUp": true, +// "custom": true +// }, +// +// // If a "memberInitialization" objet is set, the session expects the client system or title to perform initialization following session creation and/or as new members join the session. +// // The timeouts and initialization stages are automatically tracked by the session, including QoS measurements if any metrics are set. +// "memberInitialization": +// { +// "joinTimeout": 4000, // Milliseconds. Default is 4 seconds. Overrides "reservationTimeout" for the initial members. +// "measurementTimeout": 5000, // Milliseconds. Default is based on which of the metrics and/or server ping addresses are set. +// "evaluationTimeout": 5000, // Milliseconds. Can only be set if 'autoEvaluate' is false. Default is 5 seconds. +// "externalEvaluation": false, +// "membersNeededToStart": 2 // Defaults to 2. Must be between 1 and maxMemberCount. Only applies to initialization episode zero. +// }, +// +// // Thresholds to apply to each pairwise connection for all members in a session. +// "peerToPeerRequirements": +// { +// "latencyMaximum": 250, // Milliseconds +// "bandwidthMinimum": 10000 // Kilobits per second +// }, +// +// // Thresholds to apply to each connection from a host candidate. +// "peerToHostRequirements": +// { +// "latencyMaximum": 250, // Milliseconds +// "bandwidthDownMinimum": 100000, // Kilobits per second +// "bandwidthUpMinimum": 1000, // Kilobits per second +// "hostSelectionMetric": "bandwidthUp" // Or "bandwidthDown" or "latency". Not specified is the same as "latency". +// }, +// +// // The set of potential server connection strings that should be evaluated. +// "measurementServerAddresses": +// { +// "east.azure.com": +// { +// "secureDeviceAddress": "r5Y=" // Base-64 encoded secure-device-address +// }, +// "west.azure.com": +// { +// "secureDeviceAddress": "rwY=" +// } +// } +// } +// +// /properties/system +// { +// "keywords": [ "hello" ], // Optional array of case-insensitive strings. Cannot be set if the session's visibility is "private" +// "turn": [ 0 ], // Array of integer member indicies whose turn it is. Defaults to empty. +// +// // Device token of the host. +// // Must match the "deviceToken" of at least one member, otherwise this field is deleted. +// // If "peerToHostRequirements" is set and "host" is set, the measurement stage assumes the given host is the correct host and only measures metrics to that host. +// "host": "99e4c701", +// +// // Can only be set while "initialization/stage" is "evaluating". True indicates success, and false indicates failure. +// // Once set, "initialization/stage" is immediately updated, and this field is removed. +// "initializationSucceeded": true, +// +// // The ordered list of connection strings that the session could use to connect to a game server. Generally titles should use the first on +// // the list, but sophisticated titles could use a custom mechanism for choosing one of the others (e.g. based on load). +// "serverConnectionStrings": [ "west.azure.com", "east.azure.com" ], +// +// "matchmaking": +// { +// "clientResult": +// { +// // Requires the clientMatchmaking property. +// "status": "searching", // Or "expired", "found", "failed", or "canceled". +// "statusDetails": "Description", // Default is empty string. +// "typicalWait": 30, // The expected number of seconds waiting as a non-negative integer. +// "targetSessionRef": +// { +// "scid": "1ECFDB89-36EB-4E59-8901-11F7393689AE", +// "templateName": "capture-the-flag", +// "name": "2D58F65F-0E3C-4F1F-8277-2BC9873FDB23" +// } +// }, +// +// // Default is empty object. +// "targetSessionConstants": { }, +// +// // Force a specific connection string to be used (useful in preserveSession=always cases). +// "serverConnectionString": "west.azure.com" +// }, +// // True if the match that was found didn't work out and needs to be resubmitted. Set to false +// // to signal that the match did work, and the matchmaking service can release the session. +// "matchmakingResubmit": true +// } +// +// +// /members/{index}/constants/system +// { +// "xuid": "12345678", +// +// // Run initialization for this user. Defaults to false. +// // Ignored if no "memberInitialization" section is set for the session. +// "initialize": true, +// +// // When match adds a user to a session, it can provide some context around how and why they were matched into the session. +// "matchmakingResult": +// { +// +// // This is a copy of the user's serverMeasurements from the matchmaking session. +// "serverMeasurements": +// { +// "east.azure.com": +// { +// "latency": 233 // Milliseconds +// } +// } +// } +// } +// +// +// /members/{index}/properties/system +// { +// // These flags control the member status and "activeTitle", and are mutually exclusive (it's an error to set both to true). +// // For each, false is the same as not present. The default status is "inactive", i.e. neither present. +// "ready": true, +// "active": false, +// +// // Base64 blob, or not present. Empty-string is the same as not present. +// "secureDeviceAddress": "ryY=", +// +// // List of members in my group, by index. +// // If a "initializationGroup" list is set, the member's own index will always be added if it isn't already present. +// // During managed initialization, if any members in the list fail, this member will also fail. +// "initializationGroup": [ 5 ], +// +// // QoS measurements by lower-case device token. +// // Like all fields, "measurements" must be updated as a whole. It should be set once when measurement is complete, not incrementally. +// // Metrics can me omitted if they weren't successfully measured, i.e. the peer is unreachable. +// // If a "measurements" object is set, it can't contain an entry for the member's own address. +// "measurements": +// { +// "e69c43a8": +// { +// "latency": 5953, // Milliseconds +// "bandwidthDown": 19342, // Kilobits per second +// "bandwidthUp": 944, // Kilobits per second +// "custom": { } +// } +// }, +// +// // QoS measurements by game-server connection string. Like all fields, "serverMeasurements" must be updated as a whole, so it should be set once when measurement is complete. +// // If empty, it means that none of the measurements completed within the "serverMeasurementTimeout". +// "serverMeasurements": +// { +// "east.azure.com": +// { +// "latency": 233 // Milliseconds +// } +// } +// } +// +// /servers/{server-name}/constants/system +// { +// } +// +// /servers/{server-name}/properties/system +// { +// "lockId": "opaque56789", // If set, a matchmaking service is servicing this session. +// "status": "searching", // Or "expired", "found", "failed", or "canceled". Optional. +// "statusDetails": "Description", // Optional free-form text. Default is empty string. +// "typicalWait": 30, // Optional. The expected number of seconds waiting as a non-negative integer. +// "targetSessionRef": +// { +// // Optional. +// "scid": "1ECFDB89-36EB-4E59-8901-11F7393689AE", +// "templateName": "capture-the-flag", +// "name": "2D58F65F-0E3C-4F1F-8277-2BC9873FDB23" +// } +// } + +public ref class MultiplayerSession sealed +{ +public: + /// + /// Creates a new MultiplayerSession Class object from the supplied Xbox Live context, without any constants or session reference. + /// + /// The XboxLiveContext containing the user who is creating this session. + /// + /// This override is intended to be used when the session serviceconfigid, template, and name are not known. A MultiplayerSession created + /// using this constructor must be retrieved or written to by using the "ByHandle" overrides. + /// (e.g. WriteSessionByHandleAsync and GetCurrentSessionByHandleAsync) + /// + /// After calling this constructor, the client must use the MultiplayerService::WriteSessionAsync method to write batched local changes to the service. + /// If this constructor is called without calling MultiplayerService::WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + /// This constructor is intended for use with template contract 104/105 or later. + /// + MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext + ); + +#if TV_API + /// + /// Creates a new MultiplayerSession using the specified session constants. + /// + /// The XboxLiveContext containing the user who is creating this session. + /// A reference that uniquely identifies the session. + /// The maximum number of members in this session. This value can only be set if the maximum + /// is not specified in the title's multiplayer session template. If the maximum is specified in the title's multiplayer + /// session template, then set to 0 to ignore this parameter. + /// DEPRECATED. This param is ignored + /// An enumeration value indicating the visibility of this session. + /// (Optional) A collection of Xbox User IDs indicating who initiated the session. + /// (Optional) A JSON string that specify the custom constants for the session. + /// These constants cannot be changed after the session is created. + /// + /// After calling this constructor, the client must use the MultiplayerService::WriteSessionAsync method to write batched local changes to the service. + /// If this constructor is called without calling MultiplayerService::WriteSessionAsync, it only changes the local session + /// + MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference, + _In_ uint32 maxMembersInSession, + _In_ bool reserved, + _In_ MultiplayerSessionVisibility multiplayerSessionVisibility, + _In_opt_ Windows::Foundation::Collections::IVectorView^ initiatorXboxUserIds, + _In_opt_ Platform::String^ sessionCustomConstantsJson + ); +#endif + + /// + /// Creates a new MultiplayerSession using the specified session constants. + /// + /// The XboxLiveContext containing the user who is creating this session. + /// A reference that uniquely identifies the session. + /// The maximum number of members in this session. This value can only be set if the maximum + /// is not specified in the title's multiplayer session template. If the maximum is specified in the title's multiplayer + /// session template, then set to 0 to ignore this parameter. + /// An enumeration value indicating the visibility of this session. + /// (Optional) A collection of Xbox User IDs indicating who initiated the session. + /// (Optional) A JSON string that specify the custom constants for the session. + /// These constants cannot be changed after the session is created. + /// + /// After calling this constructor, the client must use the MultiplayerService::WriteSessionAsync method to write batched local changes to the service. + /// If this constructor is called without calling MultiplayerService::WriteSessionAsync, it only changes the local session + /// + MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference, + _In_ uint32 maxMembersInSession, + _In_ MultiplayerSessionVisibility multiplayerSessionVisibility, + _In_opt_ Windows::Foundation::Collections::IVectorView^ initiatorXboxUserIds, + _In_opt_ Platform::String^ sessionCustomConstantsJson + ); + + /// + /// Creates a new MultiplayerSession without any constants, which allows the request to simply use whatever constants + /// are already specified in the session template on the service. Those constants are returned in the response session data. + /// + /// The XboxLiveContext containing the user who is creating this session. + /// A reference that uniquely identifies the session. + /// + /// After calling this constructor, the client must use the MultiplayerService::WriteSessionAsync method to write batched local changes to the service. + /// If this constructor is called without calling MultiplayerService::WriteSessionAsync, it only changes the local session + /// + MultiplayerSession( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference + ); + + /// + /// A unique ID to the session used to query trace logs for entries that relate to the session. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(MultiplayerCorrelationId, multiplayer_correlation_id); + + /// + /// A unique search handle ID to the session. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(SearchHandleId, search_handle_id); + + /// + /// The date and time that the session began. + /// + DEFINE_PTR_PROP_GET_DATETIME_OBJ(StartTime, start_time); + + /// + /// If any timeouts are in progress, this is the date and time when the the next timer fires. + /// + DEFINE_PTR_PROP_GET_DATETIME_OBJ(DateOfNextTimer, date_of_next_timer); + + /// + /// The date and time when the server returned the session. + /// + DEFINE_PTR_PROP_GET_DATETIME_OBJ(DateOfSession, date_of_session); + + /// + /// Indicates the managed initialization stage, if the session is using managed initialization. + /// The "stage" goes from "joining" to "measuring" to "evaluating". + /// If episode 1 fails, then "stage" is set to "failed" and the session cannot be initialized. + /// Otherwise, when an initialization episode completes, the "initialization" object is removed. + /// If "externalEvaluation" is not set, "evaluating" is skipped. If "metrics" isn't set, "measuring" is skipped. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(InitializationStage, initialization_stage, MultiplayerInitializationStage); + + /// + /// The date and time when the initialization stage started during managed initialization. + /// + DEFINE_PTR_PROP_GET_DATETIME_OBJ(InitializingStageStartTime, initializing_stage_start_time); + + /// + /// The episode number associated with a set of session members requiring QoS metrics to be applied + /// during managed initialization. + /// + /// + /// If MemberInitialization is set and Initialize is true on the member, then the member is assigned to an InitializingEpisode. + /// An episode is a set of users that need to have QoS metrics applied to them. + /// This value is only useful when manually managing QoS. + /// This value is 0 when the InitializingEpisode is not set. + /// + DEFINE_PTR_PROP_GET_OBJ(InitializingEpisode, intializing_episode, uint32); + + /// + /// The status of a write operation when writing a session. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(WriteStatus, write_status, WriteSessionStatus); + + /// + /// An ordered list of device tokens for host names that can be used for the session, + /// ordered by the preference specified by MultiplayerSessionConstants::PeerToHostRequirements::HostSelectionMetric. + /// + property Windows::Foundation::Collections::IVectorView^ HostCandidates + { + Windows::Foundation::Collections::IVectorView^ get(); + } + + /// + /// The unique identifying information for the session. + /// + property MultiplayerSessionReference^ SessionReference { MultiplayerSessionReference^ get(); } + + /// + /// A set of constants associated with this session. These can only be set when creating the session. + /// + property MultiplayerSessionConstants^ SessionConstants { MultiplayerSessionConstants^ get(); } + + /// + /// A set of properties associated with this session. Any player can modify these. + /// + property MultiplayerSessionProperties^ SessionProperties { MultiplayerSessionProperties^ get(); } + + /// + /// A set of role types associated with this session. + /// + property MultiplayerSessionRoleTypes^ SessionRoleTypes { MultiplayerSessionRoleTypes^ get(); } + + /// + /// A list of all session members, including those who have been accepted and those who are waiting to join the session. + /// + /// + /// Call MultiplayerSession::Join or MultiplayerSession::Leave to add or remove youself from this list. + /// Call MultiplayerSession::AddMemberReservation to add a reservation for another user on this list. + /// Call MultiplayerService::WriteSessionAsync to write these changes to the service. + /// + property Windows::Foundation::Collections::IVectorView^ Members { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// A multiplayer session server that contains properties associated with a target session reference. + /// + property MultiplayerSessionMatchmakingServer^ MatchmakingServer{ MultiplayerSessionMatchmakingServer^ get(); } + + /// + /// A multiplayer tournaments server that contains properties associated with a tournament reference. + /// + property MultiplayerSessionTournamentsServer^ TournamentsServer { MultiplayerSessionTournamentsServer^ get(); } + + /// + /// An arbitration server that contains properties associated with a tournament games results. + /// + property MultiplayerSessionArbitrationServer^ ArbitrationServer { MultiplayerSessionArbitrationServer^ get(); } + + /// + // The number of members that have accepted and were added to the session. These member joins are no longer pending. + /// + DEFINE_PTR_PROP_GET_OBJ(MembersAccepted, members_accepted, uint32); + + /// + /// A JSON string containing a collection of servers for this multiplayer session. + /// + /// + /// The most common server involved in the session is used when the session is submitted to matchmaking using the + /// MatchmakingService.CreateMatchTicketAsync Method. Once the title has made this call, the JSON object for ServersJson + /// has one server object child, named "matchmaking". The server object contains information about the matchmaking for the session. + /// + /// After setting ServersJson, the title must call MultiplayerService.WriteSessionAsync to write batched local changes to the service. + /// If the method is called without calling WriteSessionAsync, the method only changes the local session object but does not commit it to the server. + /// + DEFINE_PTR_PROP_GETSET_STR_FROM_JSON_OBJ(ServersJson, servers_json); + + /// + /// The ETag returned with this session, used to determine if the session has been updated since it was last retrieved from the server. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ETag, e_tag); + + /// + /// Returns an OR'd set of MultiplayerSessionChangeTypes values representing the aspects of + /// the session that the current xboxlivecontext is subscribed to, of None if there is none. + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(SubscribedChangeTypes, subscribed_change_types, MultiplayerSessionChangeTypes); + + /// + /// The current user in the session. A nullptr is returned if there is no current user in the session. + /// + property MultiplayerSessionMember^ CurrentUser { MultiplayerSessionMember^ get(); } + + /// + /// The branch of the session, used to scope change numbers. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(Branch, branch); + + /// + /// The change number of the session. + /// + /// + /// Branch indicates if two change numbers are from the same series and therefore can be compared. If a session is deleted and + /// then recreated with the same session name, it receives a different branch. The branch also changes if the session is + /// reverted due to a service issue that forced a restore from backup or other data synchronization operation. + /// + DEFINE_PTR_PROP_GET_OBJ(ChangeNumber, change_number, uint64); + + /// + /// Adds a new member reservation on the session for the specified Xbox user ID and member constants. + /// + /// The Xbox User ID of the member to add a reservation for. + /// (Optional) A JSON string with custom constants to set for the session member. This is the only time the member's constants can be set. + /// + /// After calling AddMemberReservation, the Xbox system or title must call MultiplayerService.WriteSessionAsync + /// to write batched local changes to the service. If AddMemberReservation is called without calling WriteSessionAsync, + /// it only changes the local session object but does not commit it to the service. + /// + void AddMemberReservation( + _In_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ memberCustomConstantsJson + ); + + /// + /// Adds a new member reservation on the session for the specified Xbox user ID, member constants, and initialization request. + /// + /// The Xbox User ID of the member to add a reservation for. + /// (Optional) A JSON string with custom constants to set for the session member. This is the only time the member's constants can be set. + /// True if the system should perform managed initialization, and false otherwise. + /// + /// After calling AddMemberReservation, the system or title must call MultiplayerService.WriteSessionAsync + /// to write batched local changes to the service. If AddMemberReservation is called without calling WriteSessionAsync, + /// it only changes the local session object but does not commit it to the service. + /// + void AddMemberReservation( + _In_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested + ); + + /// + /// Joins the user that either created or got the session to the session. + /// It does not set an initialization request and does not set specified member constants + /// + /// The MultiplayerSessionMember object that represents the user. + /// + /// After calling Join, the system or title must call MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. If Join is called without calling WriteSessionAsync, it only changes the local session object but does not + /// commit it to the service. + /// + MultiplayerSessionMember^ Join(); + + /// + /// Joins the user that either created or got the session to the session, using the specified member constants. + /// It does not set an initialization request + /// + /// (Optional) A JSON string with custom constants for the new session member. This is the only time the member's constants can be set. + /// The MultiplayerSessionMember object that represents the user. + /// + /// After calling Join, the Xbox system or title must call MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. If Join is called without calling WriteSessionAsync, it only changes the local session object but does not + /// commit it to the service. + /// + MultiplayerSessionMember^ Join( + _In_opt_ Platform::String^ memberCustomConstantsJson + ); + + /// + /// Joins the user that either created or got the session to the session, using the specified member constants and an initialization request. + /// + /// (Optional) A JSON string with custom constants for the new session member. This is the only time the member's constants can be set. + /// True if the caller would like to enroll in automatic member initialization, and false otherwise. Usually used for QoS. + /// The MultiplayerSessionMember object that represents the user. + /// + /// After calling Join, the system or title must call MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. If Join is called without calling WriteSessionAsync, it only changes the local session object but does not + /// commit it to the service. + /// +#if _MSC_VER >= 1800 + [Windows::Foundation::Metadata::Deprecated("Call Join(String^) or Join(String^, bool, bool) instead", Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0)] +#endif + MultiplayerSessionMember^ Join( + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested + ); + + /// + /// Joins the user that either created or got the session to the session, using the specified member constants, an initialization request, + /// and a join condition. + /// + /// (Optional) A JSON string with custom constants for the new session member. This is the only time the member's constants can be set. + /// True if the caller would like to enroll in automatic member initialization, and false otherwise. Usually used for QoS. + /// True if the player should join with an active status. + /// The MultiplayerSessionMember object that represents the user. + /// + /// After calling Join, the system or title must call MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. If Join is called without calling WriteSessionAsync, it only changes the local session object but does not + /// commit it to the service. + /// + MultiplayerSessionMember^ Join( + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus + ); + + /// + /// Sets the visibility of the session. + /// + /// An enumeration value indicating the visibility for the session. + /// + /// This can only be set when creating a new session. + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetVisibility( + _In_ Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionVisibility visibility + ); + + /// + /// Sets the maximum number of members allowed in the session. + /// + /// The maximum number of members. + /// + /// This can only be set when creating a new session. + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetMaxMembersInSession( + _In_ uint32 maxMembersInSession + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Sets the max member count per role. + /// Note: Only the session owner can modify role settings and only those that are multiplayer_role_type::mutable_role_settings() + /// In your session template, you also need to set 'hasOwners' capability and 'ownerManaged' to true for the specific role type + /// that you want to modify the mutable_role_setting off. + /// + /// A map of role type names to multiplayer role type + void SetMutableRoleSettings( + _In_ Windows::Foundation::Collections::IMapView^ roleTypes + ); + + /// + /// Sets the timeout values for the session. + /// + /// The timeout for a member reservation, in milliseconds. A value of 0 is allowed and + /// indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// The timeout for a member to be considered inactive, in milliseconds. A value of 0 + /// is allowed and indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// The timeout for a member to be considered ready, in milliseconds. A value of 0 is + /// allowed and indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// The timeout for an empty session, in milliseconds. A value of 0 is allowed and + /// indicates an immediate timeout. If the timeout is not specified, it is considered infinite. + /// + /// This can only be set when creating a new session. + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetTimeouts( + _In_ Windows::Foundation::TimeSpan memberReservedTimeout, + _In_ Windows::Foundation::TimeSpan memberInactiveTimeout, + _In_ Windows::Foundation::TimeSpan memberReadyTimeout, + _In_ Windows::Foundation::TimeSpan sessionEmptyTimeout + ); + + /// + /// Sets the arbitration timeouts for the session. + /// + /// The timeout for arbitration, in milliseconds representing the point at which results are finalized. + /// The timeout for forfeit, in milliseconds representing the point at which, if the session has no active users, the match is canceled. + /// + /// This can only be set when creating a new session. + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetArbitrationTimeouts( + _In_ Windows::Foundation::TimeSpan arbitrationTimeout, + _In_ Windows::Foundation::TimeSpan forfeitTimeout + ); + + /// + /// Enables or disables the connectivity metrics used to satisfy QoS requirements on the network for the session. + /// + /// True to enable the measuring of latency, and false to disable latency measurement. + /// True to enable the measuring of bandwidth down, and false to disable bandwidth down measurement. + /// True to enable the measuring of bandwidth up, and false to disable bandwidth up measurement. + /// True to enable custom metrics, and false to disable them. + /// + /// This can only be set when creating a new session. + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetQualityOfServiceConnectivityMetrics( + _In_ bool enableLatencyMetric, + _In_ bool enableBandwidthDownMetric, + _In_ bool enableBandwidthUpMetric, + _In_ bool enableCustomMetric + ); + + /// + /// Configures managed initlization parameters for a session. + /// + /// The period of time, in milliseconds, that the system waits for a member to join the session. + /// This value overrides the value of the memberReservedTimeout parameter for the MultiplayerSession.SetTimeouts Method + /// for the initial session members. + /// The period of time, in milliseconds, that the system waits for a measuring operation + /// during managed initialization. + /// Note: During matchmaking, a 45-second timeout for QoS measurements is enforced. Therefore we recommend the use of a + /// measurement timeout that is less than or equal to 30 seconds during matchmaking. + /// The period of time, in milliseconds, that the system waits for an evaluation. + /// True if the system should auto-evaluate the session service, and false if the title performs the evaluation. + /// The number of members needed to start the session, for initialization episode zero only. + /// + /// This can only be set when creating a new session. + /// + /// If a 'managedInitialization' object is set, the session expects the client system or title to perform + /// initialization following session creation and/or as new members join the session. + /// + /// The timeouts and initialization stages are automatically tracked by the session, including QoS + /// measurements if any metrics are set. These timeouts override the session's reservation and ready + /// timeouts for members that have 'initializationEpisode' set. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// +#if _MSC_VER >= 1800 + [Windows::Foundation::Metadata::Deprecated("Call SetMemberInitialization instead", Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0)] +#endif + void SetManagedInitialization( + _In_ Windows::Foundation::TimeSpan joinTimeout, + _In_ Windows::Foundation::TimeSpan measurementTimeout, + _In_ Windows::Foundation::TimeSpan evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32 membersNeededToStart + ); + + /// + /// Configures managed initlization parameters for a session. + /// + /// The period of time, in milliseconds, that the system waits for a member to join the session. + /// This value overrides the value of the memberReservedTimeout parameter for the MultiplayerSession.SetTimeouts Method + /// for the initial session members. + /// The period of time, in milliseconds, that the system waits for a measuring operation + /// during managed initialization. + /// Note: During matchmaking, a 45-second timeout for QoS measurements is enforced. Therefore we recommend the use of a + /// measurement timeout that is less than or equal to 30 seconds during matchmaking. + /// The period of time, in milliseconds, that the system waits for an evaluation. + /// True if the system should auto-evaluate the session service, and false if the title performs the evaluation. + /// The number of members needed to start the session, for initialization episode zero only. + /// + /// This can only be set when creating a new session. + /// + /// If a 'managedInitialization' object is set, the session expects the client system or title to perform + /// initialization following session creation and/or as new members join the session. + /// + /// The timeouts and initialization stages are automatically tracked by the session, including QoS + /// measurements if any metrics are set. These timeouts override the session's reservation and ready + /// timeouts for members that have 'initializationEpisode' set. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetMemberInitialization( + _In_ Windows::Foundation::TimeSpan joinTimeout, + _In_ Windows::Foundation::TimeSpan measurementTimeout, + _In_ Windows::Foundation::TimeSpan evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32 membersNeededToStart + ); + + /// + /// Sets thresholds that apply to each pairwise connection for all members in a session. + /// + /// The maximum latency, in milliseconds, between session members. + /// The minimum bandwidth, in kilobits per second, between members. + /// + /// The system or title calls SetPeerToPeerRequirements only when creating a new session. It accesses the + /// MultiplayerPeerToPeerRequirements Class. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetPeerToPeerRequirements( + _In_ Windows::Foundation::TimeSpan latencyMaximum, + _In_ uint32 bandwidthMinimumInKilobitsPerSecond + ); + + /// + /// Sets thresholds that apply to each connection between a host candidate and a session member. + /// + /// The maximum latency time, in milliseconds. + /// The minimum bandwidth, in kilobits per second, for information sent from the host to the session member. + /// The minimum bandwidth, in kilobits per second, for information sent from the session member to the host. + /// An enumeration value indicating the metric for the Xbox system to use in selecting a host. + /// + /// The system or title calls SetPeerToHostRequirements only when creating a new session. It accesses the + /// MultiplayerPeerToHostRequirements Class. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetPeerToHostRequirements( + _In_ Windows::Foundation::TimeSpan latencyMaximum, + _In_ uint32 bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32 bandwidthUpMinimumInKilobitsPerSecond, + _In_ MultiplayMetrics hostSelectionMetric + ); + + /// + /// Sets the connection paths and information for the servers that can be used for QoS measurements. + /// + /// A collection of QualityOfServiceServer objects, returned from + /// GameServerPlatformService::GetQualityOfServiceServersAsync(), that represent the servers. + /// + /// The system or title calls SetMeasurementServerAddresses only when creating a new session. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetMeasurementServerAddresses( + _In_ Windows::Foundation::Collections::IVectorView^ measurementServerAddresses + ); + + /// + /// Sets the capabilities of the session. + /// + /// A collection of MultiplayerSessionCapabilities flags that apply to + /// the MultiplayerSessionConstant's capabilities JSON object. + /// + /// This can only be set when creating a new session. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write + /// batched local changes to the service. + /// + void SetSessionCapabilities( + _In_ MultiplayerSessionCapabilities^ capabilities + ); + + /// + /// Sets a flag that indicates if the session initialization succeeded, + /// + /// True if initialization succeeded, and false otherwise. + /// + /// This can only be set when creating a new session. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service. + /// + void SetInitializationStatus( + _In_ bool initializationSucceeded + ); + + /// + /// Sets the device token of the host to use in multiplayer transactions. + /// + /// The host device token. + /// + /// The host device token is set in the local cache of the session and written to the multiplayer session directory. + /// + /// If the system or title calls SetHostDeviceToken and sets peer to host requirements with a call to + /// MultiplayerSession.SetPeerToHostRequirements, the measuring stage of managed initialization assumes that the + /// specified host is the correct host and only measures metrics to that host. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetHostDeviceToken( + _In_ Platform::String^ hostDeviceToken + ); + + /// + /// Forces a specific server connection string to be used. This is useful in preserveSession=always cases. + /// + /// The server connection path. Setting this path can be useful when the session is preserved. + /// + /// After calling SetMatchmakingServerConnectionPath, the system or title must call + /// MultiplayerService.WriteSessionAsync to write batched local changes to the service. + /// If SetMatchmakingServerConnectionPath is called without calling WriteSessionAsync, + /// it only changes the local session object but does not commit it to the service. + /// + void SetMatchmakingServerConnectionPath( + _In_ Platform::String^ serverConnectionPath + ); + + /// + /// Sets the session status to closed, meaning that new users will not be able to join the session + /// unless they already have a reservation. + /// + /// Whether new users will not be able to join the session unless they already have a reservation + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetClosed( + _In_ bool closed + ); + + /// + /// Sets a flag that indicates if a match is not successful and needs to be resubmitted, or if the match is successful + /// and the matchmaking service can release the session. + /// + /// True if the match that was found was not successful and needs to be resubmitted. + /// Set this value to false to indicate that the match was successful and the matchmaking service can release the session. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetMatchmakingResubmit( + _In_ bool matchResubmit + ); + + /// + /// Sets an ordered list of case-insensitive connection path strings that the session can use to connect to + /// a game server. Generally titles should use the first on the list, but sophisticated titles could use + /// a custom mechanism for choosing one of the others (e.g. based on load). + /// + /// The collection of connection paths. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetServerConnectionStringCandidates( + _In_ Windows::Foundation::Collections::IVectorView^ serverConnectionStringCandidates + ); + + /// + /// Sets the set of session changes that this client will be subscribed to. + /// Set to "MultiplayerSessionChangeTypes::None" to clear the subscription. + /// + /// An Or'd set of MultiplayerSessionChangeType enum values representing the change types to subscribe to. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetSessionChangeSubscription( + _In_ MultiplayerSessionChangeTypes changeTypes + ); + + /// + /// Removes the current member from a session. + /// + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void Leave(); + + /// + /// Set the multiplayer status of the current user to active or inactive. + + /// + /// Indicates the current user status + /// + /// The member must first be joined to the session before the system or the title can set the status. + /// Use AddMemberReservation() to add a member reservation. + /// You cannot set the the user's status to reserved or ready by using this method. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetCurrentUserStatus( + _In_ MultiplayerSessionMemberStatus status + ); + + /// + /// Sets the base64 encoded secure device address of the member. + /// + /// Indicates the value of the current user's secure device address encoded in base64. + /// + /// The member must first be joined to the session before the system or the title can set the secure device address. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetCurrentUserSecureDeviceAddressBase64( + _In_ Platform::String^ value + ); + + /// + /// Call multiplayer_service::write_session after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set the role info of the member. + /// The member must first be joined to the session. + /// + /// Indicates a collection of role types to role names for the current user. + void SetCurrentUserRoleInfo( + _In_ Windows::Foundation::Collections::IMapView^ roles + ); + + /// + /// Sets a collection of members that make up a group. + /// + /// A collection of MultiplayerSessionMember objects that represent the session members to make up the group. + /// + /// The members must first be joined to the session before the system or the title can call this method. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetCurrentUserMembersInGroup( + _In_ Windows::Foundation::Collections::IVectorView^ membersInGroup + ); + + /// + /// Sets the measurements to use to determine the quality of service (QoS) available for the current session member. + /// + /// A collection of objects representing the QoS measurements. + /// + /// This method is only useful when the title manually manages QoS. If the platform is automatically performing QoS, + /// the title does not need to call this method. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetCurrentUserQualityOfServiceMeasurements( + _In_ Windows::Foundation::Collections::IVectorView^ measurements + ); + + /// + /// Sets a JSON string with QoS measurements for the current session member. + /// + /// The JSON string representing the server measurements. + /// + /// This method is only useful when the title manually manages QoS. If the platform is automatically performing QoS, + /// the title does not need to call this method. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetCurrentUserQualityOfServiceServerMeasurementsJson( + _In_ Platform::String^ valueJson + ); + + /// + /// Call WriteSession() after this to write batched local changes to the service. + /// If this is called without multiplayer_service::write_session, this will only change the local session object but does not commit it to the service. + /// Set the arbitration results for a tournament game session. + /// + /// A map of team names to team results. + void SetCurrentUserArbitrationResults( + _In_ Windows::Foundation::Collections::IMapView^ results + ); + + /// + /// Set a custom property on the current user to the specified JSON string + /// The member must first be joined to the session. + /// + /// The name of the property to set. + /// (Optional) The JSON string value to assign to the property. + /// + /// This method is used to store per-member attributes, for example, during creation of a match ticket session. + /// The client calls the method for each session member. For a match ticket session, the method copies attributes + /// from the /members/{index}/properties/custom/matchAttrs field to + /// the /members/{index}/constants/custom/matchmakingResult/playerAttrs field. They are later combined and processed + /// by the matchmaking service when the session is passed to matchmaking in the call to the + /// MatchmakingService.CreateMatchTicketAsync Method during match ticket creation. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetCurrentUserMemberCustomPropertyJson( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson + ); + + /// + /// Delete a custom property on the current session member. + /// + /// The name of the property to delete. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void DeleteCurrentUserMemberCustomPropertyJson( + _In_ Platform::String^ name + ); + + /// + /// Sets matchmaking constants for the session. + /// + /// A JSON string representing the target session constants + /// + /// This method is optional. Only a client acting as a matchmaking service should call it. Its use + /// requires the MultiplayerSessionCapabilities.ClientMatchmaking Property to be set. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetMatchmakingTargetSessionConstantsJson( + _In_ Platform::String^ matchmakingTargetSessionConstants + ); + + /// + /// Set a session custom property to the specified JSON string. + /// + /// The name of the property to set. + /// (Optional) The JSON string value to assign to the property. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void SetSessionCustomPropertyJson( + _In_ Platform::String^ name, + _In_opt_ Platform::String^ valueJson + ); + + /// + /// Deletes a session custom property. + /// + /// The name of the property to set. + /// + /// After calling this method, the caller must use MultiplayerService.WriteSessionAsync to write batched local changes + /// to the service.If SetHostDeviceToken is called without calling WriteSessionAsync, it only changes the local session + /// object but does not commit it to the service. + /// + void DeleteSessionCustomPropertyJson( + _In_ Platform::String^ name + ); + + /// + /// Static compare method that compares two sessions and returns an Or'ed MultiplayerSessionChangeType. + /// + /// The current session to compare to an older session. + /// The older session to compare to the current session. + /// An OR'ed MultiplayerSessionChangeType that contains all of the differences. + static MultiplayerSessionChangeTypes CompareMultiplayerSessions( + _In_ MultiplayerSession^ currentSession, + _In_ MultiplayerSession^ oldSession + ); + + /// + /// Static method that converts an HTTP Status code to a WriteSessionStatus. + /// + /// Status code of a http result + /// A WriteSessionStatus which gives more specific information about the status code in regards to the Write Session call. + static WriteSessionStatus ConvertHttpStatusToWriteSessionStatus( + _In_ int32 httpStatusCode + ); + + /// + /// Internal function + /// + void _Init( + _In_ XboxLiveContext^ xboxLiveContext, + _In_ MultiplayerSessionReference^ multiplayerSessionReference, + _In_ uint32 maxMembersInSession, + _In_ MultiplayerSessionVisibility multiplayerSessionVisibility, + _In_opt_ Windows::Foundation::Collections::IVectorView^ initiatorXboxUserIds, + _In_opt_ Platform::String^ sessionCustomConstantsJson + ); + +internal: + MultiplayerSession( + _In_ std::shared_ptr cppObj + ); + + MultiplayerSessionMember^ JoinHelper( + _In_opt_ Platform::String^ memberCustomConstantsJson, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus, + _In_ bool addInitializePropertyToRequest + ); + + std::shared_ptr GetCppObj() const; +private: + std::shared_ptr m_cppObj; + MultiplayerSessionReference^ m_sessionReference; + MultiplayerSessionConstants^ m_sessionConstants; + MultiplayerSessionProperties^ m_sessionProperties; + MultiplayerSessionRoleTypes^ m_sessionRoleTypes; + MultiplayerSessionMember^ m_currentUser; + MultiplayerSessionMatchmakingServer^ m_matchmakingServer; + MultiplayerSessionTournamentsServer^ m_tournamentsServer; + MultiplayerSessionArbitrationServer^ m_arbitrationServer; + Windows::Foundation::Collections::IMapView^ m_roles; +}; + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.cpp b/Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.cpp new file mode 100644 index 00000000..1a0c3371 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.cpp @@ -0,0 +1,19 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplayerSubscriptionLostEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +MultiplayerSubscriptionLostEventArgs::MultiplayerSubscriptionLostEventArgs() +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.h b/Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.h new file mode 100644 index 00000000..e79e4042 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MultiplayerSubscriptionLostEventArgs_WinRT.h @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Arguments used when a multiplayer connection stopped event occurs. +/// Currently there are none. +/// +public ref class MultiplayerSubscriptionLostEventArgs sealed +{ +internal: + MultiplayerSubscriptionLostEventArgs(); +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/MutableRoleSetting_WinRT.h b/Source/Services/Multiplayer/WinRT/MutableRoleSetting_WinRT.h new file mode 100644 index 00000000..430c9871 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/MutableRoleSetting_WinRT.h @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Enumeration for the types of statuses that may result from a WriteSessionAsync. +/// +public enum class MutableRoleSetting +{ + /// + /// Allows you to set a max count for the multiplayer role + /// + Max = xbox::services::multiplayer::mutable_role_setting::max, + + /// + /// Allows you to set a target count for the multiplayer role + /// + Target = xbox::services::multiplayer::mutable_role_setting::target +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/NetworkAddressTranslationSetting_WinRT.h b/Source/Services/Multiplayer/WinRT/NetworkAddressTranslationSetting_WinRT.h new file mode 100644 index 00000000..5046dff6 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/NetworkAddressTranslationSetting_WinRT.h @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Defines values that indicate the current NAT setting for a device connecting to Xbox LIVE. +/// +public enum class NetworkAddressTranslationSetting +{ + /// + /// The server returned an unrecognized response. + /// + Unknown = xbox::services::multiplayer::network_address_translation_setting::unknown, + + /// + /// Can connect with any other devices regardless of their NAT setting. + /// + Open = xbox::services::multiplayer::network_address_translation_setting::open, + + /// + /// Devices using moderate NAT settings can only connect with other devices using moderate or open settings. + /// + Moderate = xbox::services::multiplayer::network_address_translation_setting::moderate, + + /// + /// Devices using strict NAT settings can only connect with other devices using open NAT settings. + /// + Strict = xbox::services::multiplayer::network_address_translation_setting::strict +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.cpp b/Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.cpp new file mode 100644 index 00000000..d7c69baa --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.cpp @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "WriteSessionResult_WinRT.h" + +using namespace xbox::services; +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +WriteSessionResult::WriteSessionResult( + _In_ bool succeeded, + _In_opt_ MultiplayerSession^ session, + _In_ WriteSessionStatus writeSessionStatus + ) : + m_succeeded(succeeded), + m_session(session), + m_status(writeSessionStatus) +{ +} + +bool +WriteSessionResult::Succeeded::get() +{ + return m_succeeded; +} + +MultiplayerSession^ +WriteSessionResult::Session::get() +{ + return m_session; +} + +WriteSessionStatus +WriteSessionResult::Status::get() +{ + return m_status; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.h b/Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.h new file mode 100644 index 00000000..870c6265 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/WriteSessionResult_WinRT.h @@ -0,0 +1,58 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "MultiplayerSession_WinRT.h" +#include "WriteSessionStatus_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Represents the result of a write session async. +/// +public ref class WriteSessionResult sealed +{ +public: + + /// + /// Indicates whether the WriteSessionAsync was successful. + /// + property bool Succeeded { bool get(); } + + /// + /// The MultiplayerSession returned from the WriteSessionAsync (if any). + /// + property MultiplayerSession^ Session { MultiplayerSession^ get(); } + + /// + /// A WriteSessionStatus enum which indicates the status of the session write operation. + /// + property WriteSessionStatus Status { WriteSessionStatus get(); } + +internal: + + WriteSessionResult(); + + WriteSessionResult( + _In_ bool succeeded, + _In_opt_ MultiplayerSession^ session, + _In_ WriteSessionStatus writeSessionStatus + ); + + static WriteSessionStatus ConvertHttpStatusToWriteSessionStatus( + _In_ int32_t httpStatusCode + ); + +private: + bool m_succeeded; + WriteSessionStatus m_status; + MultiplayerSession^ m_session; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/WinRT/WriteSessionStatus_WinRT.h b/Source/Services/Multiplayer/WinRT/WriteSessionStatus_WinRT.h new file mode 100644 index 00000000..aa29c054 --- /dev/null +++ b/Source/Services/Multiplayer/WinRT/WriteSessionStatus_WinRT.h @@ -0,0 +1,61 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_BEGIN + +/// +/// Enumeration for the types of statuses that may result from a WriteSessionAsync. +/// +public enum class WriteSessionStatus +{ + /// + /// Unknown status. + /// + Unknown = xbox::services::multiplayer::write_session_status::unknown, + + /// + /// HTTP/403 status, access denied. + /// + AccessDenied = xbox::services::multiplayer::write_session_status::access_denied, + + /// + /// HTTP/201 status, created. + /// + Created = xbox::services::multiplayer::write_session_status::created, + + /// + /// HTTP/409 status, conflict. + /// + Conflict = xbox::services::multiplayer::write_session_status::conflict, + + /// + /// HTTP/404 status, handle not found. + /// + HandleNotFound = xbox::services::multiplayer::write_session_status::handle_not_found, + + /// + /// HTTP/412 status, out of sync. + /// + OutOfSync = xbox::services::multiplayer::write_session_status::out_of_sync, + + /// + /// HTTP/204 status, session deleted. + /// + SessionDeleted = xbox::services::multiplayer::write_session_status::session_deleted, + + /// + /// HTTP/200 status, updated. + /// + Updated = xbox::services::multiplayer::write_session_status::updated +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_END + diff --git a/Source/Services/Multiplayer/multiplayer_activity_details.cpp b/Source/Services/Multiplayer/multiplayer_activity_details.cpp new file mode 100644 index 00000000..0906a332 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_activity_details.cpp @@ -0,0 +1,127 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_activity_details::multiplayer_activity_details() : + m_titleId(0), + m_visibility(multiplayer_session_visibility::unknown), + m_joinRestriction(multiplayer_session_restriction::unknown), + m_closed(false), + m_maxMembersCount(0), + m_membersCount(0) +{ +} + +const multiplayer_session_reference& +multiplayer_activity_details::session_reference() const +{ + return m_sessionReference; +} + +const string_t& +multiplayer_activity_details::handle_id() const +{ + return m_handleId; +} + +uint32_t +multiplayer_activity_details::title_id() const +{ + return m_titleId; +} + +multiplayer_session_visibility +multiplayer_activity_details::visibility() const +{ + return m_visibility; +} + +multiplayer_session_restriction +multiplayer_activity_details::join_restriction() const +{ + return m_joinRestriction; +} + +bool +multiplayer_activity_details::closed() const +{ + return m_closed; +} + +const string_t& +multiplayer_activity_details::owner_xbox_user_id() const +{ + return m_ownerXboxUserId; +} + +uint32_t +multiplayer_activity_details::max_members_count() const +{ + return m_maxMembersCount; +} + +uint32_t +multiplayer_activity_details::members_count() const +{ + return m_membersCount; +} + +xbox_live_result +multiplayer_activity_details::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_activity_details returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + string_t type = utils::extract_json_string(json, _T("type"), errc); + + if (type.compare(_T("activity")) != 0) + { + return xbox_live_result(xbox_live_error_code::json_error, "Unexpected content"); + } + + returnResult.m_handleId = utils::extract_json_string(json, _T("id"), errc); + auto sessionReference = multiplayer_session_reference::_Deserialize( + utils::extract_json_field(json, _T("sessionRef"), errc, false) + ); + + if (sessionReference.err()) + { + errc = sessionReference.err(); + } + returnResult.m_sessionReference = sessionReference.payload(); + + returnResult.m_ownerXboxUserId = utils::extract_json_string(json, _T("ownerXuid"), errc); + + returnResult.m_titleId = utils::string_t_to_uint32(utils::extract_json_string(json, _T("titleId"), errc)); + + web::json::value relatedInfoObject = utils::extract_json_field(json, _T("relatedInfo"), errc, false); + if (!relatedInfoObject.is_null()) + { + returnResult.m_membersCount = utils::extract_json_int(relatedInfoObject, _T("membersCount"), errc); + returnResult.m_maxMembersCount = utils::extract_json_int(relatedInfoObject, _T("maxMembersCount"), errc); + returnResult.m_joinRestriction = multiplayer_session_states::_Convert_string_to_multiplayer_session_restriction( + utils::extract_json_string(relatedInfoObject, _T("joinRestriction"), errc) + ); + returnResult.m_visibility = multiplayer_session_states::_Convert_string_to_session_visibility( + utils::extract_json_string(relatedInfoObject, _T("visibility"), errc) + ); + + returnResult.m_closed = utils::extract_json_bool(relatedInfoObject, _T("closed"), errc); + } + + return returnResult; +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_activity_handle_post_request.cpp b/Source/Services/Multiplayer/multiplayer_activity_handle_post_request.cpp new file mode 100644 index 00000000..16467e2b --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_activity_handle_post_request.cpp @@ -0,0 +1,55 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_activity_handle_post_request::multiplayer_activity_handle_post_request() : + m_version(0) +{ +} + +multiplayer_activity_handle_post_request::multiplayer_activity_handle_post_request( + _In_ multiplayer_session_reference sessionReference, + _In_ uint32_t version + ) : + m_sessionReference(std::move(sessionReference)), + m_version(version) +{ + XSAPI_ASSERT(!m_sessionReference.is_null()); +} + +const multiplayer_session_reference& +multiplayer_activity_handle_post_request::session_reference() const +{ + return m_sessionReference; +} + +uint32_t +multiplayer_activity_handle_post_request::version() const +{ + return m_version; +} + +web::json::value +multiplayer_activity_handle_post_request::serialize() const +{ + web::json::value serializedObject; + + serializedObject[_T("type")] = web::json::value::string(_T("activity")); + serializedObject[_T("sessionRef")] = m_sessionReference._Serialize(); + serializedObject[_T("version")] = web::json::value(m_version); + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_activity_query_post_request.cpp b/Source/Services/Multiplayer/multiplayer_activity_query_post_request.cpp new file mode 100644 index 00000000..37ffba56 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_activity_query_post_request.cpp @@ -0,0 +1,91 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_activity_query_post_request::multiplayer_activity_query_post_request() +{ +} + +multiplayer_activity_query_post_request::multiplayer_activity_query_post_request( + _In_ string_t scid, + _In_ std::vector xuids + ) : + m_scid(std::move(scid)), + m_xuids(std::move(xuids)) +{ +} + +multiplayer_activity_query_post_request::multiplayer_activity_query_post_request( + _In_ string_t scid, + _In_ string_t socialGroup, + _In_ string_t socialGroupXuid + ) : + m_scid(std::move(scid)), + m_socialGroup(std::move(socialGroup)), + m_socialGroupXuid(std::move(socialGroupXuid)) +{ +} + +const string_t& +multiplayer_activity_query_post_request::scid() const +{ + return m_scid; +} + +const std::vector& +multiplayer_activity_query_post_request::xuids() const +{ + return m_xuids; +} +const string_t& +multiplayer_activity_query_post_request::social_group() const +{ + return m_socialGroup; +} + +const string_t& +multiplayer_activity_query_post_request::social_group_xuid() const +{ + return m_socialGroupXuid; +} + +web::json::value +multiplayer_activity_query_post_request::serialize() +{ + XSAPI_ASSERT(m_socialGroup.empty() || m_xuids.empty()); + XSAPI_ASSERT(!m_socialGroup.empty() || !m_xuids.empty()); + + web::json::value serializedObject; + serializedObject[_T("type")] = web::json::value::string(_T("activity")); + serializedObject[_T("scid")] = web::json::value::string(m_scid); + + web::json::value ownerObject; + if (!m_xuids.empty()) + { + ownerObject[_T("xuids")] = utils::serialize_vector(utils::json_string_serializer, m_xuids); + } + else + { + web::json::value peopleObject; + peopleObject[_T("moniker")] = web::json::value::string(m_socialGroup); + peopleObject[_T("monikerXuid")] = web::json::value::string(m_socialGroupXuid); + ownerObject[_T("people")] = std::move(peopleObject); + } + + serializedObject[_T("owners")] = ownerObject; + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_get_sessions_request.cpp b/Source/Services/Multiplayer/multiplayer_get_sessions_request.cpp new file mode 100644 index 00000000..bc499cae --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_get_sessions_request.cpp @@ -0,0 +1,165 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_get_sessions_request::multiplayer_get_sessions_request( + _In_ string_t serviceConfigurationId, + _In_ uint32_t maxItems + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_maxItems(maxItems), + m_visibilityFilter(multiplayer_session_visibility::open), + m_contractVersionFilter(0) +{ +} + +const string_t& +multiplayer_get_sessions_request::service_configuration_id() +{ + return m_serviceConfigurationId; +} + +uint32_t +multiplayer_get_sessions_request::max_items() +{ + return m_maxItems; +} + +bool +multiplayer_get_sessions_request::include_private_sessions() +{ + return m_includePrivateSessions; +} + +void +multiplayer_get_sessions_request::set_include_private_sessions( + _In_ bool includePrivateSessions + ) +{ + m_includePrivateSessions = includePrivateSessions; +} + +bool +multiplayer_get_sessions_request::include_reservations() +{ + return m_includeReservations; +} + +void +multiplayer_get_sessions_request::set_include_reservations( + _In_ bool includeResevations + ) +{ + m_includeReservations = includeResevations; +} + +bool +multiplayer_get_sessions_request::include_inactive_sessions() +{ + return m_includeInactiveSessions; +} + +void +multiplayer_get_sessions_request::set_include_inactive_sessions( + _In_ bool includeInactiveSessions + ) +{ + m_includeInactiveSessions = includeInactiveSessions; +} + +const string_t& +multiplayer_get_sessions_request::xbox_user_id_filter() +{ + return m_xboxUserIdFilter; +} + +void +multiplayer_get_sessions_request::set_xbox_user_id_filter( + _In_ const string_t& filter + ) +{ + m_xboxUserIdFilter = std::move(filter); +} + +const std::vector& +multiplayer_get_sessions_request::xbox_user_ids_filter() +{ + return m_xboxUserIdsFilter; +} + +void +multiplayer_get_sessions_request::set_xbox_user_ids_filter( + _In_ std::vector filter + ) +{ + m_xboxUserIdsFilter = std::move(filter); +} + +const string_t& +multiplayer_get_sessions_request::keyword_filter() +{ + return m_keywordFilter; +} + +void +multiplayer_get_sessions_request::set_keyword_filter( + _In_ const string_t& filter + ) +{ + m_keywordFilter = std::move(filter); +} + +const string_t& +multiplayer_get_sessions_request::session_template_name_filter() +{ + return m_sessionTemplateNameFilter; +} + +void +multiplayer_get_sessions_request::set_session_template_name_filter( + _In_ const string_t& filter + ) +{ + m_sessionTemplateNameFilter = std::move(filter); + +} + +multiplayer_session_visibility +multiplayer_get_sessions_request::visibility_filter() +{ + return m_visibilityFilter; +} + +void +multiplayer_get_sessions_request::set_visibility_filter( + _In_ multiplayer_session_visibility filter + ) +{ + m_visibilityFilter = filter; +} + +uint32_t +multiplayer_get_sessions_request::contract_version_filter() +{ + return m_contractVersionFilter; +} + +void +multiplayer_get_sessions_request::set_contract_version_filter( + _In_ uint32_t filter + ) +{ + m_contractVersionFilter = filter; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_internal.h b/Source/Services/Multiplayer/multiplayer_internal.h new file mode 100644 index 00000000..f84638f7 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_internal.h @@ -0,0 +1,477 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "system_internal.h" +#include "xsapi/multiplayer.h" +namespace xbox { namespace services { namespace tournaments { + class tournament_team_result; +}}} + +namespace xbox { namespace services { namespace multiplayer { + +class multiplayer_invite_handle_post_request +{ +public: + /// + /// Internal function + /// + multiplayer_invite_handle_post_request(); + + /// + /// Internal function + /// + multiplayer_invite_handle_post_request( + _In_ multiplayer_session_reference sessionReference, + _In_ uint32_t version, + _In_ string_t invitedXboxUserId, + _In_ uint32_t titleId, + _In_ string_t contextString, + _In_ string_t customActivationContext + ); + + /// + /// Internal function + /// + const multiplayer_session_reference& session_reference() const; + + /// + /// Internal function + /// + uint32_t version() const; + + /// + /// Internal function + /// + const string_t& invited_xbox_user_id() const; + + /// + /// Internal function + /// + uint32_t title_id() const; + + /// + /// Internal function + /// + const string_t& context_string() const; + + /// + /// Internal function + /// + const string_t& custom_activation_context() const; + + /// + /// Internal function + /// + web::json::value serialize() const; + +private: + multiplayer_session_reference m_sessionReference; + uint32_t m_version; + string_t m_invitedXboxUserId; + uint32_t m_titleId; + string_t m_contextString; + string_t m_customActivationContext; +}; + +class multiplayer_subscription : public xbox::services::real_time_activity::real_time_activity_subscription +{ +public: + multiplayer_subscription( + _In_ const std::function& multiplayerSessionChangeHandler, + _In_ const std::function& multiplayerSubscriptionLostHandler, + _In_ const std::function& subscriptionErrorHandler + ); + + void _Set_state(_In_ xbox::services::real_time_activity::real_time_activity_subscription_state newState) override; + const string_t& rta_connection_id() const; + pplx::task_completion_event> task; + +protected: + void on_subscription_created(_In_ uint32_t id, _In_ const web::json::value& data) override; + void on_event_received(_In_ const web::json::value& data) override; + +private: + string_t m_mpConnectionId; + std::function m_multiplayerSessionChangeHandler; + std::function m_multiplayerSubscriptionLostHandler; +}; + + +class multiplayer_activity_query_post_request +{ +public: + multiplayer_activity_query_post_request(); + multiplayer_activity_query_post_request(_In_ string_t scid, _In_ std::vector xuids); + multiplayer_activity_query_post_request(_In_ string_t scid, _In_ string_t socialGroup, _In_ string_t socialGroupXuid); + + const string_t& scid() const; + const std::vector& xuids() const; + const string_t& social_group() const; + const string_t& social_group_xuid() const; + + web::json::value serialize(); +private: + string_t m_scid; + std::vector m_xuids; + string_t m_socialGroupXuid; + string_t m_socialGroup; +}; + +class multiplayer_session_member_request +{ +public: + multiplayer_session_member_request(); + + multiplayer_session_member_request( + _In_ bool writeRequest, + _In_ string_t memberId, + _In_ string_t xboxUserId, + _In_ web::json::value memberConstants, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializeRequested + ); + + bool write_request() const; + bool write_constants() const; + const string_t& member_id() const; + const web::json::value& custom_constants() const; + + const web::json::value& custom_properties() const; + void set_custom_properties(_In_ web::json::value customProperties); + std::error_code set_custom_properties_property( + _In_ string_t name, + _In_ web::json::value customProperty + ); + + const string_t& xbox_user_id() const; + + bool is_active() const; + void set_is_active(_In_ bool isActive); + + bool write_is_active() const; + void set_write_is_active(_In_ bool writeIsActive); + + const string_t& service_device_address_base64() const; + void set_secure_device_address_base64(_In_ string_t deviceAddress); + + void set_role_info(_In_ const std::unordered_map& roles); + + bool write_secure_device_address_base64() const; + void set_write_secure_device_address_base64(_In_ bool shouldWrite); + + bool does_initialized_requested_exist() const; + bool initialize_requested() const; + + const web::json::value& member_measurements_json() const; + void set_member_measurements_json(_In_ web::json::value memberMeasurements); + + bool write_member_measurements_json() const; + void set_write_member_measurements_json(_In_ bool shouldWrite); + + const web::json::value& member_server_measurements_json() const; + void set_member_server_measurements_json(_In_ web::json::value json); + + bool write_member_server_measurements_json() const; + void set_write_member_server_measurements_json(_In_ bool shouldWrite); + + std::vector members_in_group() const; + void set_members_in_group(_In_ std::vector membersInGroup); + + bool write_members_in_group() const; + void set_write_members_in_group(_In_ bool writeMembersInGroup); + + const std::vector& groups() const; + void set_groups(_In_ std::vector groups); + + const std::vector& encounters() const; + void set_encounters(_In_ std::vector encounters); + + bool write_subscribed_change_types() const; + void set_write_subscribed_change_types(_In_ bool shouldWrite); + + multiplayer_session_change_types subscribed_change_types() const; + void set_subscribed_change_types(_In_ multiplayer_session_change_types changeTypes); + + const string_t& subscription_id() const; + void set_subscription_id(_In_ string_t subscriptionId); + + const string_t& rta_connection_id() const; + void set_rta_connection_id(_In_ string_t connectionId); + + const std::unordered_map& results() const; + void set_result(_In_ const string_t& team, _In_ const xbox::services::tournaments::tournament_team_result& result); + void set_results(_In_ const std::unordered_map& results); + + web::json::value serialize(); +private: + static std::vector get_vector_view_for_change_types(_In_ multiplayer_session_change_types changeTypes); + + bool m_writeRequest; + bool m_writeConstants; + string_t m_memberId; + web::json::value m_customConstants; + web::json::value m_customProperties; + string_t m_xboxUserId; + bool m_writeIsActive; + bool m_isActive; + std::unordered_map m_roles; + bool m_writeRoleInfo; + string_t m_serviceDeviceAddressBase64; + bool m_writeSecureDeviceAddressBase64; + bool m_addInitializePropertyToRequest; + bool m_initializeRequested; + bool m_writeMemberMeasurementsJson; + web::json::value m_memberMeasurementsJson; + bool m_writeMemberServerMeasurementsJson; + web::json::value m_memberServerMeasurementsJson; + bool m_writeMembersInGroup; + std::vector m_membersInGroup; + std::vector m_groups; + std::vector m_encounters; + bool m_writeSubscribedChangeType; + multiplayer_session_change_types m_changeTypes; + string_t m_subscriptionId; + string_t m_rtaConnectionId; + std::unordered_map m_results; +}; + +/// +/// Represents a reference to member in a multiplayer session. +/// +class multiplayer_session_request +{ +public: + multiplayer_session_request(); + multiplayer_session_request( + _In_opt_ std::shared_ptr multiplayerSessionConstants + ); + + std::shared_ptr create_deep_copy(); + + std::shared_ptr add_member_request( + _In_ bool writeRequest, + _In_ bool isMe, + _In_ string_t xboxUserId, + _In_ web::json::value memberConstants, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializedRequested + ); + + void leave_session(); + void set_leave_session(_In_ bool leaveSession); + + const multiplayer_session_reference& session_reference() const; + void set_session_reference(_In_ multiplayer_session_reference sessionReference); + + std::shared_ptr session_constants() const; + void set_session_constants(_In_ std::shared_ptr sessionConstants); + + const std::vector& session_properties_keywords() const; + void set_session_properties_keywords(_In_ std::vector keywords); + + const std::vector& session_properties_turns() const; + void set_session_properties_turns(_In_ std::vector sessionProperties); + + multiplayer_session_restriction join_restriction() const; + void set_join_restriction(_In_ multiplayer_session_restriction joinRestriction); + + multiplayer_session_restriction read_restriction() const; + void set_read_restriction(_In_ multiplayer_session_restriction readRestriction); + + const web::json::value& session_properties_custom_properties() const; + void set_session_custom_properties(_In_ web::json::value sessionCustomProperties); + + bool write_matchmaking_client_result() const; + void set_write_matchmaking_client_result(_In_ bool writeMatchmakingClientResult); + + bool write_matchmaking_session_constants() const; + void set_write_matchmaking_session_constants(_In_ bool matchmakingSessionConstant); + + const web::json::value& session_properties_target_sessions_constants() const; + void set_session_properties_target_sessions_constants(_In_ web::json::value targetSessionsConstants); + + bool write_initialization_status() const; + void set_write_initialization_status(_In_ bool status); + + bool initialization_succeeded() const; + void set_initialization_succeeded(_In_ bool succeeded); + + bool write_host_device_token() const; + void set_write_host_device_token(_In_ bool writeToken); + + const string_t& host_device_token() const; + void set_host_device_token(_In_ string_t deviceToken); + + bool write_matchmaking_server_connection_path() const; + void set_write_matchmaking_server_connection_path(_In_ bool writePath); + + const string_t& matchmaking_server_connection_path() const; + void set_matchmaking_server_connection_path(_In_ string_t serverPath); + + bool write_matchmaking_resubmit() const; + void set_write_matchmaking_resubmit(_In_ bool writeMatchmakingResubmit); + + bool matchmaking_match_resubmit() const; + void set_matchmaking_match_resubmit(_In_ bool matchmakingResubmit); + + bool write_server_connection_string_candidates() const; + void set_write_server_connection_string_candidates(_In_ bool writeCandidates); + + const std::vector& server_connection_string_candidates() const; + void set_server_connection_string_candidates(_In_ std::vector candidates); + + const std::vector>& members() const; + void set_members(_In_ std::vector> members); + + web::json::value servers() const; + void set_servers(_In_ web::json::value servers); + + bool write_closed() const; + void set_write_closed(_In_ bool writeClosed); + + bool closed() const; + void set_closed(_In_ bool closed); + + void set_mutable_role_settings(_In_ const std::unordered_map& roleTypes); + + web::json::value create_properties_json(); + web::json::value create_matchmaking_json(); + web::json::value create_role_types_json(); + web::json::value serialize(); + +private: + void deep_copy_from( + _In_ const multiplayer_session_request& other + ); + + multiplayer_session_reference m_sessionReference; + std::unordered_map m_roleTypes; + std::shared_ptr m_sessionConstants; + multiplayer_session_member_request m_memberRequest; + std::vector m_sessionPropertiesKeywords; + std::vector m_sessionPropertiesTurns; + multiplayer_session_restriction m_joinRestriction; + multiplayer_session_restriction m_readRestriction; + web::json::value m_sessionPropertiesCustomProperties; + bool m_writeMatchmakingClientResult; + bool m_writeMatchmakingSessionConstants; + web::json::value m_sessionPropertiesTargetSessionsConstants; + bool m_writeInitializationStatus; + bool m_initializationSucceeded; + bool m_writeHostDeviceToken; + string_t m_hostDeviceToken; + bool m_writeMatchmakingServerConnectionPath; + string_t m_matchmakingServerConnectionPath; + bool m_writeMatchmakingResubmit; + bool m_matchmakingMatchResubmit; + bool m_writeServerConnectionStringCandidates; + std::vector m_serverConnectionStringCandidates; + std::vector> m_members; + web::json::value m_servers; + uint32_t m_memberRequestIndex; + bool m_bLeaveSession; + xbox::services::system::xbox_live_mutex m_lock; + bool m_writeClosed; + bool m_closed; +}; + +class multiplayer_invite +{ +public: + multiplayer_invite(); + + const string_t& handle_id() const; + + static xbox_live_result deserialize(_In_ const web::json::value& inputJson); + +private: + string_t m_handleId; +}; + +class multiplayer_activity_handle_post_request +{ +public: + multiplayer_activity_handle_post_request(); + multiplayer_activity_handle_post_request(_In_ multiplayer_session_reference sessionReference, _In_ uint32_t version); + + const multiplayer_session_reference& session_reference() const; + uint32_t version() const; + + web::json::value serialize() const; +private: + multiplayer_session_reference m_sessionReference; + uint32_t m_version; +}; + +class multiplayer_transfer_handle_post_request +{ +public: + multiplayer_transfer_handle_post_request(); + multiplayer_transfer_handle_post_request( + _In_ multiplayer_session_reference targetSessionReference, + _In_ multiplayer_session_reference originSessionReference, + _In_ uint32_t version + ); + + const multiplayer_session_reference& origin_session_reference() const; + const multiplayer_session_reference& target_session_reference() const; + uint32_t version() const; + + web::json::value serialize() const; +private: + multiplayer_session_reference m_originSessionReference; + multiplayer_session_reference m_targetSessionReference; + uint32_t m_version; +}; + +class multiplayer_service_impl : public std::enable_shared_from_this +{ +public: + multiplayer_service_impl( + _In_ std::shared_ptr rtaService + ); + + void multiplayer_session_changed(_In_ const multiplayer_session_change_event_args& eventArgs); + void multiplayer_subscription_lost(); + + pplx::task> ensure_multiplayer_subscription(); + + std::error_code enable_multiplayer_subscriptions(); + + void disable_multiplayer_subscriptions(); + + bool subscriptions_enabled(); + + function_context add_multiplayer_session_changed_handler(_In_ std::function handler); + + void remove_multiplayer_session_changed_handler(_In_ function_context context); + + function_context add_multiplayer_subscription_lost_handler(_In_ std::function handler); + + void remove_multiplayer_subscription_lost_handler(_In_ function_context context); + + ~multiplayer_service_impl(); + +private: + std::shared_ptr m_realTimeActivityService; + std::shared_ptr m_subscription; + std::unordered_map> m_sessionChangeEventHandler; + std::unordered_map> m_multiplayerSubscriptionLostEventHandler; + + function_context m_sessionChangeEventHandlerCounter; + function_context m_multiplayerSubscriptionLostEventHandlerCounter; + + bool m_subscriptionEnabled; + xbox::services::system::xbox_live_mutex m_subscriptionEnabledLock; + xbox::services::system::xbox_live_mutex m_subscriptionLock; + function_context m_multiplayerJoinabilityChangeCounter; +}; + +}}} \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_invite.cpp b/Source/Services/Multiplayer/multiplayer_invite.cpp new file mode 100644 index 00000000..3dd9b997 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_invite.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_invite::multiplayer_invite() +{ +} + +const string_t& +multiplayer_invite::handle_id() const +{ + return m_handleId; +} + +xbox_live_result +multiplayer_invite::deserialize( + _In_ const web::json::value& inputJson + ) +{ + multiplayer_invite returnResult; + if (inputJson.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + returnResult.m_handleId = utils::extract_json_string(inputJson, _T("id"), errc); + + return xbox_live_result(returnResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_invite_handle_post_request.cpp b/Source/Services/Multiplayer/multiplayer_invite_handle_post_request.cpp new file mode 100644 index 00000000..b5575424 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_invite_handle_post_request.cpp @@ -0,0 +1,105 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_invite_handle_post_request::multiplayer_invite_handle_post_request() : + m_version(0), + m_titleId(0) +{ +} + +multiplayer_invite_handle_post_request::multiplayer_invite_handle_post_request( + _In_ multiplayer_session_reference sessionReference, + _In_ uint32_t version, + _In_ string_t invitedXboxUserId, + _In_ uint32_t titleId, + _In_ string_t contextString, + _In_ string_t customActivationContext + ) : + m_sessionReference(std::move(sessionReference)), + m_version(version), + m_invitedXboxUserId(std::move(invitedXboxUserId)), + m_titleId(titleId), + m_contextString(std::move(contextString)), + m_customActivationContext(std::move(customActivationContext)) +{ + XSAPI_ASSERT(!m_sessionReference.is_null()); + XSAPI_ASSERT(!m_invitedXboxUserId.empty()); +} + +const multiplayer_session_reference& +multiplayer_invite_handle_post_request::session_reference() const +{ + return m_sessionReference; +} + +uint32_t +multiplayer_invite_handle_post_request::version() const +{ + return m_version; +} + +const string_t& +multiplayer_invite_handle_post_request::invited_xbox_user_id() const +{ + return m_invitedXboxUserId; +} + +uint32_t +multiplayer_invite_handle_post_request::title_id() const +{ + return m_titleId; +} + +const string_t& +multiplayer_invite_handle_post_request::context_string() const +{ + return m_contextString; +} + +const string_t& +multiplayer_invite_handle_post_request::custom_activation_context() const +{ + return m_customActivationContext; +} + +web::json::value +multiplayer_invite_handle_post_request::serialize() const +{ + web::json::value serializedObject; + serializedObject[_T("type")] = web::json::value::string(_T("invite")); + serializedObject[_T("sessionRef")] = m_sessionReference._Serialize(); + serializedObject[_T("version")] = web::json::value(m_version); + serializedObject[_T("invitedXuid")] = web::json::value(m_invitedXboxUserId); + + web::json::value jsonInviteAttributes; + stringstream_t titleIdStream; + titleIdStream << m_titleId; + jsonInviteAttributes[_T("titleId")] = web::json::value::string(titleIdStream.str()); + + if (!m_contextString.empty()) + { + jsonInviteAttributes[_T("contextString")] = web::json::value::string(m_contextString); + } + + if (!m_customActivationContext.empty()) + { + jsonInviteAttributes[_T("context")] = web::json::value::string(m_customActivationContext); + } + serializedObject[_T("inviteAttributes")] = std::move(jsonInviteAttributes); + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_managed_initialization.cpp b/Source/Services/Multiplayer/multiplayer_managed_initialization.cpp new file mode 100644 index 00000000..da4dcdcd --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_managed_initialization.cpp @@ -0,0 +1,122 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_managed_initialization::multiplayer_managed_initialization(): + m_managedInitializationSet(false), + m_autoEvaluate(false), + m_writeManagedInitialization(false), + m_membersNeededToStart(0) +{ +} + +multiplayer_managed_initialization::multiplayer_managed_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measureTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool autoEvaluate, + _In_ uint32_t membersNeededToStart + ) : + m_joinTimeout(std::move(joinTimeout)), + m_measurementTimeout(std::move(measureTimeout)), + m_evaluationTimeout(std::move(evaluationTimeout)), + m_autoEvaluate(autoEvaluate), + m_membersNeededToStart(membersNeededToStart), + m_managedInitializationSet(true), + m_writeManagedInitialization(true) +{ +} + +bool +multiplayer_managed_initialization::managed_initialization_set() const +{ + return m_managedInitializationSet; +} + +const std::chrono::milliseconds& +multiplayer_managed_initialization::join_timeout() const +{ + return m_joinTimeout; +} + +const std::chrono::milliseconds& +multiplayer_managed_initialization::measurement_timeout() const +{ + return m_measurementTimeout; +} + +const std::chrono::milliseconds& +multiplayer_managed_initialization::evaluation_timeout() const +{ + return m_evaluationTimeout; +} + +bool +multiplayer_managed_initialization::auto_evaluate() const +{ + return m_autoEvaluate; +} + +uint32_t +multiplayer_managed_initialization::members_need_to_start() const +{ + return m_membersNeededToStart; +} + +web::json::value +multiplayer_managed_initialization::_Serialize() +{ + web::json::value serializedObject; + if (m_writeManagedInitialization) + { + serializedObject[_T("joinTimeout")] = utils::serialize_uint52_to_json(m_joinTimeout.count()); + serializedObject[_T("measurementTimeout")] = utils::serialize_uint52_to_json(m_measurementTimeout.count()); + if (!m_autoEvaluate) + { + serializedObject[_T("evaluationTimeout")] = utils::serialize_uint52_to_json(m_evaluationTimeout.count()); + } + serializedObject[_T("externalEvaluation")] = web::json::value(!m_autoEvaluate); + serializedObject[_T("membersNeededToStart")] = web::json::value(m_membersNeededToStart); + } + + return serializedObject; +} + +xbox_live_result +multiplayer_managed_initialization::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_managed_initialization returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value managedInitializationJson = utils::extract_json_field(json, _T("memberInitialization"), errc, false); + + returnObject.m_managedInitializationSet = !managedInitializationJson.is_null(); + + if (returnObject.m_managedInitializationSet) + { + returnObject.m_joinTimeout = std::chrono::milliseconds(utils::extract_json_uint52(managedInitializationJson, _T("joinTimeout"), errc)); + returnObject.m_measurementTimeout = std::chrono::milliseconds(utils::extract_json_uint52(managedInitializationJson, _T("measurementTimeout"), errc)); + returnObject.m_evaluationTimeout = std::chrono::milliseconds(utils::extract_json_uint52(managedInitializationJson, _T("evaluationTimeout"), errc)); + returnObject.m_autoEvaluate = !utils::extract_json_bool(managedInitializationJson, _T("externalEvaluation"), errc); + returnObject.m_membersNeededToStart = utils::extract_json_int(managedInitializationJson, _T("membersNeededToStart"), errc); + } + + return returnObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_member_initialization.cpp b/Source/Services/Multiplayer/multiplayer_member_initialization.cpp new file mode 100644 index 00000000..c8cf7f4d --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_member_initialization.cpp @@ -0,0 +1,122 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_member_initialization::multiplayer_member_initialization() : + m_managedInitializationSet(false), + m_externalEvaluation(false), + m_writeManagedInitialization(false), + m_membersNeededToStart(0) +{ +} + +multiplayer_member_initialization::multiplayer_member_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measureTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool externalEvaluation, + _In_ uint32_t membersNeededToStart + ) : + m_joinTimeout(std::move(joinTimeout)), + m_measurementTimeout(std::move(measureTimeout)), + m_evaluationTimeout(std::move(evaluationTimeout)), + m_externalEvaluation(externalEvaluation), + m_membersNeededToStart(membersNeededToStart), + m_managedInitializationSet(true), + m_writeManagedInitialization(true) +{ +} + +bool +multiplayer_member_initialization::member_initialization_set() const +{ + return m_managedInitializationSet; +} + +const std::chrono::milliseconds& +multiplayer_member_initialization::join_timeout() const +{ + return m_joinTimeout; +} + +const std::chrono::milliseconds& +multiplayer_member_initialization::measurement_timeout() const +{ + return m_measurementTimeout; +} + +const std::chrono::milliseconds& +multiplayer_member_initialization::evaluation_timeout() const +{ + return m_evaluationTimeout; +} + +bool +multiplayer_member_initialization::external_evaluation() const +{ + return m_externalEvaluation; +} + +uint32_t +multiplayer_member_initialization::members_need_to_start() const +{ + return m_membersNeededToStart; +} + +web::json::value +multiplayer_member_initialization::_Serialize() +{ + web::json::value serializedObject; + if (m_writeManagedInitialization) + { + serializedObject[_T("joinTimeout")] = utils::serialize_uint52_to_json(m_joinTimeout.count()); + serializedObject[_T("measurementTimeout")] = utils::serialize_uint52_to_json(m_measurementTimeout.count()); + if (m_externalEvaluation) + { + serializedObject[_T("evaluationTimeout")] = utils::serialize_uint52_to_json(m_evaluationTimeout.count()); + } + serializedObject[_T("externalEvaluation")] = web::json::value(m_externalEvaluation); + serializedObject[_T("membersNeededToStart")] = web::json::value(m_membersNeededToStart); + } + + return serializedObject; +} + +xbox_live_result +multiplayer_member_initialization::_Deserialize( + _In_ const web::json::value& json +) +{ + multiplayer_member_initialization returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value managedInitializationJson = utils::extract_json_field(json, _T("memberInitialization"), errc, false); + + returnObject.m_managedInitializationSet = !managedInitializationJson.is_null(); + + if (returnObject.m_managedInitializationSet) + { + returnObject.m_joinTimeout = std::chrono::milliseconds(utils::extract_json_uint52(managedInitializationJson, _T("joinTimeout"), errc)); + returnObject.m_measurementTimeout = std::chrono::milliseconds(utils::extract_json_uint52(managedInitializationJson, _T("measurementTimeout"), errc)); + returnObject.m_evaluationTimeout = std::chrono::milliseconds(utils::extract_json_uint52(managedInitializationJson, _T("evaluationTimeout"), errc)); + returnObject.m_externalEvaluation = utils::extract_json_bool(managedInitializationJson, _T("externalEvaluation"), errc); + returnObject.m_membersNeededToStart = utils::extract_json_int(managedInitializationJson, _T("membersNeededToStart"), errc); + } + + return returnObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_peer_to_host_requirements.cpp b/Source/Services/Multiplayer/multiplayer_peer_to_host_requirements.cpp new file mode 100644 index 00000000..89a8d5ba --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_peer_to_host_requirements.cpp @@ -0,0 +1,98 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_peer_to_host_requirements::multiplayer_peer_to_host_requirements(): + m_bandwidthDownMinimumInKilobitsPerSecond(0), + m_bandwidthUpMinimumInKilobitsPerSecond(0), + m_hostSelectionMetric(multiplay_metrics::unknown) +{ +} + +multiplayer_peer_to_host_requirements::multiplayer_peer_to_host_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32_t bandwidthUpMinimumInKilobitsPerSecond, + _In_ multiplay_metrics hostSelectionMetric + ) : + m_latencyMaximum(std::move(latencyMaximum)), + m_bandwidthDownMinimumInKilobitsPerSecond(bandwidthDownMinimumInKilobitsPerSecond), + m_bandwidthUpMinimumInKilobitsPerSecond(bandwidthUpMinimumInKilobitsPerSecond), + m_hostSelectionMetric(hostSelectionMetric) +{ +} + +const std::chrono::milliseconds& +multiplayer_peer_to_host_requirements::latency_maximum() const +{ + return m_latencyMaximum; +} + +uint64_t +multiplayer_peer_to_host_requirements::bandwidth_down_minimum_in_kilobits_per_second() const +{ + return m_bandwidthDownMinimumInKilobitsPerSecond; +} + +uint64_t +multiplayer_peer_to_host_requirements::bandwidth_up_minimum_in_kilobits_per_second() const +{ + return m_bandwidthUpMinimumInKilobitsPerSecond; +} + +multiplay_metrics +multiplayer_peer_to_host_requirements::host_selection_metric() const +{ + return m_hostSelectionMetric; +} + +web::json::value +multiplayer_peer_to_host_requirements::_Serialize() +{ + web::json::value serializedObject; + serializedObject[_T("latencyMaximum")] = utils::serialize_uint52_to_json(m_latencyMaximum.count()); + serializedObject[_T("bandwidthDownMinimum")] = web::json::value(m_bandwidthDownMinimumInKilobitsPerSecond); + serializedObject[_T("bandwidthUpMinimum")] = web::json::value(m_bandwidthUpMinimumInKilobitsPerSecond); + + auto hostSelectionMetricResult = multiplayer_session::_Convert_multiplayer_host_selection_metric_to_string(m_hostSelectionMetric); + + if (!hostSelectionMetricResult.err()) + { + serializedObject[_T("hostSelectionMetric")] = web::json::value::string( + hostSelectionMetricResult.payload() + ); + } + + return serializedObject; +} + +xbox_live_result +multiplayer_peer_to_host_requirements::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = multiplayer_peer_to_host_requirements( + std::chrono::milliseconds(utils::extract_json_uint52(json, _T("latencyMaximum"), errc)), + utils::extract_json_int(json, _T("bandwidthDownMinimum"), errc), + utils::extract_json_int(json, _T("bandwidthUpMinimum"), errc), + multiplayer_session::_Convert_string_to_multiplayer_host_selection_metric(utils::extract_json_string(json, _T("hostSelectionMetric"), errc)) + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_peer_to_peer_requirements.cpp b/Source/Services/Multiplayer/multiplayer_peer_to_peer_requirements.cpp new file mode 100644 index 00000000..e17c87b0 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_peer_to_peer_requirements.cpp @@ -0,0 +1,64 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN +multiplayer_peer_to_peer_requirements::multiplayer_peer_to_peer_requirements(): + m_bandwidthMinimumInKilobitsPerSecond(0) +{ +} + +multiplayer_peer_to_peer_requirements::multiplayer_peer_to_peer_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthMinimumInKilobitsPerSecond + ) : + m_latencyMaximum(std::move(latencyMaximum)), + m_bandwidthMinimumInKilobitsPerSecond(bandwidthMinimumInKilobitsPerSecond) +{ +} + +uint64_t +multiplayer_peer_to_peer_requirements::bandwidth_minimum_in_kilobits_per_second() const +{ + return m_bandwidthMinimumInKilobitsPerSecond; +} + +const std::chrono::milliseconds& +multiplayer_peer_to_peer_requirements::latency_maximum() const +{ + return m_latencyMaximum; +} + +web::json::value +multiplayer_peer_to_peer_requirements::_Serialize() +{ + web::json::value serializedObject; + serializedObject[_T("latencyMaximum")] = utils::serialize_uint52_to_json(m_latencyMaximum.count()); + serializedObject[_T("bandwidthMinimum")] = web::json::value(m_bandwidthMinimumInKilobitsPerSecond); + return serializedObject; +} + +xbox_live_result +multiplayer_peer_to_peer_requirements::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto response = multiplayer_peer_to_peer_requirements( + std::chrono::milliseconds(utils::extract_json_uint52(json, _T("latencyMaximum"), errc)), + utils::extract_json_int(json, _T("bandwidthMinimum"), errc) + ); + + return xbox_live_result(response, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_quality_of_service_measurement.cpp b/Source/Services/Multiplayer/multiplayer_quality_of_service_measurement.cpp new file mode 100644 index 00000000..28a64045 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_quality_of_service_measurement.cpp @@ -0,0 +1,95 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_quality_of_service_measurements::multiplayer_quality_of_service_measurements(): + m_bandwidthDownInKilobitsPerSecond(0), + m_bandwidthUpInKilobitsPerSecond(0) +{ +} + +multiplayer_quality_of_service_measurements::multiplayer_quality_of_service_measurements( + _In_ string_t memberDeviceToken, + _In_ std::chrono::milliseconds latency, + _In_ uint64_t bandwidthDownInKilobitsPerSecond, + _In_ uint64_t bandwidthUpInKilobitsPerSecond, + _In_ string_t customJson + ) : + m_memberDeviceToken(std::move(memberDeviceToken)), + m_latency(std::move(latency)), + m_bandwidthDownInKilobitsPerSecond(bandwidthDownInKilobitsPerSecond), + m_bandwidthUpInKilobitsPerSecond(bandwidthUpInKilobitsPerSecond) +{ + std::error_code errc; + m_customJson = web::json::value::parse(std::move(customJson), errc); + assert(!errc); +} + +const string_t& +multiplayer_quality_of_service_measurements::member_device_token() const +{ + return m_memberDeviceToken; +} + +void +multiplayer_quality_of_service_measurements::_Set_member_device_token( + _In_ const string_t& memberDeviceToken + ) +{ + m_memberDeviceToken = memberDeviceToken; +} + +const std::chrono::milliseconds& +multiplayer_quality_of_service_measurements::latency() const +{ + return m_latency; +} + +uint64_t +multiplayer_quality_of_service_measurements::bandwidth_down_in_kilobits_per_second() const +{ + return m_bandwidthDownInKilobitsPerSecond; +} + +uint64_t +multiplayer_quality_of_service_measurements::bandwidth_up_in_kilobits_per_second() const +{ + return m_bandwidthUpInKilobitsPerSecond; +} + +const web::json::value& +multiplayer_quality_of_service_measurements::custom_json() const +{ + return m_customJson; +} + +xbox_live_result +multiplayer_quality_of_service_measurements::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_quality_of_service_measurements returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + returnResult.m_latency = std::chrono::milliseconds(utils::extract_json_uint52(json, _T("latency"), errc)); + returnResult.m_bandwidthDownInKilobitsPerSecond = utils::extract_json_uint52(json, _T("bandwidthDown"), errc); + returnResult.m_bandwidthUpInKilobitsPerSecond = utils::extract_json_uint52(json, _T("bandwidthUp"), errc); + returnResult.m_customJson = utils::extract_json_field(json, _T("custom"), errc, false); + + return returnResult; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_query_search_handle_request.cpp b/Source/Services/Multiplayer/multiplayer_query_search_handle_request.cpp new file mode 100644 index 00000000..cc758ae4 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_query_search_handle_request.cpp @@ -0,0 +1,141 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_query_search_handle_request::multiplayer_query_search_handle_request( + _In_ string_t serviceConfigurationId, + _In_ string_t sessionTemplateName, + _In_ string_t orderBy, + _In_ bool orderAscending, + _In_ string_t searchFilter + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_sessionTemplateName(std::move(sessionTemplateName)), + m_orderBy(std::move(orderBy)), + m_orderAscending(orderAscending), + m_searchFilter(std::move(searchFilter)) +{ +} + +multiplayer_query_search_handle_request::multiplayer_query_search_handle_request( + _In_ string_t serviceConfigurationId, + _In_ string_t sessionTemplateName + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_sessionTemplateName(std::move(sessionTemplateName)), + m_orderAscending(false) +{ +} + +const string_t& +multiplayer_query_search_handle_request::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const string_t& +multiplayer_query_search_handle_request::session_template_name() const +{ + return m_sessionTemplateName; +} + +bool +multiplayer_query_search_handle_request::order_ascending() +{ + return m_orderAscending; +} + +void +multiplayer_query_search_handle_request::set_order_ascending(_In_ bool orderAscending) +{ + m_orderAscending = orderAscending; +} + +const string_t& +multiplayer_query_search_handle_request::order_by() const +{ + return m_orderBy; +} + +void +multiplayer_query_search_handle_request::set_order_by(_In_ const string_t& orderBy) +{ + m_orderBy = orderBy; +} + +const string_t& +multiplayer_query_search_handle_request::search_filter() const +{ + return m_searchFilter; +} + +void +multiplayer_query_search_handle_request::set_search_filter(_In_ const string_t& searchFilter) +{ + m_searchFilter = searchFilter; +} + +const string_t& +multiplayer_query_search_handle_request::social_group() const +{ + return m_socialGroup; +} + +void +multiplayer_query_search_handle_request::set_social_group(_In_ const string_t& socialGroup) +{ + m_socialGroup = socialGroup; +} + +web::json::value +multiplayer_query_search_handle_request::_Serialize( + _In_ const string_t& socialGroupXuid + ) const +{ + web::json::value serializedObject; + serializedObject[_T("type")] = web::json::value::string(_T("search")); + serializedObject[_T("scid")] = web::json::value::string(m_serviceConfigurationId); + serializedObject[_T("templateName")] = web::json::value::string(m_sessionTemplateName); + serializedObject[_T("filter")] = web::json::value::string(m_searchFilter); + serializedObject[_T("global")] = web::json::value::boolean(true); + + if (!m_orderBy.empty()) + { + stringstream_t orderByQuery; + orderByQuery << m_orderBy; + if (m_orderAscending) + { + orderByQuery << _T(" asc"); + } + else + { + orderByQuery << _T(" desc"); + } + serializedObject[_T("orderBy")] = web::json::value::string(orderByQuery.str()); + } + + if (!m_socialGroup.empty()) + { + web::json::value ownerObject; + web::json::value peopleObject; + peopleObject[_T("moniker")] = web::json::value::string(m_socialGroup); + peopleObject[_T("monikerXuid")] = web::json::value::string(socialGroupXuid); + + ownerObject[_T("people")] = std::move(peopleObject); + serializedObject[_T("sessionMembers")] = ownerObject; + } + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_role_info.cpp b/Source/Services/Multiplayer/multiplayer_role_info.cpp new file mode 100644 index 00000000..699d1195 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_role_info.cpp @@ -0,0 +1,84 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_role_info::multiplayer_role_info(): + m_maxMembersCount(0), + m_membersCount(0), + m_targetCount(0) +{ +} + +const std::vector& +multiplayer_role_info::member_xbox_user_ids() const +{ + return m_memberXuids; +} + +uint32_t +multiplayer_role_info::max_members_count() const +{ + return m_maxMembersCount; +} + +uint32_t +multiplayer_role_info::members_count() const +{ + return m_membersCount; +} + +uint32_t +multiplayer_role_info::target_count() const +{ + return m_targetCount; +} + +void +multiplayer_role_info::set_max_members_count( + _In_ uint32_t maxCount + ) +{ + m_maxMembersCount = maxCount; +} + +void +multiplayer_role_info::set_target_count( + _In_ uint32_t targetCount + ) +{ + m_targetCount = targetCount; +} + +xbox_live_result +multiplayer_role_info::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + multiplayer_role_info returnResult; + std::error_code errc = xbox_live_error_code::no_error; + + returnResult.m_membersCount = utils::extract_json_int(json, _T("count"), errc, false); + returnResult.m_maxMembersCount = utils::extract_json_int(json, _T("max"), errc, false); + returnResult.m_targetCount = utils::extract_json_int(json, _T("target"), errc, false); + if (returnResult.m_membersCount > 0) + { + returnResult.m_memberXuids = utils::extract_json_vector(utils::json_string_extractor, json, _T("memberXuids"), errc, true); + } + + return xbox_live_result(returnResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_role_type.cpp b/Source/Services/Multiplayer/multiplayer_role_type.cpp new file mode 100644 index 00000000..f5716b10 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_role_type.cpp @@ -0,0 +1,102 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_role_type::multiplayer_role_type() : + m_ownerManaged(false) +{ +} + +const std::unordered_map& +multiplayer_role_type::roles() const +{ + return m_roles; +} + +void +multiplayer_role_type::set_roles( + _In_ const std::unordered_map& roles + ) +{ + m_roles = roles; +} + +bool +multiplayer_role_type::owner_managed() const +{ + return m_ownerManaged; +} + +const std::vector& +multiplayer_role_type::mutable_role_settings() const +{ + return m_mutableRoleSettings; +} + +std::vector +multiplayer_role_type::_Convert_string_vector_to_mutable_role_settings( + std::vector roleSettings + ) +{ + std::vector mutableRoleSettings; + for (auto& setting : roleSettings) + { + if (utils::str_icmp(setting, _T("max")) == 0) + { + mutableRoleSettings.push_back(mutable_role_setting::max); + } + else if (utils::str_icmp(setting, _T("target")) == 0) + { + mutableRoleSettings.push_back(mutable_role_setting::target); + } + } + + return mutableRoleSettings; +} + +xbox_live_result +multiplayer_role_type::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + multiplayer_role_type returnResult; + std::error_code errc = xbox_live_error_code::no_error; + + returnResult.m_ownerManaged = utils::extract_json_bool(json, _T("ownerManaged"), errc, false); + returnResult.m_mutableRoleSettings = _Convert_string_vector_to_mutable_role_settings( + utils::extract_json_vector(utils::json_string_extractor, json, _T("mutableRoleSettings"), errc, false) + ); + + auto rolesJson = utils::extract_json_field(json, _T("roles"), errc, false); + if (!rolesJson.is_null() && rolesJson.is_object()) + { + web::json::object rolesObj = rolesJson.as_object(); + for (const auto& role : rolesObj) + { + auto roleInfoResult = multiplayer_role_info::_Deserialize(role.second); + if (roleInfoResult.err()) + { + errc = roleInfoResult.err(); + } + returnResult.m_roles[role.first] = roleInfoResult.payload(); + } + } + + return xbox_live_result(returnResult, errc); + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_search_handle_details.cpp b/Source/Services/Multiplayer/multiplayer_search_handle_details.cpp new file mode 100644 index 00000000..94557a91 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_search_handle_details.cpp @@ -0,0 +1,190 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_search_handle_details::multiplayer_search_handle_details() : + m_visibility(multiplayer_session_visibility::unknown), + m_joinRestriction(multiplayer_session_restriction::unknown), + m_closed(false), + m_maxMembersCount(0), + m_membersCount(0) +{ +} + +const multiplayer_session_reference& +multiplayer_search_handle_details::session_reference() const +{ + return m_sessionReference; +} + +const string_t& +multiplayer_search_handle_details::handle_id() const +{ + return m_handleId; +} + +const std::vector& +multiplayer_search_handle_details::session_owner_xbox_user_ids() const +{ + return m_sessionOwners; +} + +const std::unordered_map& +multiplayer_search_handle_details::role_types() const +{ + return m_roleTypes; +} + +const std::vector& +multiplayer_search_handle_details::tags() const +{ + return m_tags; +} + +const std::unordered_map& +multiplayer_search_handle_details::numbers_metadata() const +{ + return m_numbersMetadata; +} + +const std::unordered_map& +multiplayer_search_handle_details::strings_metadata() const +{ + return m_stringsMetadata; +} + +multiplayer_session_visibility +multiplayer_search_handle_details::visibility() const +{ + return m_visibility; +} + +multiplayer_session_restriction +multiplayer_search_handle_details::join_restriction() const +{ + return m_joinRestriction; +} + +bool +multiplayer_search_handle_details::closed() const +{ + return m_closed; +} + +uint32_t +multiplayer_search_handle_details::max_members_count() const +{ + return m_maxMembersCount; +} + +uint32_t +multiplayer_search_handle_details::members_count() const +{ + return m_membersCount; +} + +utility::datetime +multiplayer_search_handle_details::handle_creation_time() const +{ + return m_handleCreationTime; +} + +xbox_live_result +multiplayer_search_handle_details::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_search_handle_details returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + string_t type = utils::extract_json_string(json, _T("type"), errc); + + if (utils::str_icmp(type, _T("search")) != 0) + { + return xbox_live_result(xbox_live_error_code::json_error, "Unexpected content"); + } + + returnResult.m_handleId = utils::extract_json_string(json, _T("id"), errc); + returnResult.m_handleCreationTime = utils::extract_json_time(json, _T("createTime"), errc); + auto sessionReference = multiplayer_session_reference::_Deserialize(utils::extract_json_field(json, _T("sessionRef"), errc, false)); + if (sessionReference.err()) + { + errc = sessionReference.err(); + } + returnResult.m_sessionReference = sessionReference.payload(); + + web::json::value searchAttributesObject = utils::extract_json_field(json, _T("searchAttributes"), errc, false); + if (!searchAttributesObject.is_null()) + { + returnResult.m_tags = utils::extract_json_vector(utils::json_string_extractor, searchAttributesObject, _T("tags"), errc, false); + auto stringsMetadataJson = utils::extract_json_field(searchAttributesObject, _T("strings"), errc, false); + if (!stringsMetadataJson.is_null() && stringsMetadataJson.is_object()) + { + web::json::object stringMetadataObj = stringsMetadataJson.as_object(); + for (const auto& stringsMetadata : stringMetadataObj) + { + returnResult.m_stringsMetadata[stringsMetadata.first] = stringsMetadata.second.as_string(); + } + } + + auto numbersMetadataJson = utils::extract_json_field(searchAttributesObject, _T("numbers"), errc, false); + if (!numbersMetadataJson.is_null() && numbersMetadataJson.is_object()) + { + web::json::object numberMetadataObj = numbersMetadataJson.as_object(); + for (const auto& numbersMetadata : numberMetadataObj) + { + returnResult.m_numbersMetadata[numbersMetadata.first] = numbersMetadata.second.as_double(); + } + } + } + + web::json::value relatedInfoObject = utils::extract_json_field(json, _T("relatedInfo"), errc, false); + if (!relatedInfoObject.is_null()) + { + returnResult.m_membersCount = utils::extract_json_int(relatedInfoObject, _T("membersCount"), errc, true); + returnResult.m_maxMembersCount = utils::extract_json_int(relatedInfoObject, _T("maxMembersCount"), errc, true); + returnResult.m_joinRestriction = multiplayer_session_states::_Convert_string_to_multiplayer_session_restriction( + utils::extract_json_string(relatedInfoObject, _T("joinRestriction"), errc) + ); + returnResult.m_visibility = multiplayer_session_states::_Convert_string_to_session_visibility( + utils::extract_json_string(relatedInfoObject, _T("visibility"), errc) + ); + + returnResult.m_closed = utils::extract_json_bool(relatedInfoObject, _T("closed"), errc); + returnResult.m_sessionOwners = utils::extract_json_vector(utils::json_string_extractor, relatedInfoObject, _T("sessionOwners"), errc, false); + } + + auto roleInfo = utils::extract_json_field(json, _T("roleInfo"), errc, false); + if (!roleInfo.is_null()) + { + auto roleTypes = utils::extract_json_field(roleInfo, _T("roleTypes"), errc, false); + if (!roleTypes.is_null() && roleTypes.is_object()) + { + web::json::object roleTypesObj = roleTypes.as_object(); + for (const auto& roleType : roleTypesObj) + { + auto roleTypeResult = multiplayer_role_type::_Deserialize(roleType.second); + if (roleTypeResult.err()) + { + errc = roleTypeResult.err(); + } + returnResult.m_roleTypes[roleType.first] = roleTypeResult.payload(); + } + } + } + + return returnResult; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END diff --git a/Source/Services/Multiplayer/multiplayer_search_handle_request.cpp b/Source/Services/Multiplayer/multiplayer_search_handle_request.cpp new file mode 100644 index 00000000..7dd8e4c3 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_search_handle_request.cpp @@ -0,0 +1,123 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_search_handle_request::multiplayer_search_handle_request( + _In_ multiplayer_session_reference sessionReference + ) : + m_sessionReference(std::move(sessionReference)) +{ +} + +const multiplayer_session_reference& +multiplayer_search_handle_request::session_reference() const +{ + return m_sessionReference; +} + +const std::vector& +multiplayer_search_handle_request::tags() const +{ + return m_tags; +} + +void +multiplayer_search_handle_request::set_tags( + _In_ const std::vector& value +) +{ + m_tags = std::move(value); +} + +const std::unordered_map& +multiplayer_search_handle_request::numbers_metadata() const +{ + return m_numbersMetadata; +} + +void +multiplayer_search_handle_request::set_numbers_metadata( + _In_ const std::unordered_map& metadata +) +{ + m_numbersMetadata = std::move(metadata); +} + +const std::unordered_map& +multiplayer_search_handle_request::strings_metadata() const +{ + return m_stringsMetadata; +} + +void +multiplayer_search_handle_request::set_strings_metadata( + _In_ const std::unordered_map& metadata +) +{ + m_stringsMetadata = std::move(metadata); +} + +void +multiplayer_search_handle_request::_Set_version(_In_ uint32_t version) +{ + m_version = version; +} + +web::json::value +multiplayer_search_handle_request::_Serialize() const +{ + web::json::value serializedObject; + + serializedObject[_T("type")] = web::json::value::string(_T("search")); + serializedObject[_T("version")] = web::json::value(m_version); + serializedObject[_T("sessionRef")] = m_sessionReference._Serialize(); + + web::json::value searchAttributesJson; + bool setSearchAttributes = false; + if (!m_tags.empty()) + { + setSearchAttributes = true; + searchAttributesJson[_T("tags")] = utils::serialize_vector(utils::json_string_serializer, m_tags); + } + + if (m_numbersMetadata.size() > 0) + { + setSearchAttributes = true; + web::json::value numbersPropertiesJson; + for (const auto& metadata: m_numbersMetadata) + { + numbersPropertiesJson[metadata.first] = web::json::value::number(static_cast(metadata.second)); + } + searchAttributesJson[_T("numbers")] = numbersPropertiesJson; + } + + if (m_stringsMetadata.size() > 0) + { + setSearchAttributes = true; + web::json::value stringsPropertiesJson; + for (const auto& metadata : m_stringsMetadata) + { + stringsPropertiesJson[metadata.first] = web::json::value::string(metadata.second); + } + searchAttributesJson[_T("strings")] = stringsPropertiesJson; + } + + if (setSearchAttributes) + { + serializedObject[_T("searchAttributes")] = searchAttributesJson; + } + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END diff --git a/Source/Services/Multiplayer/multiplayer_service.cpp b/Source/Services/Multiplayer/multiplayer_service.cpp new file mode 100644 index 00000000..817d34d1 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_service.cpp @@ -0,0 +1,1206 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/real_time_activity.h" +#include "xsapi/multiplayer.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" +#include "multiplayer_internal.h" + +using namespace pplx; +using namespace xbox::services::system; +using namespace xbox::services::real_time_activity; +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN +const uint32_t c_multiplayerHandleVersionValue = 1; +const string_t c_getActivitiesSubpath = _T("/handles/query?include=relatedInfo"); +const string_t c_getSearchHandlesSubpath = _T("/handles/query?include=relatedInfo,roleInfo"); +const string_t c_multiplayerServiceContractHeaderValue = _T("107"); + +multiplayer_service::multiplayer_service() +{ +} + +multiplayer_service::multiplayer_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivity + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ + m_multiplayerServiceImpl = std::make_shared(realTimeActivity); +} + +task>> +multiplayer_service::write_session( + _In_ std::shared_ptr session, + _In_ multiplayer_session_write_mode mode + ) +{ + multiplayer_session_reference sessionReference = session->session_reference(); + + string_t pathAndQuery = multiplayer_session_directory_create_or_update_subpath( + sessionReference.service_configuration_id(), + sessionReference.session_template_name(), + sessionReference.session_name() + ); + + return write_session_using_subpath( + session, + mode, + pathAndQuery + ); +} + +task>> +multiplayer_service::write_session_by_handle( + _In_ std::shared_ptr session, + _In_ multiplayer_session_write_mode mode, + _In_ const string_t& handleId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(handleId, std::shared_ptr, "Handle id was empty"); + + string_t pathAndQuery = multiplayer_session_directory_create_or_update_by_handle_subpath(handleId); + return write_session_using_subpath( + session, + mode, + pathAndQuery + ); +} + +task>> +multiplayer_service::write_session_using_subpath( + _In_ std::shared_ptr session, + _In_ multiplayer_session_write_mode mode, + _In_ const string_t& subpathAndQuery + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(subpathAndQuery, std::shared_ptr, "Subpath and query was empty"); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("PUT"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + subpathAndQuery, + xbox_live_api::write_session_using_subpath + ); + + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + + switch (mode) + { + case multiplayer_session_write_mode::create_new: + { + httpCall->set_custom_header(_T("If-None-Match"), _T("*")); + break; + } + case multiplayer_session_write_mode::update_existing: + { + httpCall->set_custom_header(_T("If-Match"), _T("*")); + break; + } + case multiplayer_session_write_mode::update_or_create_new: + { + // No match header + break; + } + case multiplayer_session_write_mode::synchronized_update: + { + if (session->e_tag().empty()) + { + httpCall->set_custom_header(_T("If-None-Match"), _T("*")); + } + else + { + httpCall->set_custom_header(_T("If-Match"), session->e_tag()); + } + break; + } + default: + { + return pplx::task_from_result(xbox_live_result>(xbox_live_error_code::invalid_argument, "multiplayer session write mode is out of range")); + } + } + + task> subscriptionTask; + bool subscriptionsEnabled = m_multiplayerServiceImpl->subscriptions_enabled(); + if (subscriptionsEnabled && session->current_user() != nullptr && session->current_user()->_Member_request() != nullptr) + { + subscriptionTask = m_multiplayerServiceImpl->ensure_multiplayer_subscription() + .then([httpCall, session](xbox_live_result connectionId) + { + if (connectionId.err()) + { + return xbox_live_result(connectionId.err(), connectionId.err_message()); + } + session->current_user()->_Set_rta_connection_id(connectionId.payload()); + return xbox_live_result(session->_Session_request()->serialize().serialize(), connectionId.err(), connectionId.err_message()); + }); + } + else + { + subscriptionTask = task_from_result(xbox_live_result(session->_Session_request()->serialize().serialize())); + } + + auto userContext = m_userContext; + multiplayer_session_reference sessionReference = session->session_reference(); + auto task = subscriptionTask.then([httpCall, userContext](xbox_live_result body) + { + if (body.err()) + { + return task_from_result(xbox_live_result>(body.err(), body.err_message())); + } + + httpCall->set_request_body(body.payload()); + auto httpResponse = httpCall->get_response_with_auth(userContext); + return task_from_result(xbox_live_result>(httpResponse.get())); + }) + .then([sessionReference, httpCall, userContext](xbox_live_result> responseResult) + { + auto& response = responseResult.payload(); + if (responseResult.err()) + { + return xbox_live_result>(responseResult.err(), responseResult.err_message()); + } + + auto& errCode = response->err_code(); + if (errCode && errCode != xbox_live_error_code::http_status_412_precondition_failed) + { + auto errMessage = response->err_message(); + if (errMessage.empty() && response->response_body_json().is_string()) + { + string_t debugString = response->response_body_json().as_string(); + if (!debugString.empty()) + { + errMessage = utility::conversions::to_utf8string(debugString); + } + } + return xbox_live_result>(response->err_code(), errMessage); + } + + auto status = response->http_status(); + + if (status == 204) + { + return xbox_live_result>(nullptr); + } + + xbox_live_result> multiplayerSessionResult = xbox_live_result>(response->err_code(), response->err_message()); + if (response->response_body_json().size() > 0) + { + auto multiplayerSession = multiplayer_session::_Deserialize( + response->response_body_json() + ); + + if (multiplayerSession.err() && !response->err_code()) + { + response->_Set_error(xbox_live_error_code::json_error, "WriteSession failed due to deserialization error"); + } + + xbox_live_result> multiplayerSessionShared( + std::make_shared(multiplayerSession.payload()), + multiplayerSession.err(), + multiplayerSession.err_message() + ); + + multiplayerSessionResult = utils::generate_xbox_live_result>( + multiplayerSessionShared, + response + ); + + auto newSession = std::make_shared(multiplayerSession.payload()); + + multiplayer_session_reference localSessionRef; + if (sessionReference.is_null()) + { + web::http::http_headers header = response->response_headers(); + web::http::http_headers::key_type contentKey(_T("Content-Location")); + + localSessionRef = multiplayer_session_reference::parse_from_uri_path( + header[contentKey] + ); + } + else + { + localSessionRef = std::move(sessionReference); + } + + newSession->_Initialize_after_deserialize( + response->e_tag(), + response->response_date(), + localSessionRef, + userContext->xbox_user_id() + ); + + newSession->_Set_write_session_status( + response->http_status() + ); + + multiplayerSessionResult.set_payload(newSession); + } + + return multiplayerSessionResult; + }); + + return utils::create_exception_free_task>( + task + ); +} + +task>> +multiplayer_service::get_current_session( + _In_ multiplayer_session_reference sessionReference + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(sessionReference.is_null(), std::shared_ptr, "Session reference is null"); + + string_t pathAndQuery = multiplayer_session_directory_create_or_update_subpath( + sessionReference.service_configuration_id(), + sessionReference.session_template_name(), + sessionReference.session_name() + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + pathAndQuery, + xbox_live_api::get_current_session + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + + auto userContextShared = m_userContext; + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([sessionReference, userContextShared](std::shared_ptr response) + { + if (response->http_status() == 204) + { + return xbox_live_result>(xbox_live_error_code::http_status_204_resource_data_not_found, "Content not found on get_current_session"); + } + + auto multiplayerSession = multiplayer_session::_Deserialize( + response->response_body_json() + ); + + auto multiplayerSessionResult = utils::generate_xbox_live_result( + multiplayerSession, + response + ); + + xbox_live_result> multiplayerSessionSharedResult( + std::make_shared(multiplayerSessionResult.payload()), + multiplayerSessionResult.err(), + multiplayerSessionResult.err_message() + ); + + multiplayerSessionSharedResult.payload()->_Initialize_after_deserialize( + response->e_tag(), + response->response_date(), + sessionReference, + userContextShared->xbox_user_id() + ); + + return multiplayerSessionSharedResult; + }); + + return utils::create_exception_free_task>( + task + ); +} + +task>> +multiplayer_service::get_current_session_by_handle( + _In_ const string_t& handleId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(handleId, std::shared_ptr, "Handle id was empty"); + string_t pathAndQuery = multiplayer_session_directory_create_or_update_by_handle_subpath( + handleId + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + pathAndQuery, + xbox_live_api::get_current_session_by_handle + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + auto userContextShared = m_userContext; + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([userContextShared](std::shared_ptr response) + { + if (response->http_status() == 204) + { + return xbox_live_result>(xbox_live_error_code::http_status_204_resource_data_not_found, "Content not found on get_current_session"); + } + + auto multiplayerSession = multiplayer_session::_Deserialize( + response->response_body_json() + ); + + auto multiplayerSessionResult = utils::generate_xbox_live_result( + multiplayerSession, + response + ); + + xbox_live_result> multiplayerSessionShared( // TOOD: Implement a way to quit creating a new result object... + std::make_shared(multiplayerSessionResult.payload()), + multiplayerSessionResult.err(), + multiplayerSessionResult.err_message() + ); + + web::http::http_headers header = response->response_headers(); + web::http::http_headers::key_type contentKey(_T("Content-Location")); + + multiplayer_session_reference sessionReference = multiplayer_session_reference::parse_from_uri_path( + header[contentKey] + ); + + if (sessionReference.is_null()) return xbox_live_result>(response->err_code(), response->err_message()); + + multiplayerSessionShared.payload()->_Initialize_after_deserialize( + response->e_tag(), + response->response_date(), + sessionReference, + userContextShared->xbox_user_id() + ); + + return multiplayerSessionShared; + }); + + return utils::create_exception_free_task>( + task + ); +} + +task>> +multiplayer_service::get_sessions( + _In_ multiplayer_get_sessions_request getSessionsRequest + ) +{ + auto filter = getSessionsRequest.visibility_filter(); + + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(getSessionsRequest.service_configuration_id(), std::vector, "serviceConfigurationId was empty in request"); + + RETURN_TASK_CPP_INVALIDARGUMENT_IF(!getSessionsRequest.xbox_user_ids_filter().empty() && !getSessionsRequest.xbox_user_id_filter().empty(), std::vector, "xboxUserIdsFilter and xboxUserIdFilter cannot both be set for request") + + RETURN_TASK_CPP_INVALIDARGUMENT_IF(getSessionsRequest.xbox_user_id_filter().empty() && getSessionsRequest.keyword_filter().empty() && getSessionsRequest.xbox_user_ids_filter().empty(), std::vector, "Must have xboxUserIdFilter, xboxUserIdsFilter, or keywordFilter set for request"); + + RETURN_TASK_CPP_INVALIDARGUMENT_IF(getSessionsRequest.include_reservations() && getSessionsRequest.xbox_user_id_filter().empty() && getSessionsRequest.xbox_user_ids_filter().empty(), std::vector, "Cannot include reservations in request without xboxUserIdFilter or xboxUserIdsFilter"); + + RETURN_TASK_CPP_INVALIDARGUMENT_IF(getSessionsRequest.include_inactive_sessions() && getSessionsRequest.xbox_user_id_filter().empty() && getSessionsRequest.xbox_user_ids_filter().empty(), std::vector, "Cannot include inactive sessions in request without xboxUserIdFilter or xboxUserIdsFilter"); + + auto visibilityFilterToString = multiplayer_session_states::_Convert_multiplayer_session_visibility_to_string(filter); + RETURN_TASK_CPP_IF_ERR(visibilityFilterToString, std::vector); + + auto xboxUserIdFilters = getSessionsRequest.xbox_user_ids_filter(); + bool hasXboxUserIdsFilter = !xboxUserIdFilters.empty(); + + string_t pathAndQuery = multiplayer_session_directory_get_sessions_sub_path( + getSessionsRequest.service_configuration_id(), + getSessionsRequest.session_template_name_filter(), + getSessionsRequest.xbox_user_id_filter(), + getSessionsRequest.keyword_filter(), + visibilityFilterToString.payload(), + getSessionsRequest.contract_version_filter(), + getSessionsRequest.include_private_sessions(), + getSessionsRequest.include_reservations(), + getSessionsRequest.include_inactive_sessions(), + hasXboxUserIdsFilter, + getSessionsRequest.max_items() + ); + + string_t requestType; + if (hasXboxUserIdsFilter) + { + requestType = _T("POST"); + } + else + { + requestType = _T("GET"); + } + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + requestType, + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + pathAndQuery, + xbox_live_api::get_sessions + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + if (hasXboxUserIdsFilter) + { + web::json::value xuidsJson; + xuidsJson[_T("xuids")] = utils::serialize_vector(utils::json_string_serializer, xboxUserIdFilters); + httpCall->set_request_body( + xuidsJson.serialize() + ); + } + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto sessionStates = utils::extract_xbox_live_result_json_vector( + multiplayer_session_states::_Deserialize, + response->response_body_json(), + _T("results"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + sessionStates, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +task> +multiplayer_service::set_activity( + _In_ multiplayer_session_reference sessionReference + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(sessionReference.is_null(), void, "Session reference was not initialized properly"); + + multiplayer_activity_handle_post_request request( + std::move(sessionReference), + c_multiplayerHandleVersionValue + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + _T("/handles"), + xbox_live_api::set_activity + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body( + request.serialize().serialize() + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +task> +multiplayer_service::clear_activity( + _In_ const string_t& serviceConfigurationId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, void, "Service configuration id is empty"); + + std::vector xuidVector; + xuidVector.push_back(m_userContext->xbox_user_id()); + + auto sharedXboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + auto sharedUserContext = m_userContext; + + auto getActivityTask = get_activities_for_users(serviceConfigurationId, xuidVector); + auto taskResult = getActivityTask.then([sharedXboxLiveContextSettings, appConfig, sharedUserContext](task>> t) + { + auto response = t.get(); + if (response.err()) return xbox_live_result(response.err(), response.err_message()); + + auto activityDetails = response.payload(); + string_t handleId; + size_t responseSize = activityDetails.size(); + if (responseSize == 0) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "There should be at least one activity per user"); + } + else if (responseSize == 1) + { + handleId = activityDetails.at(0).handle_id(); + } + else + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "There should only be one activity per user"); + } + + return xbox_live_result(handleId); + }).then([sharedXboxLiveContextSettings, appConfig, sharedUserContext](xbox_live_result handleResult) + { + RETURN_TASK_CPP_IF_ERR(handleResult, void); + auto handleId = handleResult.payload(); + stringstream_t handleStream; + handleStream << "/handles/"; + handleStream << handleId; + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + sharedXboxLiveContextSettings, + _T("DELETE"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), appConfig), + handleStream.str(), + xbox_live_api::clear_activity + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + return httpCall->get_response_with_auth(sharedUserContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + }); + + return utils::create_exception_free_task( + taskResult + ); +} + +task> +multiplayer_service::set_transfer_handle( + _In_ multiplayer_session_reference targetSessionReference, + _In_ multiplayer_session_reference originSessionReference + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(targetSessionReference.is_null(), string_t, "Session reference was not initialized properly"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(originSessionReference.is_null(), string_t, "Session reference was not initialized properly"); + + multiplayer_transfer_handle_post_request request( + std::move(targetSessionReference), + std::move(originSessionReference), + c_multiplayerHandleVersionValue + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + _T("/handles"), + xbox_live_api::set_transfer_handle + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body( + request.serialize().serialize() + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto multiplayerInvite = multiplayer_invite::deserialize( + response->response_body_json() + ); + + auto invite = utils::generate_xbox_live_result( + multiplayerInvite, + response + ); + + if (invite.err()) + { + return xbox_live_result(response->err_code(), response->err_message()); + } + + string_t handleId = invite.payload().handle_id(); + return xbox_live_result(handleId); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +multiplayer_service::set_search_handle( + _In_ multiplayer_search_handle_request searchHandleRequest + ) +{ + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + _T("/handles"), + xbox_live_api::set_search_handle + ); + + searchHandleRequest._Set_version(c_multiplayerHandleVersionValue); + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body( + searchHandleRequest._Serialize().serialize() + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task(task); +} + +pplx::task> +multiplayer_service::clear_search_handle( + _In_ const string_t& handleId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(handleId, void, "HandleId is empty"); + + string_t handleStr = _T("/handles/") + handleId; + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("DELETE"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + handleStr, + xbox_live_api::clear_search_handle + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task(task); +} + +task>> +multiplayer_service::send_invites( + _In_ multiplayer_session_reference sessionReference, + _In_ const std::vector& xboxUserIds, + _In_ uint32_t titleId + ) +{ + return send_invites( + std::move(sessionReference), + xboxUserIds, + titleId, + _T(""), + _T("") + ); +} + +task>> +multiplayer_service::send_invites( + _In_ multiplayer_session_reference sessionReference, + _In_ const std::vector& xboxUserIds, + _In_ uint32_t titleId, + _In_ const string_t& contextStringId, + _In_ const string_t& customActivationContext + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(sessionReference.is_null(), std::vector, "sessionReference was not explicity constructed"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(xboxUserIds, std::vector, "xboxUserIds are empty"); + + auto sharedXboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + auto sharedUserContext = m_userContext; + + auto task = create_task([sessionReference, xboxUserIds, titleId, contextStringId, customActivationContext, sharedXboxLiveContextSettings, appConfig, sharedUserContext]() + { + xbox_live_result> inviteHandles; + for (const auto& xuid : xboxUserIds) + { + multiplayer_invite_handle_post_request request( + std::move(sessionReference), + c_multiplayerHandleVersionValue, + xuid, + titleId, + contextStringId, + customActivationContext + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + sharedXboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), appConfig), + _T("/handles"), + xbox_live_api::send_invites + ); + + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body( + request.serialize().serialize() + ); + + auto& inviteHandlePayload = inviteHandles.payload(); + httpCall->get_response_with_auth(sharedUserContext) + .then([&inviteHandles, &inviteHandlePayload](std::shared_ptr response) + { + auto multiplayerInvite = multiplayer_invite::deserialize( + response->response_body_json() + ); + + auto invite = utils::generate_xbox_live_result( + multiplayerInvite, + response + ); + + if (invite.err()) + { + inviteHandles._Set_err(response->err_code()); + inviteHandles._Set_err_message(response->err_message()); + return; + } + string_t handleId = invite.payload().handle_id(); + inviteHandlePayload.push_back(std::move(handleId)); + }).wait(); + } + + return inviteHandles; + }); + + return utils::create_exception_free_task>( + task + ); +} + +task>> +multiplayer_service::get_activities_for_social_group( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& socialGroupOwnerXboxUserId, + _In_ const string_t& socialGroup + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, std::vector, "serviceConfigurationId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(socialGroupOwnerXboxUserId, std::vector, "socialGroupOwnerXboxUserId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(socialGroup, std::vector, "socialGroup is empty"); + + multiplayer_activity_query_post_request request( + serviceConfigurationId, + socialGroup, + socialGroupOwnerXboxUserId + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + c_getActivitiesSubpath, + xbox_live_api::get_activities_for_social_group + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body( + request.serialize().serialize() + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto activityDetails = utils::extract_xbox_live_result_json_vector( + multiplayer_activity_details::_Deserialize, + response->response_body_json(), + _T("results"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + activityDetails, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +task>> +multiplayer_service::get_activities_for_users( + _In_ const string_t& serviceConfigurationId, + _In_ const std::vector& xboxUserIds + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, std::vector, "serviceConfigurationId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserIds.empty(), std::vector, "xboxUserIds are empty"); + + multiplayer_activity_query_post_request request( + std::move(serviceConfigurationId), + std::move(xboxUserIds) + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + c_getActivitiesSubpath, + xbox_live_api::get_activities_for_users + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body( + request.serialize().serialize() + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto activityDetails = utils::extract_xbox_live_result_json_vector( + multiplayer_activity_details::_Deserialize, + response->response_body_json(), + _T("results"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + activityDetails, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task>> +multiplayer_service::get_search_handles( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& orderBy, + _In_ bool orderAscending, + _In_ const string_t& searchFilter + ) +{ + multiplayer_query_search_handle_request searchHandleRequest( + serviceConfigurationId, + sessionTemplateName, + orderBy, + orderAscending, + searchFilter); + + return get_search_handles(searchHandleRequest); +} + +pplx::task>> +multiplayer_service::get_search_handles( + _In_ const multiplayer_query_search_handle_request& searchHandleRequest + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(searchHandleRequest.service_configuration_id(), std::vector, "serviceConfigurationId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(searchHandleRequest.session_template_name(), std::vector, "sessionTemplateName is empty"); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("sessiondirectory"), m_appConfig), + c_getSearchHandlesSubpath, + xbox_live_api::get_search_handles + ); + + httpCall->set_xbox_contract_version_header_value(c_multiplayerServiceContractHeaderValue); + httpCall->set_request_body(searchHandleRequest._Serialize(m_userContext->xbox_user_id())); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto searchHandleDetails = utils::extract_xbox_live_result_json_vector( + multiplayer_search_handle_details::_Deserialize, + response->response_body_json(), + _T("results"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + searchHandleDetails, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +string_t +multiplayer_service::multiplayer_session_directory_create_or_update_subpath( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateName, + _In_ const string_t& sessionName + ) +{ + stringstream_t source; + source << _T("/serviceconfigs/"); + source << serviceConfigurationId; + source << _T("/sessionTemplates/"); + source << sessionTemplateName; + source << _T("/sessions/"); + source << sessionName; + return source.str(); +} + +string_t +multiplayer_service::multiplayer_session_directory_create_or_update_by_handle_subpath( + _In_ const string_t& handleId + ) +{ + stringstream_t source; + source << _T("/handles/"); + source << handleId; + source << _T("/session"); + + return source.str(); +} + +string_t +multiplayer_service::multiplayer_session_directory_get_sessions_sub_path( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& sessionTemplateNameFilter, + _In_ const string_t& xboxUserIdFilter, + _In_ const string_t& keywordFilter, + _In_ const string_t& visibilityFilter, + _In_ uint32_t contextVersionFilter, + _In_ bool includePrivateSessions, + _In_ bool includeReservations, + _In_ bool includeInactiveSessions, + _In_ bool isBatch, + _In_ uint32_t maxItems + ) +{ + stringstream_t source; + + source << _T("/serviceconfigs/"); + source << serviceConfigurationId; + if (!sessionTemplateNameFilter.empty()) + { + source << _T("/sessiontemplates/"); + source << sessionTemplateNameFilter; + } + + if (isBatch) + { + source << _T("/batch"); + } + else + { + source << _T("/sessions"); + } + + std::vector params; + if (!xboxUserIdFilter.empty()) + { + stringstream_t param; + param << _T("xuid="); + param << web::uri::encode_uri(xboxUserIdFilter); + params.push_back(param.str()); + } + + if (!keywordFilter.empty()) + { + stringstream_t param; + param << _T("keyword="); + param << web::uri::encode_uri(keywordFilter); + params.push_back(param.str()); + } + + if (!visibilityFilter.empty() && + utils::str_icmp(visibilityFilter, _T("any")) != 0) + { + stringstream_t param; + param << _T("visibility="); + param << web::uri::encode_uri(visibilityFilter); + params.push_back(param.str()); + } + + if (contextVersionFilter != 0) + { + stringstream_t param; + param << _T("version="); + param << contextVersionFilter; + params.push_back(param.str()); + } + + if (includePrivateSessions) + { + params.push_back(_T("private=true")); + } + + if (includeReservations) + { + params.push_back(_T("reservations=true")); + } + + if (includeInactiveSessions) + { + params.push_back(_T("inactive=true")); + } + + if (maxItems != 0) + { + stringstream_t param; + param << _T("take="); + param << maxItems; + params.push_back(param.str()); + } + + source << utils::get_query_from_params(params); + + return source.str(); +} + +std::error_code +multiplayer_service::enable_multiplayer_subscriptions() +{ + return m_multiplayerServiceImpl->enable_multiplayer_subscriptions(); +} + +bool +multiplayer_service::subscriptions_enabled() +{ + return m_multiplayerServiceImpl->subscriptions_enabled(); +} + +void +multiplayer_service::disable_multiplayer_subscriptions() +{ + return m_multiplayerServiceImpl->disable_multiplayer_subscriptions(); +} + +function_context +multiplayer_service::add_multiplayer_session_changed_handler( + _In_ std::function handler + ) +{ + return m_multiplayerServiceImpl->add_multiplayer_session_changed_handler( + std::move(handler) + ); +} + +void +multiplayer_service::remove_multiplayer_session_changed_handler( + _In_ function_context context + ) +{ + return m_multiplayerServiceImpl->remove_multiplayer_session_changed_handler( + context + ); +} + +function_context +multiplayer_service::add_multiplayer_subscription_lost_handler( + _In_ std::function handler + ) +{ + return m_multiplayerServiceImpl->add_multiplayer_subscription_lost_handler( + std::move(handler) + ); +} + +void +multiplayer_service::remove_multiplayer_subscription_lost_handler( + _In_ function_context context + ) +{ + m_multiplayerServiceImpl->remove_multiplayer_subscription_lost_handler( + context + ); +} + +tournament_game_result_state +multiplayer_service::_Convert_string_to_game_result_state(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("win")) == 0) + { + return tournament_game_result_state::win; + } + else if (utils::str_icmp(value, _T("loss")) == 0) + { + return tournament_game_result_state::loss; + } + else if (utils::str_icmp(value, _T("draw")) == 0) + { + return tournament_game_result_state::draw; + } + else if (utils::str_icmp(value, _T("rank")) == 0) + { + return tournament_game_result_state::rank; + } + else if (utils::str_icmp(value, _T("noShow")) == 0) + { + return tournament_game_result_state::no_show; + } + + return tournament_game_result_state::no_contest; +} + +string_t +multiplayer_service::_Convert_game_result_state_to_string(_In_ tournament_game_result_state value) +{ + switch (value) + { + case tournament_game_result_state::win: + return _T("win"); + break; + case tournament_game_result_state::loss: + return _T("loss"); + break; + case tournament_game_result_state::draw: + return _T("draw"); + break; + case tournament_game_result_state::no_show: + return _T("noShow"); + break; + case tournament_game_result_state::rank: + return _T("rank"); + break; + case tournament_game_result_state::no_contest: + default: + return _T("noContest"); + break; + } +} + +tournament_game_result_source +multiplayer_service::_Convert_string_to_game_result_source(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("adjusted")) == 0) + { + return tournament_game_result_source::adjusted; + } + else if (utils::str_icmp(value, _T("arbitration")) == 0) + { + return tournament_game_result_source::arbitration; + } + else if (utils::str_icmp(value, _T("server")) == 0) + { + return tournament_game_result_source::server; + } + + return tournament_game_result_source::none; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_service_impl.cpp b/Source/Services/Multiplayer/multiplayer_service_impl.cpp new file mode 100644 index 00000000..63c7ec98 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_service_impl.cpp @@ -0,0 +1,269 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xbox_system_factory.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +using namespace xbox::services::multiplayer; +using namespace xbox::services::system; +using namespace xbox::services; +using namespace pplx; + +multiplayer_service_impl::multiplayer_service_impl( + _In_ std::shared_ptr rtaService + ) : + m_realTimeActivityService(rtaService), + m_subscriptionEnabled(false), + m_multiplayerSubscriptionLostEventHandlerCounter(0), + m_sessionChangeEventHandlerCounter(0) +{ +} + +multiplayer_service_impl::~multiplayer_service_impl() +{ + disable_multiplayer_subscriptions(); + m_sessionChangeEventHandler.clear(); +} + +task> +multiplayer_service_impl::ensure_multiplayer_subscription() +{ + std::lock_guard lock(m_subscriptionLock.get()); + + RETURN_TASK_CPP_INVALIDARGUMENT_IF(m_realTimeActivityService == nullptr, string_t, "real_time_activity_service not initialized"); + + if (m_subscription == nullptr) + { + std::weak_ptr thisWeakPtr = shared_from_this(); + m_subscription = xbox_system_factory::get_factory()->create_multiplayer_subscription( + ([thisWeakPtr](const multiplayer_session_change_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->multiplayer_session_changed(eventArgs); + } + }), + ([thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->multiplayer_subscription_lost(); + } + }), + ([thisWeakPtr](const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->m_realTimeActivityService->_Trigger_subscription_error(eventArgs); + } + }) + ); + + auto subscriptionResult = m_realTimeActivityService->_Add_subscription( + m_subscription + ); + + if (subscriptionResult.err()) + { + m_subscription = nullptr; + return pplx::task_from_result(xbox_live_result(xbox_live_error_code::runtime_error, "Failed to create multiplayer subscription, please make sure real_time_activity_service::activate() is called and connection is connected")); + } + } + + return create_task(m_subscription->task); +} + +void +multiplayer_service_impl::multiplayer_session_changed( + _In_ const multiplayer_session_change_event_args& eventArgs + ) +{ + std::unordered_map> sessionChangeCopy; + { + std::lock_guard lock(m_subscriptionLock.get()); + sessionChangeCopy = m_sessionChangeEventHandler; + } + + for(auto& handler : sessionChangeCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + LOG_ERROR_IF(handler.second == nullptr, "multiplayer_session_changed handle is null"); + if (handler.second != nullptr) + { + try + { + handler.second(eventArgs); + } + catch (...) + { + LOG_ERROR("multiplayer_session_changed call threw an exception"); + } + } + } +} + +void +multiplayer_service_impl::multiplayer_subscription_lost() +{ + { + std::lock_guard lock(m_subscriptionEnabledLock.get()); + m_subscriptionEnabled = false; + } + + std::unordered_map> multiplayerSubscriptionLostCopy; + { + std::lock_guard lock(m_subscriptionLock.get()); + + if (m_subscription) + { + auto subscription = m_subscription; + auto rta = m_realTimeActivityService; + pplx::create_task( + [subscription, rta]() + { + rta->_Remove_subscription(subscription); + } + ); + m_subscription = nullptr; + } + + multiplayerSubscriptionLostCopy = m_multiplayerSubscriptionLostEventHandler; + } + + for(auto& handler : multiplayerSubscriptionLostCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(); + } + catch (...) + { + LOG_ERROR("multiplayer_session_changed call threw an exception"); + } + } + } +} + +std::error_code +multiplayer_service_impl::enable_multiplayer_subscriptions() +{ + std::lock_guard lock(m_subscriptionEnabledLock.get()); + if (m_realTimeActivityService == nullptr || m_subscriptionEnabled) + { + return xbox_live_error_code::logic_error; + } + + m_subscriptionEnabled = true; + + return xbox_live_error_code::no_error; +} + +bool +multiplayer_service_impl::subscriptions_enabled() +{ + std::lock_guard lock(m_subscriptionEnabledLock.get()); + return m_subscriptionEnabled; +} + +void +multiplayer_service_impl::disable_multiplayer_subscriptions() +{ + if (m_realTimeActivityService == nullptr) return; + + { + std::lock_guard lock(m_subscriptionEnabledLock.get()); + m_subscriptionEnabled = false; + } + + std::shared_ptr subscription; + { + std::lock_guard lock(m_subscriptionLock.get()); + subscription = m_subscription; + } + + if (subscription) + { + m_realTimeActivityService->_Remove_subscription( + subscription + ); + + { + std::lock_guard lock(m_subscriptionLock.get()); + m_subscription = nullptr; + } + } + else + { + multiplayer_subscription_lost(); + } +} + +function_context +multiplayer_service_impl::add_multiplayer_session_changed_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + + function_context context = -1; + if (m_realTimeActivityService != nullptr && handler != nullptr) + { + context = ++m_sessionChangeEventHandlerCounter; + m_sessionChangeEventHandler[m_sessionChangeEventHandlerCounter] = std::move(handler); + } + + return context; +} + +void +multiplayer_service_impl::remove_multiplayer_session_changed_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + if (m_realTimeActivityService == nullptr) return; + + m_sessionChangeEventHandler.erase(context); +} + +function_context +multiplayer_service_impl::add_multiplayer_subscription_lost_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + + function_context context = -1; + if (m_realTimeActivityService != nullptr && handler != nullptr) + { + context = ++m_multiplayerSubscriptionLostEventHandlerCounter; + m_multiplayerSubscriptionLostEventHandler[m_multiplayerSubscriptionLostEventHandlerCounter] = std::move(handler); + } + + return context; +} + +void +multiplayer_service_impl::remove_multiplayer_subscription_lost_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_subscriptionLock.get()); + if (m_realTimeActivityService == nullptr) return; + + m_multiplayerSubscriptionLostEventHandler.erase(context); +} \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session.cpp b/Source/Services/Multiplayer/multiplayer_session.cpp new file mode 100644 index 00000000..32f6e4b3 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session.cpp @@ -0,0 +1,1638 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" + +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" +#include "multiplayer_internal.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session::multiplayer_session() : + m_membersAccepted(0), + m_joiningSession(false), + m_newSession(false), + m_initializationStage(multiplayer_initialization_stage::unknown), + m_initializationEpisode(0), + m_hasMatchmakingServer(false), + m_changeNumber(0) +{ + m_servers = web::json::value::object(); + m_sessionConstants = std::make_shared(); + m_sessionRequest = std::make_shared(); + m_multiplayerSessionProperties = std::make_shared(); + m_sessionRoleTypes = std::make_shared(); +} + + +multiplayer_session::multiplayer_session( + _In_ string_t xboxUserId + ) : + m_xboxUserId(std::move(xboxUserId)), + m_membersAccepted(0), + m_joiningSession(false), + m_newSession(true), + m_initializationStage(multiplayer_initialization_stage::unknown), + m_initializationEpisode(0), + m_hasMatchmakingServer(false), + m_changeNumber(0) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + _Initialize(m_xboxUserId); +} + +multiplayer_session::multiplayer_session( + _In_ string_t xboxUserId, + _In_ multiplayer_session_reference sessionReference + ) : + m_xboxUserId(std::move(xboxUserId)), + m_sessionReference(std::move(sessionReference)), + m_newSession(true), + m_membersAccepted(0), + m_joiningSession(false), + m_initializationStage(multiplayer_initialization_stage::unknown), + m_initializationEpisode(0), + m_hasMatchmakingServer(false), + m_changeNumber(0) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + + _Initialize(m_xboxUserId); + m_sessionRequest->set_session_reference(m_sessionReference); +} + + +multiplayer_session::multiplayer_session( + _In_ string_t xboxUserId, + _In_ multiplayer_session_reference sessionReference, + _In_ std::vector initiatorXboxUserIds + ) : + m_xboxUserId(std::move(xboxUserId)), + m_sessionReference(std::move(sessionReference)), + m_newSession(true), + m_membersAccepted(0), + m_joiningSession(false), + m_initializationStage(multiplayer_initialization_stage::unknown), + m_initializationEpisode(0), + m_hasMatchmakingServer(false), + m_changeNumber(0) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + + _Initialize(m_xboxUserId); + + m_sessionConstants = std::make_shared(initiatorXboxUserIds); + m_sessionRequest->set_session_constants(m_sessionConstants); + m_sessionRequest->set_session_reference(m_sessionReference); +} + +multiplayer_session::multiplayer_session( + _In_ string_t xboxUserId, + _In_ multiplayer_session_reference sessionReference, + _In_ uint32_t maxMembersInSession, + _In_ multiplayer_session_visibility multiplayerSessionVisibility, + _In_ std::vector initiatorXboxUserIds, + _In_ web::json::value sessionCustomConstantsJson + ) : + m_xboxUserId(std::move(xboxUserId)), + m_sessionReference(std::move(sessionReference)), + m_newSession(true), + m_membersAccepted(0), + m_joiningSession(false), + m_initializationStage(multiplayer_initialization_stage::unknown), + m_initializationEpisode(0), + m_hasMatchmakingServer(false), + m_changeNumber(0) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + + XSAPI_ASSERT( + multiplayerSessionVisibility >= multiplayer_session_visibility::any && + multiplayerSessionVisibility <= multiplayer_session_visibility::open + ); + + _Initialize(m_xboxUserId); + + web::json::value sessionCustomConstants; + if (!sessionCustomConstantsJson.is_null()) + { + sessionCustomConstants = std::move(sessionCustomConstantsJson); + } + m_sessionConstants = std::make_shared( + maxMembersInSession, + multiplayerSessionVisibility, + initiatorXboxUserIds, + sessionCustomConstants + ); + + m_sessionRequest->set_session_constants(m_sessionConstants); + m_sessionRequest->set_session_reference(m_sessionReference); +} + + +std::shared_ptr multiplayer_session::_Create_deep_copy() +{ + auto copy = std::make_shared(); + copy->deep_copy_from(*this); + return copy; +} + +void multiplayer_session::deep_copy_from( + _In_ const multiplayer_session& other + ) +{ + m_xboxUserId = other.m_xboxUserId; + m_sessionReference = other.m_sessionReference; + m_sessionConstants = other.m_sessionConstants; + m_sessionRoleTypes = other.m_sessionRoleTypes; + m_servers = other.m_servers; + m_membersAccepted = other.m_membersAccepted; + m_correlationId = other.m_correlationId; + m_searchHandleId = other.m_searchHandleId; + m_eTag = other.m_eTag; + m_joiningSession = other.m_joiningSession; + m_newSession = other.m_newSession; + m_startTime = other.m_startTime; + m_dateOfSession = other.m_dateOfSession; + m_matchmakingServer = other.m_matchmakingServer; + m_hasMatchmakingServer = other.m_hasMatchmakingServer; + m_sessionSubscriptionGuid = other.m_sessionSubscriptionGuid; + m_branch = other.m_branch; + m_changeNumber = other.m_changeNumber; + m_writeSessionStatus = other.m_writeSessionStatus; + m_nextTimer = other.m_nextTimer; + m_initializationStage = other.m_initializationStage; + m_initializationStageStartTime = other.m_initializationStageStartTime; + m_initializationEpisode = other.m_initializationEpisode; + m_hostCandidate = other.m_hostCandidate; + m_tournamentsServer = other.m_tournamentsServer; + m_arbitrationServer = other.m_arbitrationServer; + + m_memberCurrentUser = other.m_memberCurrentUser == nullptr ? nullptr : other.m_memberCurrentUser->_Create_deep_copy(); + m_sessionRequest = other.m_sessionRequest == nullptr ? nullptr : other.m_sessionRequest->create_deep_copy(); + m_members = std::vector>(); + + bool lookForMe = true; + for (const auto& member : other.m_members) + { + std::shared_ptr memberCopy = std::make_shared(); + memberCopy = member->_Create_deep_copy(); + memberCopy->_Set_session_request(m_sessionRequest); + if (lookForMe) + { + bool isMe = + utils::str_icmp(memberCopy->xbox_user_id(), m_xboxUserId) == 0; + if (isMe) + { + lookForMe = false; + std::shared_ptr memberRequest = m_sessionRequest->add_member_request( + false, + isMe, + m_xboxUserId, + web::json::value(), + false, + false + ); + + memberCopy->_Set_member_request(memberRequest); + memberCopy->_Set_is_current_user(true); + memberCopy->_Set_current_user_status(member->status()); + m_memberCurrentUser = memberCopy; + } + } + m_members.push_back(memberCopy); + } + + m_multiplayerSessionProperties->_Deep_copy(*(other.m_multiplayerSessionProperties)); + m_multiplayerSessionProperties->_Initialize( + m_sessionRequest, + m_members + ); +} + +void multiplayer_session::_Initialize( + _In_ string_t xboxUserId + ) +{ + m_xboxUserId = std::move(xboxUserId); + m_servers = web::json::value::object(); + m_sessionConstants = std::make_shared(); + m_multiplayerSessionProperties = std::make_shared(); + m_sessionRoleTypes = std::make_shared(); + m_sessionRequest = std::make_shared(m_sessionConstants); + + m_multiplayerSessionProperties->_Initialize( + m_sessionRequest, + m_members + ); + + ensure_session_subscription_id_initialized(); +} + +void +multiplayer_session::_Initialize_after_deserialize( + _In_ string_t eTag, + _In_ string_t responseDate, + _In_ multiplayer_session_reference sessionReference, + _In_ string_t xboxUserId + ) +{ + m_eTag = std::move(eTag); + m_dateOfSession = utility::datetime::from_string(responseDate, utility::datetime::date_format::RFC_1123); + m_sessionReference = std::move(sessionReference); + m_xboxUserId = std::move(xboxUserId); + m_sessionRequest->set_session_reference(m_sessionReference); + + ensure_session_subscription_id_initialized(); + if (!m_members.empty()) + { + bool lookForMe = true; + for (auto& member : m_members) + { + member->_Set_session_request(m_sessionRequest); + if (lookForMe) + { + bool isMe = + utils::str_icmp(member->xbox_user_id(), m_xboxUserId) == 0; + if (isMe) + { + lookForMe = false; + std::shared_ptr memberRequest = m_sessionRequest->add_member_request( + false, + isMe, + m_xboxUserId, + web::json::value(), + false, + false + ); + + member->_Set_member_request(memberRequest); + member->_Set_is_current_user( true ); + m_memberCurrentUser = member; + } + } + } + } +} + +std::shared_ptr +multiplayer_session::_Session_request() const +{ + return m_sessionRequest; +} + +const string_t& +multiplayer_session::multiplayer_correlation_id() const +{ + return m_correlationId; +} + +const string_t& +multiplayer_session::search_handle_id() const +{ + return m_searchHandleId; +} + +utility::datetime +multiplayer_session::start_time() const +{ + return m_startTime; +} + +utility::datetime +multiplayer_session::date_of_next_timer() const +{ + return m_nextTimer; +} + +utility::datetime +multiplayer_session::date_of_session() const +{ + return m_dateOfSession; +} + +multiplayer_initialization_stage +multiplayer_session::initialization_stage() const +{ + return m_initializationStage; +} + +utility::datetime +multiplayer_session::initializing_stage_start_time() const +{ + return m_initializationStageStartTime; +} + +uint32_t +multiplayer_session::intializing_episode() const +{ + return m_initializationEpisode; +} + +multiplayer_session_change_types +multiplayer_session::subscribed_change_types() const +{ + if (m_memberCurrentUser == nullptr) + { + return multiplayer_session_change_types::none; + } + return m_memberCurrentUser->_Subscribed_change_types(); +} + +std::vector +multiplayer_session::host_candidates() const +{ + return m_hostCandidate; +} + +const multiplayer_session_reference& +multiplayer_session::session_reference() const +{ + return m_sessionReference; +} + + +std::shared_ptr +multiplayer_session::session_constants() const +{ + return m_sessionConstants; +} + +std::shared_ptr +multiplayer_session::session_properties() const +{ + return m_multiplayerSessionProperties; +} + +std::shared_ptr +multiplayer_session::session_role_types() const +{ + return m_sessionRoleTypes; +} + +const std::vector>& +multiplayer_session::members() const +{ + return m_members; +} + +const multiplayer_session_matchmaking_server& +multiplayer_session::matchmaking_server() const +{ + return m_matchmakingServer; +} + +const multiplayer_session_tournaments_server& +multiplayer_session::tournaments_server() const +{ + return m_tournamentsServer; +} + +const multiplayer_session_arbitration_server& +multiplayer_session::arbitration_server() const +{ + return m_arbitrationServer; +} + +uint32_t +multiplayer_session::members_accepted() const +{ + return m_membersAccepted; +} + +const web::json::value& +multiplayer_session::servers_json() const +{ + return m_servers; +} + +void +multiplayer_session::set_servers_json( + _In_ const web::json::value& serversJson + ) +{ + m_servers = serversJson; + m_sessionRequest->set_servers(m_servers); +} + +const string_t& +multiplayer_session::e_tag() const +{ + return m_eTag; +} + +std::shared_ptr +multiplayer_session::current_user() const +{ + return m_memberCurrentUser; +} + +const string_t& +multiplayer_session::branch() const +{ + return m_branch; +} + +uint64_t +multiplayer_session::change_number() const +{ + return m_changeNumber; +} + +write_session_status +multiplayer_session::write_status() const +{ + return m_writeSessionStatus; +} + +void +multiplayer_session::_Set_write_session_status( + int32_t httpStatusCode + ) +{ + m_writeSessionStatus = convert_http_status_to_write_session_status(httpStatusCode); +} + +std::error_code +multiplayer_session::add_member_reservation( + _In_ const string_t& xboxUserId, + _In_ const web::json::value& memberCustomConstantsJson + ) +{ + return add_member_reservation_helper( + xboxUserId, + memberCustomConstantsJson, + false, + false + ); +} + +std::error_code +multiplayer_session::add_member_reservation( + _In_ const string_t& xboxUserId, + _In_ const web::json::value& memberCustomConstantsJson, + _In_ bool initializeRequested + ) +{ + return add_member_reservation_helper( + xboxUserId, + memberCustomConstantsJson, + true, + initializeRequested + ); +} + +xbox_live_result> +multiplayer_session::join( + _In_ const web::json::value& memberCustomConstantsJson, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus, + _In_ bool addInitializePropertyToRequest + ) +{ + return join_helper( + memberCustomConstantsJson, + addInitializePropertyToRequest, + initializeRequested, + joinWithActiveStatus + ); +} + +void +multiplayer_session::set_visibility( + _In_ multiplayer_session_visibility visibility + ) +{ + m_sessionConstants->set_visibility(visibility); +} + +void +multiplayer_session::set_max_members_in_session( + _In_ uint32_t maxMembersInSession + ) +{ + m_sessionConstants->set_max_members_in_session(maxMembersInSession); +} + + +std::error_code +multiplayer_session::set_timeouts( + _In_ std::chrono::milliseconds memberReservedTimeout, + _In_ std::chrono::milliseconds memberInactiveTimeout, + _In_ std::chrono::milliseconds memberReadyTimeout, + _In_ std::chrono::milliseconds sessionEmptyTimeout + ) +{ + // Call set_timeouts/SetTimeouts before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_timeouts( + memberReservedTimeout, + memberInactiveTimeout, + memberReadyTimeout, + sessionEmptyTimeout + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_arbitration_timeouts( + _In_ std::chrono::milliseconds arbitrationTimeout, + _In_ std::chrono::milliseconds forfeitTimeout + ) +{ + // Call set_arbitration_timeouts/SetArbitrationTimeouts before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_arbitration_timeouts( + arbitrationTimeout, + forfeitTimeout + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_quality_of_service_connectivity_metrics( + _In_ bool enableLatencyMetric, + _In_ bool enableBandwidthDownMetric, + _In_ bool enableBandwidthUpMetric, + _In_ bool enableCustomMetric + ) +{ + // Call set_quality_of_service_connectivity_metrics/SetQualityOfServiceConnectivityMetrics + // before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_quality_of_service_connectivity_metrics( + enableLatencyMetric, + enableBandwidthDownMetric, + enableBandwidthUpMetric, + enableCustomMetric + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_managed_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool autoEvaluate, + _In_ uint32_t membersNeededToStart + ) +{ + // Call set_managed_initialization/SetManagedInitialization before writing a new session to the service"); + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_managed_initialization( + joinTimeout, + measurementTimeout, + evaluationTimeout, + autoEvaluate, + membersNeededToStart + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_member_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool externalEvaluation, + _In_ uint32_t membersNeededToStart +) +{ + // Call set_member_initialization/SetMemberInitialization before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_member_initialization( + joinTimeout, + measurementTimeout, + evaluationTimeout, + externalEvaluation, + membersNeededToStart + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_peer_to_peer_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthMinimumInKilobitsPerSecond + ) +{ + // Call set_peer_to_peer_requirements/SetPeerToPeerRequirements before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_peer_to_peer_requirements( + std::move(latencyMaximum), + bandwidthMinimumInKilobitsPerSecond + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_peer_to_host_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32_t bandwidthUpMinimumInKilobitsPerSecond, + _In_ multiplay_metrics hostSelectionMetric + ) +{ + // Call set_peer_to_host_requirements/SetPeerToHostRequirements before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_peer_to_host_requirements( + std::move(latencyMaximum), + bandwidthDownMinimumInKilobitsPerSecond, + bandwidthUpMinimumInKilobitsPerSecond, + hostSelectionMetric + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_measurement_server_addresses( + _In_ const std::vector& measurementServerAddresses + ) +{ + // Call set_measurement_server_addresses/SetMeasurementServerAddresses + // before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_measurement_server_addresses(measurementServerAddresses); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_session_capabilities( + _In_ const multiplayer_session_capabilities& capabilities + ) +{ + // Call set_session_capabilities/SetSessionCapabilities before writing a new session to the service + if (!m_newSession) + { + return xbox_live_error_code::logic_error; + } + + m_sessionConstants->_Set_session_capabilities( + capabilities + ); + + return xbox_live_error_code::no_error; +} + +void +multiplayer_session::set_initialization_status( + _In_ bool initializationSucceeded + ) +{ + m_sessionRequest->set_write_initialization_status(true); + m_sessionRequest->set_initialization_succeeded(initializationSucceeded); +} + + +void +multiplayer_session::set_host_device_token( + _In_ const string_t& hostDeviceToken + ) +{ + m_sessionRequest->set_write_host_device_token(true); + m_sessionRequest->set_host_device_token(hostDeviceToken); +} + + +void +multiplayer_session::set_matchmaking_server_connection_path( + _In_ const string_t& serverConnectionPath + ) +{ + m_sessionRequest->set_write_matchmaking_server_connection_path(true); + m_sessionRequest->set_matchmaking_server_connection_path(serverConnectionPath); +} + +void +multiplayer_session::set_matchmaking_resubmit( + _In_ bool matchResubmit + ) +{ + m_sessionRequest->set_write_matchmaking_resubmit(true); + m_sessionRequest->set_matchmaking_match_resubmit(matchResubmit); +} + +void +multiplayer_session::set_closed( + _In_ bool closed + ) +{ + m_sessionRequest->set_write_closed(true); + m_sessionRequest->set_closed(closed); +} + +void +multiplayer_session::set_server_connection_string_candidates( + _In_ const std::vector& serverConnectionStringCandidates + ) +{ + m_sessionRequest->set_write_server_connection_string_candidates(true); + m_sessionRequest->set_server_connection_string_candidates(serverConnectionStringCandidates); +} + +std::error_code +multiplayer_session::set_session_change_subscription( + _In_ multiplayer_session_change_types changeTypes + ) +{ + if(m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_session_change_subscription(changeTypes, m_sessionSubscriptionGuid); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::leave() +{ + // Failed trying to leave and join the session at the same time + if (m_joiningSession) + { + return xbox_live_error_code::logic_error; + } + + for (uint32_t i = 0; i < m_members.size(); ++i) + { + std::shared_ptr member = m_members.at(i); + if (member->is_current_user()) + { + m_members.erase((m_members.begin() + i)); + break; + } + } + + m_sessionRequest->leave_session(); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_status( + _In_ multiplayer_session_member_status status + ) +{ + // Must join the session first before calling SetCurrentUserStatus + // Can not set member to ready + // Can not set member to reserved. Use AddMemberReservation instead + if (m_memberCurrentUser == nullptr || status == multiplayer_session_member_status::ready || status == multiplayer_session_member_status::reserved) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_current_user_status(status); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_secure_device_address_base64( + _In_ const string_t& value + ) +{ + // Must join the session first before calling SetCurrentUserSecureDeviceAddressBase64 + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_secure_device_base_address64(value); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_role_info( + _In_ const std::unordered_map& roles + ) +{ + // Must join the session first before calling SetCurrentUserRoleInfo + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_role_info(roles); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_mutable_role_settings( + _In_ const std::unordered_map& roleTypes + ) +{ + m_sessionRequest->set_mutable_role_settings(roleTypes); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_members_in_group( + _In_ const std::vector>& membersInGroup + ) +{ + // Must join the session first before calling SetCurrentUserMembersInGroup + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_current_user_members_in_group(membersInGroup); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_quality_of_service_measurements( + _In_ std::shared_ptr> measurements + ) +{ + // Must join the session first before calling SetCurrentUserQualityOfServiceMeasurements + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_current_user_quality_of_service_measurements( + measurements + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_quality_of_service_measurements_json( + _In_ const web::json::value& serverMeasurementsJson + ) +{ + // Must join the session first before calling SetCurrentUserQualityOfServiceServerMeasurementsJson + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_current_user_quality_of_service_server_measurements_json(serverMeasurementsJson); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_member_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + // Must join the session first before calling SetCurrentUserMemberCustomPropertyJson + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::invalid_argument; + } + m_memberCurrentUser->_Set_member_custom_property_json(name, valueJson); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_current_user_member_arbitration_results( + _In_ const std::unordered_map& results + ) +{ + // Must join the session first before calling set_current_user_member_arbitration_result + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + + m_memberCurrentUser->_Set_arbitration_results(results); + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::delete_current_user_member_custom_property_json( + _In_ const string_t& name + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + // Must join the session first before calling DeleteCurrentUserMemberCustomPropertyJson + if (m_memberCurrentUser == nullptr) + { + return xbox_live_error_code::logic_error; + } + m_memberCurrentUser->_Delete_custom_property_json(name); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_matchmaking_target_session_constants_json( + _In_ web::json::value matchmakingTargetSessionConstantsJson + ) +{ + m_multiplayerSessionProperties->_Set_matchmaking_target_session_constants_json( + matchmakingTargetSessionConstantsJson + ); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::set_session_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + m_multiplayerSessionProperties->_Set_session_custom_property_json(name, valueJson); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::delete_session_custom_property_json( + _In_ const string_t& name + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + m_multiplayerSessionProperties->_Delete_session_custom_property_json(name); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session::add_member_reservation_helper( + _In_ const string_t& xboxUserId, + _In_ const web::json::value& memberCustomConstantsJson, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializeRequested + ) +{ + if (xboxUserId.empty()) + { + return xbox_live_error_code::invalid_argument; + } + web::json::value customConstantsJson; + if (!memberCustomConstantsJson.is_null()) + { + customConstantsJson = memberCustomConstantsJson; + } + + std::shared_ptr memberRequest = m_sessionRequest->add_member_request( + true, + false, + xboxUserId, + customConstantsJson, + addInitializePropertyToRequest, + initializeRequested + ); + + std::shared_ptr member = std::make_shared( + false, + 0, + xboxUserId, + customConstantsJson + ); + + member->_Set_member_request(memberRequest); + member->_Set_session_request(m_sessionRequest); + m_members.push_back(member); + + return xbox_live_error_code::no_error; +} + +xbox_live_result> +multiplayer_session::join_helper( + _In_ web::json::value memberCustomConstantsJson, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializeRequested, + _In_ bool joinWithActiveStatus + ) +{ + if (m_joiningSession) + { + return xbox_live_result>(xbox_live_error_code::logic_error, "Failed trying to join the session more than once"); + } + + m_joiningSession = true; + + web::json::value customConstantsJson = web::json::value::null(); + if (!memberCustomConstantsJson.is_null()) + { + customConstantsJson = memberCustomConstantsJson; + } + + std::shared_ptr memberRequest = m_sessionRequest->add_member_request( + true, + true, + m_xboxUserId, + customConstantsJson, + addInitializePropertyToRequest, + initializeRequested + ); + + if (joinWithActiveStatus) + { + memberRequest->set_is_active(true); + memberRequest->set_write_is_active(true); + } + + std::shared_ptr member = std::make_shared( + true, + 0, + m_xboxUserId, + customConstantsJson + ); + + member->_Set_member_request(memberRequest); + member->_Set_session_request(m_sessionRequest); + m_members.push_back(member); + m_memberCurrentUser = member; + + return xbox_live_result>(member); +} + +void +multiplayer_session::ensure_session_subscription_id_initialized() +{ + if (m_sessionSubscriptionGuid.empty()) + { + m_sessionSubscriptionGuid = utils::create_guid(true); + } +} + +multiplay_metrics +multiplayer_session::_Convert_string_to_multiplayer_host_selection_metric( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return multiplay_metrics::latency; + } + else if (utils::str_icmp(value, _T("bandwidthUp")) == 0) + { + return multiplay_metrics::bandwidth_up; + } + else if (utils::str_icmp(value, _T("bandwidthDown")) == 0) + { + return multiplay_metrics::bandwidth_down; + } + else if (utils::str_icmp(value, _T("bandwidth")) == 0) + { + return multiplay_metrics::bandwidth; + } + else if (utils::str_icmp(value, _T("latency")) == 0) + { + return multiplay_metrics::latency; + } + + return multiplay_metrics::unknown; +} + +const xbox_live_result +multiplayer_session::_Convert_multiplayer_host_selection_metric_to_string( + _In_ multiplay_metrics multiplayMetric + ) +{ + switch (multiplayMetric) + { + case multiplay_metrics::unknown: return xbox_live_result(_T("unknown")); + + case multiplay_metrics::bandwidth_up: return xbox_live_result(_T("bandwidthUp")); + + case multiplay_metrics::bandwidth_down: return xbox_live_result(_T("bandwidthDown")); + + case multiplay_metrics::bandwidth: return xbox_live_result(_T("bandwidth")); + + case multiplay_metrics::latency: return xbox_live_result(_T("latency")); + + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Enum out of range"); + } +} + +multiplayer_initialization_stage +multiplayer_session::_Convert_string_to_multiplayer_initialization_stage( + _In_ const string_t& value +) +{ + if (value.empty()) + { + return multiplayer_initialization_stage::none; + } + else if (utils::str_icmp(value, _T("joining")) == 0) + { + return multiplayer_initialization_stage::joining; + } + else if (utils::str_icmp(value, _T("failed")) == 0) + { + return multiplayer_initialization_stage::failed; + } + else if (utils::str_icmp(value, _T("evaluating")) == 0) + { + return multiplayer_initialization_stage::evaluating; + } + else if (utils::str_icmp(value, _T("measuring")) == 0) + { + return multiplayer_initialization_stage::measuring; + } + + return multiplayer_initialization_stage::unknown; +} + +xbox_live_result +multiplayer_session::_Convert_string_to_matchmaking_status( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Value was empty"); + } + + if (utils::str_icmp(value, _T("searching")) == 0) + { + return xbox_live_result(matchmaking_status::searching); + } + else if (utils::str_icmp(value, _T("expired")) == 0) + { + return xbox_live_result(matchmaking_status::expired); + } + else if (utils::str_icmp(value, _T("found")) == 0) + { + return xbox_live_result(matchmaking_status::found); + } + else if (utils::str_icmp(value, _T("canceled")) == 0) + { + return xbox_live_result(matchmaking_status::canceled); + } + + return xbox_live_result(matchmaking_status::unknown); +} + +const xbox_live_result +multiplayer_session::_Convert_matchmaking_status_to_string( + _In_ matchmaking_status matchmakingStatus + ) +{ + switch (matchmakingStatus) + { + case matchmaking_status::unknown: return xbox_live_result(_T("unknown")); + + case matchmaking_status::searching: return xbox_live_result(_T("searching")); + + case matchmaking_status::expired: return xbox_live_result(_T("expired")); + + case matchmaking_status::found: return xbox_live_result(_T("found")); + + case matchmaking_status::canceled: return xbox_live_result(_T("canceled")); + + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Enum out of range"); + } +} + +write_session_status +multiplayer_session::convert_http_status_to_write_session_status( +_In_ int32_t httpStatusCode +) +{ + switch (httpStatusCode) + { + case 200: return write_session_status::updated; + + case 201: return write_session_status::created; + + case 204: return write_session_status::session_deleted; + + case 401: return write_session_status::access_denied; + + case 404: return write_session_status::handle_not_found; + + case 409: return write_session_status::conflict; + + case 412: return write_session_status::out_of_sync; + + default: return write_session_status::unknown; + } +} + +std::vector> +multiplayer_session::_Deserialize_me_member( + _In_ const web::json::value& json, + _In_ std::error_code& errc + ) +{ + web::json::value membersInfo = utils::extract_json_field(json, _T("membersInfo"), errc, true); + uint32_t first = utils::extract_json_int(membersInfo, _T("first"), errc, true); + web::json::value memberJson = utils::extract_json_field(json, _T("members"), errc, true); + uint32_t current = first; + + std::vector> members; + + auto member = multiplayer_session_member::_Deserialize( + utils::extract_json_field( + memberJson, + _T("me"), + errc, + true + ) + ); + + if (member.err()) + { + errc = member.err(); + } + std::shared_ptr meMember = std::make_shared( + member.payload() + ); + + meMember->_Set_member_id(current); + + members.push_back(meMember); + + return members; +} + +std::vector> +multiplayer_session::_Deserialize_members_list( + _In_ const web::json::value& json, + _In_ std::error_code& errc + ) +{ + web::json::value membersInfo = utils::extract_json_field(json, _T("membersInfo"), errc, false); + uint32_t first = utils::extract_json_int(membersInfo, _T("first"), errc, false); + uint32_t count = utils::extract_json_int(membersInfo, _T("count"), errc, false); + + std::vector> members; + uint32_t current = first; + web::json::value membersJson = utils::extract_json_field(json, _T("members"), errc, false); + for (uint32_t i = 0; i < count; i++) + { + stringstream_t stream; + stream << current; + web::json::value memberJsonIndex = utils::extract_json_field(membersJson, stream.str(), errc, true); + + auto member = multiplayer_session_member::_Deserialize(memberJsonIndex); + if (member.err()) + { + errc = member.err(); + } + + std::shared_ptr currentMember = std::make_shared( + member.payload() + ); + + currentMember->_Set_member_id(current); + members.push_back(currentMember); + + uint32_t next = utils::extract_json_int(memberJsonIndex, _T("next"), errc, false, current); + if (next == current) + { + break; + } + + current = next; + } + + return members; +} + +std::error_code +multiplayer_session::_Populate_members_with_members_list( + _In_ std::vector> members + ) +{ + std::error_code errc; + for (auto& member : members) + { + errc = member->set_members_list(members); + } + return errc; +} + +xbox_live_result +multiplayer_session::compare_multiplayer_sessions( + _In_ std::shared_ptr currentSession, + _In_ std::shared_ptr oldSession + ) +{ + if (currentSession == nullptr || oldSession == nullptr) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Cannot compare a null session"); + } + + uint32_t currentType = static_cast(multiplayer_session_change_types::none); + + if (utils::str_icmp(currentSession->session_properties()->host_device_token(), oldSession->session_properties()->host_device_token()) != 0) + { + currentType |= multiplayer_session_change_types::host_device_token_change; + } + + if (currentSession->initialization_stage() != oldSession->initialization_stage()) + { + currentType |= multiplayer_session_change_types::initialization_state_change; + } + + if ((currentSession->matchmaking_server().is_null() != oldSession->matchmaking_server().is_null()) || + (!currentSession->matchmaking_server().is_null() && currentSession->matchmaking_server().status() != oldSession->matchmaking_server().status()) + ) + { + currentType |= multiplayer_session_change_types::matchmaking_status_change; + } + + bool hasMemberChanged = false; + bool memberStatusChanged = false; + bool memberCustomPropertyChanged = false; + + if (currentSession->members().size() != oldSession->members().size()) + { + hasMemberChanged = true; + } + + for (uint32_t i = 0; i < currentSession->members().size(); i++) + { + std::shared_ptr currentSessionMember = currentSession->members()[i]; + bool isMemberFound = false; + for (uint32_t j = 0; j < oldSession->members().size(); j++) + { + std::shared_ptr olderSessionMember = oldSession->members()[j]; + + if (utils::str_icmp(currentSessionMember->xbox_user_id(), + olderSessionMember->xbox_user_id()) == 0) + { + isMemberFound = true; + + if (currentSessionMember->status() != olderSessionMember->status()) + { + memberStatusChanged = true; + } + + if (utils::str_icmp(currentSessionMember->member_custom_properties_json().serialize(), + olderSessionMember->member_custom_properties_json().serialize()) != 0) + { + memberCustomPropertyChanged = true; + } + } + } + + if (!isMemberFound) + { + hasMemberChanged = true; + } + + if (memberStatusChanged && hasMemberChanged && memberCustomPropertyChanged) + { + break; + } + } + + if (hasMemberChanged) + { + currentType |= multiplayer_session_change_types::member_list_change; + } + + if (memberStatusChanged) + { + currentType |= multiplayer_session_change_types::member_status_change; + } + + if (memberCustomPropertyChanged) + { + currentType |= multiplayer_session_change_types::member_custom_property_change; + } + + + if (currentSession->session_properties()->closed() != oldSession->session_properties()->closed() || + currentSession->session_properties()->join_restriction() != oldSession->session_properties()->join_restriction() || + (currentSession->members().size() == currentSession->session_constants()->max_members_in_session()) != + (oldSession->members().size() == oldSession->session_constants()->max_members_in_session()) // if the session is open again or closed again because the max member has changed + ) + { + currentType |= multiplayer_session_change_types::session_joinability_change; + } + + if (utils::str_icmp(currentSession->session_properties()->session_custom_properties_json().serialize(), oldSession->session_properties()->session_custom_properties_json().serialize()) != 0) + { + currentType |= multiplayer_session_change_types::custom_property_change; + } + + if (!currentSession->tournaments_server()._Is_same(oldSession->tournaments_server())) + { + currentType |= multiplayer_session_change_types::tournament_property_change; + } + + if (!currentSession->arbitration_server()._Is_same(oldSession->arbitration_server())) + { + currentType |= multiplayer_session_change_types::arbitration_property_change; + } + + return xbox_live_result(static_cast(currentType)); +} + +xbox_live_result +multiplayer_session::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session returnResult; + if ( json.is_null() ) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value initializingJson = utils::extract_json_field(json, _T("initializing"), errc, false); + web::json::value memberInfoJson = utils::extract_json_field(json, _T("membersInfo"), errc, false); + + returnResult.m_correlationId = utils::extract_json_string(json, _T("correlationId"), errc); + returnResult.m_searchHandleId = utils::extract_json_string(json, _T("searchHandle"), errc, false); + returnResult.m_startTime = utils::extract_json_time(json, _T("startTime"), errc); + + returnResult.m_branch = utils::extract_json_string(json, _T("branch"), errc); + returnResult.m_changeNumber = utils::extract_json_int(json, _T("changeNumber"), errc, false, ULONG_MAX); + + auto sessionConstants = multiplayer_session_constants::_Deserialize( + utils::extract_json_field( + json, + _T("constants"), + errc, + true + ) + ); + + if (sessionConstants.err()) + { + errc = sessionConstants.err(); + } + returnResult.m_sessionConstants = std::make_shared( + sessionConstants.payload() + ); + + returnResult.m_nextTimer = utils::extract_json_time(json, _T("nextTimer"), errc); + returnResult.m_initializationStage = _Convert_string_to_multiplayer_initialization_stage(utils::extract_json_string(initializingJson, _T("stage"), errc)); + returnResult.m_initializationStageStartTime = utils::extract_json_time(initializingJson, _T("stageStartTime"), errc); + returnResult.m_initializationEpisode = utils::extract_json_int(initializingJson, _T("episode"), errc); + returnResult.m_hostCandidate = utils::extract_json_vector(utils::json_string_extractor, json, _T("hostCandidates"), errc, false); + + web::json::value jsonMembers = utils::extract_json_field(json, _T("members"), errc, false); + if (jsonMembers.size() != 0) + { + if (returnResult.m_sessionConstants->capabilities_large()) + { + returnResult.m_members = _Deserialize_me_member(json, errc); + } + else + { + returnResult.m_members = _Deserialize_members_list(json, errc); + } + } + + _Populate_members_with_members_list(returnResult.m_members); + + auto multiplayerSessionProperties = multiplayer_session_properties::_Deserialize( + utils::extract_json_field( + json, + _T("properties"), + true + ) + ); + + if (multiplayerSessionProperties.err()) + { + errc = multiplayerSessionProperties.err(); + } + returnResult.m_multiplayerSessionProperties = std::make_shared(multiplayerSessionProperties.payload()); + + returnResult.m_multiplayerSessionProperties->_Initialize( + returnResult.m_sessionRequest, + returnResult.m_members + ); + returnResult.m_membersAccepted = utils::extract_json_int(memberInfoJson, _T("accepted")); + + auto sessionRoleTypes = multiplayer_session_role_types::_Deserialize( + utils::extract_json_field(json, _T("roleTypes"), false) + ); + + if (sessionRoleTypes.err()) + { + errc = sessionRoleTypes.err(); + } + returnResult.m_sessionRoleTypes = std::make_shared(sessionRoleTypes.payload()); + + auto serversJson = utils::extract_json_field(json, _T("servers"), errc, false); + auto serversMatchmakingJson = utils::extract_json_field(serversJson, _T("matchmaking"), errc, false); + auto serversMatchmakingPropertiesJson = utils::extract_json_field(serversMatchmakingJson, _T("properties"), errc, false); + + if (!serversMatchmakingJson.is_null()) + { + returnResult.m_matchmakingServer = + multiplayer_session_matchmaking_server::_Deserialize( + utils::extract_json_field(serversMatchmakingPropertiesJson, _T("system"), errc, false) + ).payload(); + + returnResult.m_hasMatchmakingServer = true; + } + + auto serversArbitrationJson = utils::extract_json_field(serversJson, _T("arbitration"), errc, false); + if (!serversArbitrationJson.is_null()) + { + auto arbitrationServerResult = multiplayer_session_arbitration_server::_Deserialize(serversArbitrationJson); + if (arbitrationServerResult.err()) + { + errc = arbitrationServerResult.err(); + } + returnResult.m_arbitrationServer = arbitrationServerResult.payload(); + } + + auto serversTournamentJson = utils::extract_json_field(serversJson, _T("tournaments"), errc, false); + if (!serversTournamentJson.is_null()) + { + auto tournamentServerResult = multiplayer_session_tournaments_server::_Deserialize(serversTournamentJson); + if (tournamentServerResult.err()) + { + errc = tournamentServerResult.err(); + } + returnResult.m_tournamentsServer = tournamentServerResult.payload(); + + if (returnResult.m_members.size() > 0 && returnResult.m_tournamentsServer.teams().size() > 0) + { + auto teamRefs = returnResult.m_tournamentsServer.teams(); + for (size_t i = 0; i < returnResult.m_members.size(); ++i) + { + auto member = returnResult.m_members[i]; + if (teamRefs.find(member->m_teamId) != teamRefs.end()) + { + member->m_tournamentTeamSessionRef = teamRefs[member->m_teamId]; + } + else + { + errc = xbox_live_error_code::json_error; + } + } + } + } + + returnResult.m_servers = std::move(serversJson); + + return xbox_live_result(returnResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_arbitration_server.cpp b/Source/Services/Multiplayer/multiplayer_session_arbitration_server.cpp new file mode 100644 index 00000000..9733d00c --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_arbitration_server.cpp @@ -0,0 +1,135 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_arbitration_server::multiplayer_session_arbitration_server() : + m_resultState(tournament_arbitration_state::no_results), + m_resultSource(tournament_game_result_source::none), + m_resultConfidenceLevel(0), + m_isNull(true) +{ +} + +tournament_arbitration_state multiplayer_session_arbitration_server::result_state() const +{ + return m_resultState; +} + +tournament_game_result_source multiplayer_session_arbitration_server::result_source() const +{ + return m_resultSource; +} + +uint32_t multiplayer_session_arbitration_server::result_confidence_level() const +{ + return m_resultConfidenceLevel; +} + +const std::unordered_map& multiplayer_session_arbitration_server::results() const +{ + return m_results; +} + +bool +multiplayer_session_arbitration_server::_Is_null() const +{ + return m_isNull; +} + +bool +multiplayer_session_arbitration_server::_Is_same(const multiplayer_session_arbitration_server& other) const +{ + std::unordered_map otherResults = other.results(); + if (m_resultConfidenceLevel != other.result_confidence_level() || + m_resultState != other.result_state() || + m_resultSource != other.result_source() || + m_results.size() != otherResults.size()) + { + return false; + } + + for (const auto& result : m_results) + { + const auto& otherResult = otherResults.find(result.first); + if (otherResult != otherResults.end() || + otherResult->second.state() != result.second.state() || + otherResult->second.ranking() != result.second.ranking()) + { + return false; + } + } + + return true; +} + +tournament_arbitration_state +multiplayer_session_arbitration_server::_Convert_string_to_arbitration_state( + _In_ const string_t& value + ) +{ + if (value == _T("completed")) + { + return tournament_arbitration_state::completed; + } + else if (value == _T("canceled")) + { + return tournament_arbitration_state::canceled; + } + else if (value == _T("partialresults")) + { + return tournament_arbitration_state::partial_results; + } + + return tournament_arbitration_state::no_results; +} + +xbox_live_result +multiplayer_session_arbitration_server::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_arbitration_server returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + auto propertiesJson = utils::extract_json_field(json, _T("properties"), errc, true); + auto systemPropertiesJson = utils::extract_json_field(propertiesJson, _T("system"), errc, true); + + returnObject.m_resultState = _Convert_string_to_arbitration_state(utils::extract_json_string(systemPropertiesJson, _T("resultState"), errc, false)); + returnObject.m_resultSource = multiplayer_service::_Convert_string_to_game_result_source(utils::extract_json_string(systemPropertiesJson, _T("resultSource"), errc, false)); + returnObject.m_resultConfidenceLevel = static_cast(utils::extract_json_uint52(systemPropertiesJson, _T("resultConfidenceLevel"), errc, false)); + + auto resultsJson = utils::extract_json_field(systemPropertiesJson, _T("results"), errc, false); + if (!resultsJson.is_null()) + { + web::json::object resultsObj = resultsJson.as_object(); + for (const auto& result : resultsObj) + { + const string_t& team = result.first; + auto tournamentTemResult = tournament_team_result::_Deserialize(result.second); + if (tournamentTemResult.err()) + { + errc = tournamentTemResult.err(); + } + returnObject.m_results[team] = tournamentTemResult.payload(); + } + } + + returnObject.m_isNull = false; + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_capabilities.cpp b/Source/Services/Multiplayer/multiplayer_session_capabilities.cpp new file mode 100644 index 00000000..ae1456a9 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_capabilities.cpp @@ -0,0 +1,185 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_capabilities::multiplayer_session_capabilities(): + m_connectivity(false), + m_suppressPresenceActivityCheck(false), + m_gameplay(false), + m_large(false), + m_connectionRequiredForActiveMembers(false), + m_userAuthorizationStyle(false), + m_crossplay(false), + m_team(false), + m_arbitration(false), + m_searchable(false), + m_hasOwners(false) +{ +} + +bool +multiplayer_session_capabilities::connectivity() const +{ + return m_connectivity; +} + +void +multiplayer_session_capabilities::set_connectivity( + _In_ bool connectivity + ) +{ + m_connectivity = connectivity; +} + +bool multiplayer_session_capabilities::team() const +{ + return m_team; +} + +void +multiplayer_session_capabilities::set_team( + _In_ bool team + ) +{ + m_team = team; +} + +bool multiplayer_session_capabilities::arbitration() const +{ + return m_arbitration; +} + +void +multiplayer_session_capabilities::set_arbitration( + _In_ bool arbitration + ) +{ + m_arbitration = arbitration; +} + + +bool +multiplayer_session_capabilities::suppress_presence_activity_check() const +{ + return m_suppressPresenceActivityCheck; +} + + +void +multiplayer_session_capabilities::set_suppress_presence_activity_check( + _In_ bool suppressPresenceActivityCheck + ) +{ + m_suppressPresenceActivityCheck = suppressPresenceActivityCheck; +} + +bool +multiplayer_session_capabilities::gameplay() const +{ + return m_gameplay; +} + +void +multiplayer_session_capabilities::set_gameplay( + _In_ bool gameplay + ) +{ + m_gameplay = gameplay; +} + +bool +multiplayer_session_capabilities::large() const +{ + return m_large; +} + +void +multiplayer_session_capabilities::set_large( + _In_ bool large + ) +{ + m_large = large; +} + +bool +multiplayer_session_capabilities::connection_required_for_active_members() const +{ + return m_connectionRequiredForActiveMembers; +} + +void +multiplayer_session_capabilities::set_connection_required_for_active_members( + _In_ bool connectionRequired + ) +{ + m_connectionRequiredForActiveMembers = connectionRequired; +} + +bool +multiplayer_session_capabilities::user_authorization_style() const +{ + return m_userAuthorizationStyle; +} + +void +multiplayer_session_capabilities::set_user_authorization_style( + _In_ bool userAuthorizationStyle + ) +{ + m_userAuthorizationStyle = userAuthorizationStyle; +} + +bool +multiplayer_session_capabilities::crossplay() const +{ + return m_crossplay; +} + +void +multiplayer_session_capabilities::set_crossplay( + _In_ bool crossplay + ) +{ + m_crossplay = crossplay; +} + +bool +multiplayer_session_capabilities::searchable() const +{ + return m_searchable; +} + +void +multiplayer_session_capabilities::set_searchable( + _In_ bool searchable + ) +{ + m_searchable = searchable; +} + +bool +multiplayer_session_capabilities::has_owners() const +{ + return m_hasOwners; +} + +void +multiplayer_session_capabilities::set_has_owners( + _In_ bool hasOwners + ) +{ + m_hasOwners = hasOwners; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_change_event_args.cpp b/Source/Services/Multiplayer/multiplayer_session_change_event_args.cpp new file mode 100644 index 00000000..28358a26 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_change_event_args.cpp @@ -0,0 +1,44 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_change_event_args::multiplayer_session_change_event_args( + _In_ multiplayer_session_reference sessionRef, + _In_ string_t branch, + _In_ uint64_t changeNumber + ) : + m_sessionReference(std::move(sessionRef)), + m_branch(std::move(branch)), + m_changeNumber(changeNumber) +{ +} + +const multiplayer_session_reference& +multiplayer_session_change_event_args::session_reference() const +{ + return m_sessionReference; +} + +const string_t& +multiplayer_session_change_event_args::branch() const +{ + return m_branch; +} + +uint64_t +multiplayer_session_change_event_args::change_number() const +{ + return m_changeNumber; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_constants.cpp b/Source/Services/Multiplayer/multiplayer_session_constants.cpp new file mode 100644 index 00000000..c2bfcee9 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_constants.cpp @@ -0,0 +1,739 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +std::mutex multiplayer_session_constants::m_lock; +const uint32_t c_multiplayerSessionVersion = 1; + +multiplayer_session_constants::multiplayer_session_constants() : + m_maxMembersInSession(0), + m_visibility(multiplayer_session_visibility::unknown), + m_writeTimeouts(false), + m_writeArbitrationTimeouts(false), + m_writeQualityOfServiceConnectivityMetrics(false), + m_enableMetricsLatency(false), + m_enableMetricsBandwidthDown(false), + m_enableMetricsBandwidthUp(false), + m_enableMetricsCustom(false), + m_shouldSerialize(false), + m_writeMemberInitialization(false), + m_writePeerToPeerRequirements(false), + m_writePeerToHostRequirements(false), + m_writeMeasurementServerAddresses(false) +{ + m_sessionCustomConstants = web::json::value::object(); + m_measurementServerAddressesJson = web::json::value::object(); +} + +multiplayer_session_constants::multiplayer_session_constants( + _In_ uint32_t maxMembersInSession, + _In_ multiplayer_session_visibility visibility, + _In_ std::vector initiatorXboxIds, + _In_ web::json::value sessionCustomConstants + ) : + m_maxMembersInSession(maxMembersInSession), + m_visibility(visibility), + m_initiatorXboxUserIds(std::move(initiatorXboxIds)), + m_sessionCustomConstants(std::move(sessionCustomConstants)), + m_shouldSerialize(true), + m_writeTimeouts(false), + m_writeArbitrationTimeouts(false), + m_writeQualityOfServiceConnectivityMetrics(false), + m_enableMetricsLatency(false), + m_enableMetricsBandwidthDown(false), + m_enableMetricsBandwidthUp(false), + m_enableMetricsCustom(false), + m_writeMemberInitialization(false), + m_writePeerToPeerRequirements(false), + m_writePeerToHostRequirements(false), + m_writeMeasurementServerAddresses(false) +{ + XSAPI_ASSERT( + visibility >= multiplayer_session_visibility::any && + visibility <= multiplayer_session_visibility::open + ); + + m_measurementServerAddressesJson = web::json::value::object(); +} + +multiplayer_session_constants::multiplayer_session_constants( + _In_ std::vector initiatorXboxIds + ) : + m_maxMembersInSession(0), + m_visibility(multiplayer_session_visibility::unknown), + m_initiatorXboxUserIds(std::move(initiatorXboxIds)), + m_shouldSerialize(true), + m_writeTimeouts(false), + m_writeArbitrationTimeouts(false), + m_writeQualityOfServiceConnectivityMetrics(false), + m_enableMetricsLatency(false), + m_enableMetricsBandwidthDown(false), + m_enableMetricsBandwidthUp(false), + m_enableMetricsCustom(false), + m_writeMemberInitialization(false), + m_writePeerToPeerRequirements(false), + m_writePeerToHostRequirements(false), + m_writeMeasurementServerAddresses(false) +{ + m_sessionCustomConstants = web::json::value::object(); + m_measurementServerAddressesJson = web::json::value::object(); +} + +uint32_t +multiplayer_session_constants::max_members_in_session() const +{ + return m_maxMembersInSession; +} + +void +multiplayer_session_constants::set_max_members_in_session( + _In_ uint32_t maxMembersInSession + ) +{ + m_maxMembersInSession = maxMembersInSession; + m_shouldSerialize = true; +} + +multiplayer_session_visibility +multiplayer_session_constants::visibility() const +{ + return m_visibility; +} + +void +multiplayer_session_constants::set_visibility( + _In_ multiplayer_session_visibility visibility + ) +{ + m_visibility = visibility; + m_shouldSerialize = true; +} + +const std::vector& +multiplayer_session_constants::initiator_xbox_user_ids() const +{ + return m_initiatorXboxUserIds; +} + +const web::json::value& +multiplayer_session_constants::session_custom_constants_json() const +{ + return m_sessionCustomConstants; +} + +const std::chrono::milliseconds& +multiplayer_session_constants::member_reserved_time_out() const +{ + std::lock_guard guard(m_lock); + return m_memberReservedTimeout; +} + +const std::chrono::milliseconds& +multiplayer_session_constants::member_inactive_timeout() const +{ + std::lock_guard guard(m_lock); + return m_memberInactiveTimeout; +} + +const std::chrono::milliseconds& +multiplayer_session_constants::member_ready_timeout() const +{ + std::lock_guard guard(m_lock); + return m_memberReadyTimeout; +} + +const std::chrono::milliseconds& +multiplayer_session_constants::session_empty_timeout() const +{ + std::lock_guard guard(m_lock); + return m_sessionEmptyTimeout; +} + +const std::chrono::milliseconds& +multiplayer_session_constants::arbitration_timeout() const +{ + std::lock_guard guard(m_lock); + return m_arbitrationTimeout; +} + +const std::chrono::milliseconds& +multiplayer_session_constants::forfeit_timeout() const +{ + std::lock_guard guard(m_lock); + return m_forfeitTimeout; +} + +bool +multiplayer_session_constants::enable_metrics_latency() const +{ + std::lock_guard guard(m_lock); + return m_enableMetricsLatency; +} + +bool +multiplayer_session_constants::enable_metrics_bandwidth_down() const +{ + std::lock_guard guard(m_lock); + return m_enableMetricsBandwidthDown; +} + +bool +multiplayer_session_constants::enable_metrics_bandwidth_up() const +{ + std::lock_guard guard(m_lock); + return m_enableMetricsBandwidthUp; +} + +bool +multiplayer_session_constants::enable_metrics_custom() const +{ + std::lock_guard guard(m_lock); + return m_enableMetricsCustom; +} + +const multiplayer_managed_initialization& +multiplayer_session_constants::managed_initialization() const +{ + std::lock_guard guard(m_lock); + return m_managedInitialization; +} + +const multiplayer_member_initialization& +multiplayer_session_constants::member_initialization() const +{ + std::lock_guard guard(m_lock); + return m_memberInitialization; +} + + +const multiplayer_peer_to_peer_requirements& +multiplayer_session_constants::peer_to_peer_requirements() const +{ + std::lock_guard guard(m_lock); + return m_peerToPeerRequirements; +} + +const multiplayer_peer_to_host_requirements& +multiplayer_session_constants::peer_to_host_requirements() const +{ + std::lock_guard guard(m_lock); + return m_peerToHostRequirements; +} + +const web::json::value& +multiplayer_session_constants::measurement_server_addresses_json() const +{ + return m_measurementServerAddressesJson; +} + +bool +multiplayer_session_constants::capabilities_connectivity() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.connectivity(); +} + +bool +multiplayer_session_constants::capabilities_suppress_presence_activity_check() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.suppress_presence_activity_check(); +} + +bool +multiplayer_session_constants::capabilities_gameplay() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.gameplay(); +} + +bool +multiplayer_session_constants::capabilities_large() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.large(); +} + +bool +multiplayer_session_constants::capabilities_connection_required_for_active_member() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.connection_required_for_active_members(); +} + +bool +multiplayer_session_constants::capabilities_crossplay() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.crossplay(); +} + +bool +multiplayer_session_constants::capabilities_user_authorization_style() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.user_authorization_style(); +} + +bool multiplayer_session_constants::capabilities_team() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.team(); +} + +bool multiplayer_session_constants::capabilities_searchable() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.searchable(); +} + + +bool multiplayer_session_constants::capabilities_arbitration() const +{ + std::lock_guard guard(m_lock); + return m_sessionCapabilities.arbitration(); +} + +bool +multiplayer_session_constants::_Should_serialize() const +{ + std::lock_guard guard(m_lock); + return m_shouldSerialize; +} + +void +multiplayer_session_constants::_Set_timeouts( + _In_ std::chrono::milliseconds memberReservedTimeout, + _In_ std::chrono::milliseconds memberInactiveTimeout, + _In_ std::chrono::milliseconds memberReadyTimeout, + _In_ std::chrono::milliseconds sessionEmptyTimeout + ) +{ + std::lock_guard guard(m_lock); + + m_writeTimeouts = true; + m_memberReservedTimeout = std::move(memberReservedTimeout); + m_memberInactiveTimeout = std::move(memberInactiveTimeout); + m_memberReadyTimeout = std::move(memberReadyTimeout); + m_sessionEmptyTimeout = std::move(sessionEmptyTimeout); + + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_arbitration_timeouts( + _In_ std::chrono::milliseconds arbitrationTimeout, + _In_ std::chrono::milliseconds forfeitTimeout + ) +{ + std::lock_guard guard(m_lock); + + m_writeArbitrationTimeouts = true; + m_arbitrationTimeout = std::move(arbitrationTimeout); + m_forfeitTimeout = std::move(forfeitTimeout); + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_quality_of_service_connectivity_metrics( + _In_ bool enableLatencyMetric, + _In_ bool enableBandwidthDownMetric, + _In_ bool enableBandwidthUpMetric, + _In_ bool enableCustomMetric + ) +{ + std::lock_guard guard(m_lock); + + m_writeQualityOfServiceConnectivityMetrics = true; + m_enableMetricsLatency = enableLatencyMetric; + m_enableMetricsBandwidthDown = enableBandwidthDownMetric; + m_enableMetricsBandwidthUp = enableBandwidthUpMetric; + m_enableMetricsCustom = enableCustomMetric; + + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_managed_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool autoEvalute, + _In_ uint32_t membersNeededToStart + ) +{ + std::lock_guard guard(m_lock); + + m_writeMemberInitialization = true; + m_managedInitialization = multiplayer_managed_initialization( + std::move(joinTimeout), + std::move(measurementTimeout), + std::move(evaluationTimeout), + autoEvalute, + membersNeededToStart + ); + + m_memberInitialization = multiplayer_member_initialization( + std::move(joinTimeout), + std::move(measurementTimeout), + std::move(evaluationTimeout), + !autoEvalute, + membersNeededToStart + ); + + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_member_initialization( + _In_ std::chrono::milliseconds joinTimeout, + _In_ std::chrono::milliseconds measurementTimeout, + _In_ std::chrono::milliseconds evaluationTimeout, + _In_ bool externalEvaluation, + _In_ uint32_t membersNeededToStart +) +{ + std::lock_guard guard(m_lock); + + m_writeMemberInitialization = true; + m_managedInitialization = multiplayer_managed_initialization( + std::move(joinTimeout), + std::move(measurementTimeout), + std::move(evaluationTimeout), + !externalEvaluation, + membersNeededToStart + ); + + m_memberInitialization = multiplayer_member_initialization( + std::move(joinTimeout), + std::move(measurementTimeout), + std::move(evaluationTimeout), + externalEvaluation, + membersNeededToStart + ); + + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_peer_to_peer_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthMinimumInKilobitsPerSecond + ) +{ + std::lock_guard guard(m_lock); + + m_writePeerToPeerRequirements = true; + m_peerToPeerRequirements = multiplayer_peer_to_peer_requirements( + std::move(latencyMaximum), + bandwidthMinimumInKilobitsPerSecond + ); + + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_peer_to_host_requirements( + _In_ std::chrono::milliseconds latencyMaximum, + _In_ uint32_t bandwidthDownMinimumInKilobitsPerSecond, + _In_ uint32_t bandwidthUpMinimumInKilobitsPerSecond, + _In_ multiplay_metrics hostSelectionMetric + ) +{ + std::lock_guard guard(m_lock); + + m_writePeerToHostRequirements = true; + m_peerToHostRequirements = multiplayer_peer_to_host_requirements( + latencyMaximum, + bandwidthDownMinimumInKilobitsPerSecond, + bandwidthUpMinimumInKilobitsPerSecond, + hostSelectionMetric + ); + + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_session_capabilities( + _In_ const multiplayer_session_capabilities& capabilities + ) +{ + std::lock_guard guard(m_lock); + + m_sessionCapabilities = capabilities; + m_shouldSerialize = true; +} + +void +multiplayer_session_constants::_Set_measurement_server_addresses( + _In_ const std::vector& serverAddresses + ) +{ + std::lock_guard guard(m_lock); + m_writeMeasurementServerAddresses = true; + + for (const auto& address : serverAddresses) + { + web::json::value qosServerJson; + qosServerJson[_T("secureDeviceAddress")] = web::json::value::string(address.secure_device_address_base64()); + auto targetLocationKey = address.target_location(); + std::transform(targetLocationKey.begin(), targetLocationKey.end(), targetLocationKey.begin(), ::tolower); + m_measurementServerAddressesJson[targetLocationKey] = qosServerJson; + } + + m_shouldSerialize = true; +} + +web::json::value +multiplayer_session_constants::_Serialize() +{ + std::lock_guard guard(m_lock); + + web::json::value serializedObject = web::json::value::object(); + if (!m_shouldSerialize) + { + return web::json::value::null(); + } + + web::json::value systemJson; + systemJson[_T("version")] = web::json::value(c_multiplayerSessionVersion); + if (m_maxMembersInSession > 0) + { + systemJson[_T("maxMembersCount")] = web::json::value(m_maxMembersInSession); + } + + web::json::value systemCapabilitiesJson; + + if (m_sessionCapabilities.connectivity()) + { + systemCapabilitiesJson[_T("connectivity")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.suppress_presence_activity_check()) + { + systemCapabilitiesJson[_T("suppressPresenceActivityCheck")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.gameplay()) + { + systemCapabilitiesJson[_T("gameplay")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.large()) + { + systemCapabilitiesJson[_T("large")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.user_authorization_style()) + { + systemCapabilitiesJson[_T("userAuthorizationStyle")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.connection_required_for_active_members()) + { + systemCapabilitiesJson[_T("connectionRequiredForActiveMembers")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.crossplay()) + { + systemCapabilitiesJson[_T("crossplay")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.team()) + { + systemCapabilitiesJson[_T("team")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.arbitration()) + { + systemCapabilitiesJson[_T("arbitration")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.searchable()) + { + systemCapabilitiesJson[_T("searchable")] = web::json::value::boolean(true); + } + + if (m_sessionCapabilities.has_owners()) + { + systemCapabilitiesJson[_T("hasOwners")] = web::json::value::boolean(true); + } + + if (!systemCapabilitiesJson.is_null()) + { + systemJson[_T("capabilities")] = systemCapabilitiesJson; + } + + if (m_visibility != multiplayer_session_visibility::any && m_visibility != multiplayer_session_visibility::unknown) + { + auto visibilityToString = multiplayer_session_states::_Convert_multiplayer_session_visibility_to_string(m_visibility); + systemJson[_T("visibility")] = web::json::value::string( + visibilityToString.payload() + ); + } + + if (!m_initiatorXboxUserIds.empty()) + { + std::sort(m_initiatorXboxUserIds.begin(), m_initiatorXboxUserIds.end()); + systemJson[_T("initiators")] = utils::serialize_vector(utils::json_string_serializer, m_initiatorXboxUserIds); + } + + if (m_writeTimeouts) + { + systemJson[_T("reservedRemovalTimeout")] = utils::serialize_uint52_to_json(m_memberReservedTimeout.count()); + systemJson[_T("inactiveRemovalTimeout")] = utils::serialize_uint52_to_json(m_memberInactiveTimeout.count()); + systemJson[_T("readyRemovalTimeout")] = utils::serialize_uint52_to_json(m_memberReadyTimeout.count()); + systemJson[_T("sessionEmptyTimeout")] = utils::serialize_uint52_to_json(m_sessionEmptyTimeout.count()); + } + + if (m_writeArbitrationTimeouts) + { + web::json::value systemArbitrationTimeoutsJson; + systemArbitrationTimeoutsJson[_T("arbitrationTimeout")] = utils::serialize_uint52_to_json(m_arbitrationTimeout.count()); + systemArbitrationTimeoutsJson[_T("forfeitTimeout")] = utils::serialize_uint52_to_json(m_forfeitTimeout.count()); + systemJson[_T("arbitration")] = systemArbitrationTimeoutsJson; + } + + if (m_writeQualityOfServiceConnectivityMetrics) + { + web::json::value systemMetricsJson; + systemMetricsJson[_T("latency")] = web::json::value(m_enableMetricsLatency); + systemMetricsJson[_T("bandwidthDown")] = web::json::value(m_enableMetricsBandwidthDown); + systemMetricsJson[_T("bandwidthUp")] = web::json::value(m_enableMetricsBandwidthUp); + systemMetricsJson[_T("custom")] = web::json::value(m_enableMetricsCustom); + systemJson[_T("metrics")] = systemMetricsJson; + } + + if (m_writeMemberInitialization) + { + systemJson[_T("memberInitialization")] = m_memberInitialization._Serialize(); + } + + if (m_writePeerToPeerRequirements) + { + systemJson[_T("peerToPeerRequirements")] = m_peerToPeerRequirements._Serialize(); + } + + if (m_writePeerToHostRequirements) + { + systemJson[_T("peerToHostRequirements")] = m_peerToHostRequirements._Serialize(); + } + + if (m_writeMeasurementServerAddresses) + { + systemJson[_T("measurementServerAddresses")] = m_measurementServerAddressesJson; + } + + serializedObject[_T("system")] = systemJson; + + if (!m_sessionCustomConstants.is_null()) + { + serializedObject[_T("custom")] = m_sessionCustomConstants; + } + + return serializedObject; +} + +xbox_live_result +multiplayer_session_constants::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_constants returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value systemJson = utils::extract_json_field(json, _T("system"), errc, true); + web::json::value systemCapabilitiesJson = utils::extract_json_field(systemJson, _T("capabilities"), errc, false); + web::json::value systemMetricsJson = utils::extract_json_field(systemJson, _T("metrics"), errc, false); + web::json::value systemArbitrationTimeoutsJson = utils::extract_json_field(systemJson, _T("arbitration"), errc, false); + + returnResult.m_maxMembersInSession = utils::extract_json_int(systemJson, _T("maxMembersCount"), errc); + + returnResult.m_visibility = multiplayer_session_states::_Convert_string_to_session_visibility(utils::extract_json_string(systemJson, _T("visibility"), errc)), + returnResult.m_initiatorXboxUserIds = utils::extract_json_vector(utils::json_string_extractor, systemJson, _T("initiators"), errc, false); + returnResult.m_sessionCustomConstants = utils::extract_json_field(json, _T("custom"), errc, false); + + bool clientConnectivityCapable = utils::extract_json_bool(systemCapabilitiesJson, _T("connectivity"), errc, false); + bool suppressPresenceActivityCheck = utils::extract_json_bool(systemCapabilitiesJson, _T("suppressPresenceActivityCheck"), errc, false); + bool gameplay = utils::extract_json_bool(systemCapabilitiesJson, _T("gameplay"), errc, false); + bool large = utils::extract_json_bool(systemCapabilitiesJson, _T("large"), errc, false); + bool connectionRequiredForActiveMembers = utils::extract_json_bool(systemCapabilitiesJson, _T("connectionRequiredForActiveMembers"), errc, false); + bool userAuthorizationStyle = utils::extract_json_bool(systemCapabilitiesJson, _T("userAuthorizationStyle"), errc, false); + bool crossplay = utils::extract_json_bool(systemCapabilitiesJson, _T("crossplay"), errc, false); + bool team = utils::extract_json_bool(systemCapabilitiesJson, _T("team"), errc, false); + bool arbitration = utils::extract_json_bool(systemCapabilitiesJson, _T("arbitration"), errc, false); + bool hasOwners = utils::extract_json_bool(systemCapabilitiesJson, _T("hasOwners"), errc, false); + bool searchable = utils::extract_json_bool(systemCapabilitiesJson, _T("searchable"), errc, false); + + returnResult.m_sessionCapabilities.set_connectivity( clientConnectivityCapable ); + returnResult.m_sessionCapabilities.set_suppress_presence_activity_check( suppressPresenceActivityCheck ); + returnResult.m_sessionCapabilities.set_gameplay( gameplay ); + returnResult.m_sessionCapabilities.set_large( large ); + returnResult.m_sessionCapabilities.set_connection_required_for_active_members(connectionRequiredForActiveMembers); + returnResult.m_sessionCapabilities.set_user_authorization_style(userAuthorizationStyle); + returnResult.m_sessionCapabilities.set_crossplay(crossplay); + returnResult.m_sessionCapabilities.set_team(team); + returnResult.m_sessionCapabilities.set_arbitration(arbitration); + returnResult.m_sessionCapabilities.set_has_owners(hasOwners); + returnResult.m_sessionCapabilities.set_searchable(searchable); + + returnResult.m_memberReservedTimeout = std::chrono::milliseconds(utils::extract_json_uint52(systemJson, _T("reservedRemovalTimeout"), errc, false)); + returnResult.m_memberInactiveTimeout = std::chrono::milliseconds(utils::extract_json_uint52(systemJson, _T("inactiveRemovalTimeout"), errc, false)); + returnResult.m_memberReadyTimeout = std::chrono::milliseconds(utils::extract_json_uint52(systemJson, _T("readyRemovalTimeout"), errc, false)); + returnResult.m_sessionEmptyTimeout = std::chrono::milliseconds(utils::extract_json_uint52(systemJson, _T("sessionEmptyTimeout"), errc, false)); + returnResult.m_arbitrationTimeout = std::chrono::milliseconds(utils::extract_json_uint52(systemArbitrationTimeoutsJson, _T("arbitrationTimeout"), errc, false)); + returnResult.m_forfeitTimeout = std::chrono::milliseconds(utils::extract_json_uint52(systemArbitrationTimeoutsJson, _T("forfeitTimeout"), errc, false)); + + returnResult.m_enableMetricsLatency = utils::extract_json_bool(systemMetricsJson, _T("latency"), errc, false); + returnResult.m_enableMetricsBandwidthDown = utils::extract_json_bool(systemMetricsJson, _T("bandwidthDown"), errc, false); + returnResult.m_enableMetricsBandwidthUp = utils::extract_json_bool(systemMetricsJson, _T("bandwidthUp"), errc, false); + returnResult.m_enableMetricsCustom = utils::extract_json_bool(systemMetricsJson, _T("custom"), errc, false); + + auto multiplayerManagedInitialization = multiplayer_managed_initialization::_Deserialize(systemJson); + if (multiplayerManagedInitialization.err()) + { + errc = multiplayerManagedInitialization.err(); + } + returnResult.m_managedInitialization = multiplayerManagedInitialization.payload(); + + auto multiplayerMemberInitialization = multiplayer_member_initialization::_Deserialize(systemJson); + if (multiplayerMemberInitialization.err()) + { + errc = multiplayerMemberInitialization.err(); + } + returnResult.m_memberInitialization = multiplayerMemberInitialization.payload(); + + auto multiplayerPeerToPeerRequirements = multiplayer_peer_to_peer_requirements::_Deserialize(utils::extract_json_field(systemJson, _T("peerToPeerRequirements"), errc, false)); + if (multiplayerPeerToPeerRequirements.err()) + { + errc = multiplayerPeerToPeerRequirements.err(); + } + + returnResult.m_peerToPeerRequirements = multiplayerPeerToPeerRequirements.payload(); + + auto multiplayerPeerToHostRequirements = multiplayer_peer_to_host_requirements::_Deserialize(utils::extract_json_field(systemJson, _T("peerToHostRequirements"), errc, false)); + if (multiplayerPeerToHostRequirements.err()) + { + errc = multiplayerPeerToHostRequirements.err(); + } + returnResult.m_peerToHostRequirements = multiplayerPeerToHostRequirements.payload(); + + returnResult.m_measurementServerAddressesJson = utils::extract_json_field(systemJson, _T("measurementServerAddresses"), errc, false); + + returnResult.m_shouldSerialize = true; + return xbox_live_result(returnResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_matchmaking_server.cpp b/Source/Services/Multiplayer/multiplayer_session_matchmaking_server.cpp new file mode 100644 index 00000000..a495df83 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_matchmaking_server.cpp @@ -0,0 +1,104 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_matchmaking_server::multiplayer_session_matchmaking_server() : + m_status(matchmaking_status::unknown), + m_isNull(true) +{ +} + +matchmaking_status +multiplayer_session_matchmaking_server::status() const +{ + return m_status; +} + +const string_t& +multiplayer_session_matchmaking_server::status_details() const +{ + return m_statusDetails; +} + +const std::chrono::seconds& +multiplayer_session_matchmaking_server::typical_wait() const +{ + return m_typicalWait; +} + +const multiplayer_session_reference& +multiplayer_session_matchmaking_server::target_session_ref() const +{ + return m_targetSessionRef; +} + +bool +multiplayer_session_matchmaking_server::is_null() const +{ + return m_isNull; +} + +xbox_live_result +multiplayer_session_matchmaking_server::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_matchmaking_server returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + auto matchmakingStatusResult = multiplayer_session::_Convert_string_to_matchmaking_status( + utils::extract_json_string(json, _T("status"), errc) + ); + + if (matchmakingStatusResult.err()) + { + return xbox_live_result(matchmakingStatusResult.err(), matchmakingStatusResult.err_message()); + } + returnObject.m_status = matchmakingStatusResult.payload(); + + returnObject.m_statusDetails = utils::extract_json_string( + json, + _T("statusDetails"), + errc + ); + + returnObject.m_typicalWait = std::chrono::seconds( + utils::extract_json_int( + json, + _T("typicalWait"), + errc + ) + ); + + auto multiplayerSessionReference = multiplayer_session_reference::_Deserialize( + utils::extract_json_field( + json, + _T("targetSessionRef"), + errc, + false + ) + ); + + if (multiplayerSessionReference.err()) + { + errc = multiplayerSessionReference.err(); + } + returnObject.m_targetSessionRef = multiplayerSessionReference.payload(); + + returnObject.m_isNull = false; + return returnObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_member.cpp b/Source/Services/Multiplayer/multiplayer_session_member.cpp new file mode 100644 index 00000000..b2ecf959 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_member.cpp @@ -0,0 +1,826 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +std::mutex multiplayer_session_member::m_lock; + +std::shared_ptr multiplayer_session_member::_Create_deep_copy() +{ + auto copy = std::make_shared(); + copy->deep_copy_from(*this); + return copy; +} + +void multiplayer_session_member::deep_copy_from( + _In_ const multiplayer_session_member& other + ) +{ + std::lock_guard guard(other.m_lock); + + m_memberId = other.m_memberId; + m_customConstantsJson = other.m_customConstantsJson; + m_customPropertiesJson = other.m_customPropertiesJson; + m_gamertag = other.m_gamertag; + m_xboxUserId = other.m_xboxUserId; + m_isCurrentUser = other.m_isCurrentUser; + m_isTurnAvailable = other.m_isTurnAvailable; + m_isReserved = other.m_isReserved; + m_isActive = other.m_isActive; + m_isReady = other.m_isReady; + m_roles = other.m_roles; + m_secureDeviceAddressBase64 = other.m_secureDeviceAddressBase64; + m_groups = other.m_groups; + m_encounters = other.m_encounters; + m_subscribedChangeTypes = other.m_subscribedChangeTypes; + m_teamId = other.m_teamId; + m_arbitrationStatus = other.m_arbitrationStatus; + m_results = other.m_results; + m_registrationReason = other.m_registrationReason; + m_registrationState = other.m_registrationState; + m_tournamentTeamSessionRef = other.m_tournamentTeamSessionRef; + + // QoS + m_deviceToken = other.m_deviceToken; + m_nat = other.m_nat; + m_activeTitleId = other.m_activeTitleId; + m_initializationEpisode = other.m_initializationEpisode; + m_joinTime = other.m_joinTime; + m_initializationFailure = other.m_initializationFailure; + m_initialize = other.m_initialize; + m_matchmakingResultServerMeasurementsJson = other.m_matchmakingResultServerMeasurementsJson; + m_memberServerMeasurementsJson = other.m_memberServerMeasurementsJson; + m_membersInGroup = other.m_membersInGroup; + m_memberMeasurementsJson = other.m_memberMeasurementsJson; + m_memberMeasurements = other.m_memberMeasurements; +} + +multiplayer_session_member::multiplayer_session_member() : + m_memberId(0), + m_isCurrentUser(false), + m_isTurnAvailable(false), + m_isReserved(false), + m_isActive(false), + m_isReady(false), + m_nat(network_address_translation_setting::unknown), + m_activeTitleId(0), + m_initializationEpisode(0), + m_initializationFailure(multiplayer_measurement_failure::none), + m_initialize(false), + m_subscribedChangeTypes(multiplayer_session_change_types::none) +{ + m_memberServerMeasurementsJson = web::json::value::object(); + m_matchmakingResultServerMeasurementsJson = web::json::value::object(); + m_customConstantsJson = web::json::value::object(); + m_customPropertiesJson = web::json::value::object(); + m_memberMeasurements = std::make_shared>(); +} + +multiplayer_session_member::multiplayer_session_member( + _In_ bool isCurrentUser, + _In_ uint32_t memberId, + _In_ string_t xboxUserId, + _In_ web::json::value customConstants + ) : + m_isCurrentUser(isCurrentUser), + m_memberId(memberId), + m_xboxUserId(std::move(xboxUserId)), + m_customConstantsJson(std::move(customConstants)), + m_isTurnAvailable(false), + m_isReserved(false), + m_isActive(false), + m_isReady(false), + m_nat(network_address_translation_setting::unknown), + m_activeTitleId(0), + m_initializationEpisode(0), + m_initializationFailure(multiplayer_measurement_failure::none), + m_initialize(false), + m_subscribedChangeTypes(multiplayer_session_change_types::none) +{ + m_memberServerMeasurementsJson = web::json::value::object(); + m_matchmakingResultServerMeasurementsJson = web::json::value::object(); + m_customConstantsJson = web::json::value::object(); + m_customPropertiesJson = web::json::value::object(); + m_memberMeasurements = std::make_shared>(); +} + +uint32_t +multiplayer_session_member::member_id() const +{ + return m_memberId; +} + +const string_t& +multiplayer_session_member::team_id() const +{ + return m_teamId; +} + +tournament_arbitration_status +multiplayer_session_member::arbitration_status() const +{ + return m_arbitrationStatus; +} + +void +multiplayer_session_member::_Set_member_id( + _In_ uint32_t memberId + ) +{ + m_memberId = memberId; +} + +const string_t& +multiplayer_session_member::xbox_user_id() const +{ + return m_xboxUserId; +} + +const web::json::value& +multiplayer_session_member::member_custom_constants_json() const +{ + return m_customConstantsJson; +} + +const string_t& +multiplayer_session_member::secure_device_base_address64() const +{ + std::lock_guard lock(m_lock); + + return m_secureDeviceAddressBase64; +} + +void +multiplayer_session_member::_Set_secure_device_base_address64( + _In_ const string_t& deviceBaseAddress + ) +{ + std::lock_guard lock(m_lock); + + m_secureDeviceAddressBase64 = std::move(deviceBaseAddress); + m_memberRequest->set_secure_device_address_base64(m_secureDeviceAddressBase64); + m_memberRequest->set_write_secure_device_address_base64(true); +} + +const std::unordered_map& +multiplayer_session_member::roles() const +{ + std::lock_guard lock(m_lock); + return m_roles; +} + +void +multiplayer_session_member::_Set_role_info( + _In_ const std::unordered_map& roleInfo + ) +{ + std::lock_guard lock(m_lock); + + m_roles = std::move(roleInfo); + m_memberRequest->set_role_info(m_roles); +} + +const web::json::value& +multiplayer_session_member::member_custom_properties_json() const +{ + std::lock_guard lock(m_lock); + + return m_customPropertiesJson; +} + +const string_t& +multiplayer_session_member::gamertag() const +{ + return m_gamertag; +} + +multiplayer_session_member_status +multiplayer_session_member::status() const +{ + std::lock_guard lock(m_lock); + + if (m_isActive) + { + return multiplayer_session_member_status::active; + } + else if (m_isReady) + { + return multiplayer_session_member_status::ready; + } + else if (m_isReserved) + { + return multiplayer_session_member_status::reserved; + } + else + { + return multiplayer_session_member_status::inactive; + } +} + +const std::unordered_map& +multiplayer_session_member::results() const +{ + return m_results; +} + +bool +multiplayer_session_member::is_turn_available() const +{ + return m_isTurnAvailable; +} + +bool +multiplayer_session_member::is_current_user() const +{ + return m_isCurrentUser; +} + +void +multiplayer_session_member::_Set_is_current_user( + _In_ bool isCurrentUser + ) +{ + m_isCurrentUser = isCurrentUser; +} + +bool +multiplayer_session_member::initialize_requested() const +{ + return m_initialize; +} + +const web::json::value& +multiplayer_session_member::matchmaking_result_server_measurements_json() const +{ + return m_matchmakingResultServerMeasurementsJson; +} + +const web::json::value& +multiplayer_session_member::member_server_measurements_json() const +{ + return m_memberServerMeasurementsJson; +} + +const std::vector>& +multiplayer_session_member::members_in_group() const +{ + return m_membersInGroup; +} + + +std::error_code +multiplayer_session_member::set_members_list( + _In_ std::vector> members + ) +{ + std::vector> membersInGroup; + for (const uint32_t memberIndex : m_membersInGroupIndices) + { + for (const auto& member : members) + { + if (member->member_id() == memberIndex) + { + membersInGroup.push_back(member); + break; + } + } + } + + m_membersInGroup = membersInGroup; + + return convert_measure_json_to_vector(); +} + +std::shared_ptr> +multiplayer_session_member::member_measurements() const +{ + return m_memberMeasurements; +} + +const string_t& +multiplayer_session_member::device_token() const +{ + return m_deviceToken; +} + +network_address_translation_setting +multiplayer_session_member::nat() const +{ + return m_nat; +} + +uint32_t +multiplayer_session_member::active_title_id() const +{ + return m_activeTitleId; +} + +uint32_t +multiplayer_session_member::initialization_episode() const +{ + return m_initializationEpisode; +} + +const utility::datetime& +multiplayer_session_member::join_time() const +{ + return m_joinTime; +} + +multiplayer_measurement_failure +multiplayer_session_member::initialization_failure_cause() const +{ + return m_initializationFailure; +} + +const std::vector& +multiplayer_session_member::groups() const +{ + return m_groups; +} + +void +multiplayer_session_member::set_groups( + _In_ std::vector groups + ) +{ + m_groups = std::move(groups); + m_memberRequest->set_groups(m_groups); +} + + +const std::vector& +multiplayer_session_member::encounters() const +{ + return m_encounters; +} + +void +multiplayer_session_member::set_encounters( + _In_ std::vector encounters + ) +{ + m_encounters = std::move(encounters); + m_memberRequest->set_encounters(m_encounters); +} + + +std::shared_ptr +multiplayer_session_member::_Session_request() const +{ + return m_sessionRequest; +} + +void +multiplayer_session_member::_Set_session_request( + _In_ std::shared_ptr sessionRequest + ) +{ + m_sessionRequest = std::move(sessionRequest); +} + + +std::shared_ptr +multiplayer_session_member::_Member_request() const +{ + return m_memberRequest; +} + +void +multiplayer_session_member::_Set_member_request( + _In_ std::shared_ptr multiplayerSessionMemberRequest + ) +{ + m_memberRequest = multiplayerSessionMemberRequest; +} + +std::error_code +multiplayer_session_member::_Set_current_user_status( + _In_ multiplayer_session_member_status status + ) +{ + XSAPI_ASSERT(m_isCurrentUser); + if (status != multiplayer_session_member_status::active && status != multiplayer_session_member_status::inactive) + { + return xbox_live_error_code::invalid_argument; + } + + m_isActive = (status == multiplayer_session_member_status::active); + m_memberRequest->set_is_active(m_isActive); + m_memberRequest->set_write_is_active(true); + + return xbox_live_error_code::no_error; +} + +void +multiplayer_session_member::_Set_current_user_members_in_group( + _In_ std::vector> membersInGroup + ) +{ + m_membersInGroupIndices.clear(); + for (const auto& member : membersInGroup) + { + m_membersInGroupIndices.push_back(member->member_id()); + } + m_membersInGroup = std::move(membersInGroup); + m_memberRequest->set_write_members_in_group(true); + m_memberRequest->set_members_in_group(m_membersInGroupIndices); +} + +std::error_code +multiplayer_session_member::_Set_member_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + if (!m_isCurrentUser) + { + return xbox_live_error_code::logic_error; + } + + std::lock_guard lock(m_lock); + + web::json::value customProperty = web::json::value::null(); + if (!valueJson.is_null()) + { + customProperty = std::move(valueJson); + } + + if (m_memberRequest->custom_properties().is_null()) + { + m_memberRequest->set_custom_properties(web::json::value::object()); + } + + m_memberRequest->set_custom_properties_property(name, customProperty); + + return xbox_live_error_code::no_error; +} + +void +multiplayer_session_member::_Delete_custom_property_json( + _In_ const string_t& name + ) +{ + _Set_member_custom_property_json(name, web::json::value::null()); +} + +void +multiplayer_session_member::_Set_current_user_quality_of_service_measurements( + _In_ std::shared_ptr> qualityOfServiceMeasurements + ) +{ + for (const auto& measurement : *qualityOfServiceMeasurements) + { + web::json::value jsonMeasurement; + jsonMeasurement[_T("latency")] = measurement.latency().count(); + jsonMeasurement[_T("bandwidthDown")] = measurement.bandwidth_down_in_kilobits_per_second(); + jsonMeasurement[_T("bandwidthUp")] = measurement.bandwidth_up_in_kilobits_per_second(); + jsonMeasurement[_T("custom")] = measurement.custom_json(); + + m_memberMeasurementsJson[measurement.member_device_token().c_str()] = jsonMeasurement; + } + + m_memberMeasurements = qualityOfServiceMeasurements; + m_memberRequest->set_write_member_measurements_json(true); + m_memberRequest->set_member_measurements_json(m_memberMeasurementsJson); +} + +void +multiplayer_session_member::_Set_current_user_quality_of_service_server_measurements_json( + _In_ web::json::value serverMeasurementsJson + ) +{ + m_memberServerMeasurementsJson = serverMeasurementsJson; + m_memberRequest->set_write_member_server_measurements_json(true); + m_memberRequest->set_member_server_measurements_json(m_memberServerMeasurementsJson); +} + +multiplayer_session_change_types +multiplayer_session_member::_Subscribed_change_types() const +{ + return m_subscribedChangeTypes; +} + +void +multiplayer_session_member::_Set_session_change_subscription( + _In_ multiplayer_session_change_types changeTypes, + _In_ const string_t& subscriptionId + ) +{ + m_subscribedChangeTypes = changeTypes; + m_memberRequest->set_subscribed_change_types(changeTypes); + m_memberRequest->set_subscription_id(subscriptionId); + m_memberRequest->set_write_subscribed_change_types(true); +} + +void +multiplayer_session_member::_Set_arbitration_results( + _In_ const std::unordered_map& results + ) +{ + m_results = results; + m_memberRequest->set_results(results); +} + +void +multiplayer_session_member::_Set_rta_connection_id( + _In_ const string_t& rtaConnectionId + ) +{ + m_memberRequest->set_rta_connection_id(std::move(rtaConnectionId)); +} + +const multiplayer_session_reference& +multiplayer_session_member::tournament_team_session_reference() const +{ + return m_tournamentTeamSessionRef; +} + +network_address_translation_setting +multiplayer_session_member::_Convert_string_to_multiplayer_nat_setting( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return network_address_translation_setting::unknown; + } + else if (utils::str_icmp(value, _T("strict")) == 0) + { + return network_address_translation_setting::strict; + } + else if (utils::str_icmp(value, _T("moderate")) == 0) + { + return network_address_translation_setting::moderate; + } + else if (utils::str_icmp(value, _T("open")) == 0) + { + return network_address_translation_setting::open; + } + + return network_address_translation_setting::unknown; +} + +multiplayer_measurement_failure +multiplayer_session_member::_Convert_string_to_multiplayer_metric_stage( + _In_ const string_t& value + ) +{ + if (value.empty()) + { + return multiplayer_measurement_failure::none; + } + else if (utils::str_icmp(value, _T("bandwidthUp")) == 0) + { + return multiplayer_measurement_failure::bandwidth_up; + } + else if (utils::str_icmp(value, _T("bandwidthDown")) == 0) + { + return multiplayer_measurement_failure::bandwidth_down; + } + else if (utils::str_icmp(value, _T("latency")) == 0) + { + return multiplayer_measurement_failure::latency; + } + else if (utils::str_icmp(value, _T("timeout")) == 0) + { + return multiplayer_measurement_failure::timeout; + } + else if (utils::str_icmp(value, _T("group")) == 0) + { + return multiplayer_measurement_failure::group; + } + else if (utils::str_icmp(value, _T("network")) == 0) + { + return multiplayer_measurement_failure::network; + } + else if (utils::str_icmp(value, _T("episode")) == 0) + { + return multiplayer_measurement_failure::episode; + } + + return multiplayer_measurement_failure::unknown; +} + +std::error_code +multiplayer_session_member::convert_measure_json_to_vector() +{ + m_memberMeasurements->clear(); + if (!m_memberMeasurementsJson.is_null()) + { + for (const auto& memberPair : m_memberMeasurementsJson.as_object()) + { + auto multiplayerQOSMeasurements = multiplayer_quality_of_service_measurements::_Deserialize(memberPair.second); + if (multiplayerQOSMeasurements.err()) return multiplayerQOSMeasurements.err(); + + multiplayer_quality_of_service_measurements measurements = multiplayerQOSMeasurements.payload(); + measurements._Set_member_device_token(memberPair.first); + m_memberMeasurements->push_back(measurements); + } + } + + return xbox_live_error_code::no_error; +} + +multiplayer_session_change_types +multiplayer_session_member::_Convert_string_vector_to_change_types( + std::vector changeTypeList + ) +{ + uint32_t resultingChangeTypes = static_cast(multiplayer_session_change_types::none); + + for(auto& current : changeTypeList) + { + if (utils::str_icmp(current, _T("everything")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::everything; + } + else if (utils::str_icmp(current, _T("host")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::host_device_token_change; + } + else if (utils::str_icmp(current, _T("initialization")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::initialization_state_change; + } + else if (utils::str_icmp(current, _T("matchmakingStatus")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::matchmaking_status_change; + } + else if (utils::str_icmp(current, _T("membersList")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::member_list_change; + } + else if (utils::str_icmp(current, _T("membersStatus")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::member_status_change; + } + else if (utils::str_icmp(current, _T("joinability")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::session_joinability_change; + } + else if (utils::str_icmp(current, _T("customProperty")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::custom_property_change; + } + else if (utils::str_icmp(current, _T("membersCustomProperty")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::member_custom_property_change; + } + else if (utils::str_icmp(current, _T("tournaments")) == 0) + { + resultingChangeTypes |= multiplayer_session_change_types::tournament_property_change; + } + } + + return static_cast(resultingChangeTypes); + +} + +tournament_arbitration_status +multiplayer_session_member::_Convert_string_to_arbitration_status( + _In_ const string_t& value +) +{ + if (utils::str_icmp(value, _T("waiting")) == 0) + { + return tournament_arbitration_status::waiting; + } + else if (utils::str_icmp(value, _T("inprogress")) == 0) + { + return tournament_arbitration_status::in_progress; + } + else if (utils::str_icmp(value, _T("complete")) == 0) + { + return tournament_arbitration_status::complete; + } + else if (utils::str_icmp(value, _T("playing")) == 0) + { + return tournament_arbitration_status::playing; + } + + return tournament_arbitration_status::incomplete; +} + +xbox_live_result +multiplayer_session_member::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_member returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + + web::json::value constantsJson = utils::extract_json_field(json, _T("constants"), errc, true); + web::json::value constantsSystemJson = utils::extract_json_field(constantsJson, _T("system"), errc, true); + web::json::value constantsSystemMatchmakingResultJson = utils::extract_json_field(constantsSystemJson, _T("matchmakingResult"), errc, false); + + web::json::value propertiesJson = utils::extract_json_field(json, _T("properties"), errc, true); + web::json::value propertiesSystemJson = utils::extract_json_field(propertiesJson, _T("system"), errc, true); + web::json::value propertiesSystemSubscriptionJson = utils::extract_json_field(propertiesSystemJson, _T("subscription"), errc, false); + + returnResult.m_isReserved = utils::extract_json_bool(json, _T("reserved"), errc); + returnResult.m_xboxUserId = utils::extract_json_string(constantsSystemJson, _T("xuid"), errc); + returnResult.m_initialize = utils::extract_json_bool(constantsSystemJson, _T("initialize"), errc); + returnResult.m_customPropertiesJson = utils::extract_json_field(propertiesJson, _T("custom"), errc, false); + returnResult.m_customConstantsJson = utils::extract_json_field(constantsJson, _T("custom"), errc, false); + returnResult.m_teamId = utils::extract_json_string(constantsSystemJson, _T("team"), errc); + returnResult.m_arbitrationStatus = _Convert_string_to_arbitration_status(utils::extract_json_string(constantsSystemJson, _T("arbitrationStatus"), errc)); + returnResult.m_gamertag = utils::extract_json_string(json, _T("gamertag"), errc); + returnResult.m_deviceToken = utils::extract_json_string(json, _T("deviceToken"), errc); + returnResult.m_nat = _Convert_string_to_multiplayer_nat_setting(utils::extract_json_string(json, _T("nat"), errc)); + returnResult.m_isTurnAvailable = utils::extract_json_bool(json, _T("turn"), errc); + returnResult.m_isActive = utils::extract_json_bool(propertiesSystemJson, _T("active"), errc); + returnResult.m_isReady = utils::extract_json_bool(propertiesSystemJson, _T("ready"), errc); + returnResult.m_secureDeviceAddressBase64 = utils::extract_json_string(propertiesSystemJson, _T("secureDeviceAddress"), errc); + returnResult.m_subscribedChangeTypes = _Convert_string_vector_to_change_types( + utils::extract_json_vector(utils::json_string_extractor, propertiesSystemSubscriptionJson, _T("changeTypes"), errc, false) + ); + + returnResult.m_memberServerMeasurementsJson = utils::extract_json_field(propertiesSystemJson, _T("serverMeasurements"), errc, false); + returnResult.m_memberMeasurementsJson = utils::extract_json_field(propertiesSystemJson, _T("measurements"), errc, false); + returnResult.m_membersInGroupIndices = utils::extract_json_vector(utils::json_int_extractor, propertiesSystemJson, _T("initializationGroup"), errc, false); + + web::json::value rolesJson = utils::extract_json_field(json, _T("roles"), errc, false); + if (!rolesJson.is_null() && rolesJson.is_object()) + { + web::json::object rolesObj = rolesJson.as_object(); + for (const auto& role : rolesObj) + { + returnResult.m_roles[role.first] = role.second.as_string(); + } + } + + web::json::value registrationJson = utils::extract_json_field(propertiesSystemJson, _T("registration"), errc, false); + if (!registrationJson.is_null()) + { + returnResult.m_registrationState = multiplayer_session_tournaments_server::_Convert_string_to_registration_result( + utils::extract_json_string(registrationJson, _T("state"), errc) + ); + returnResult.m_registrationReason = multiplayer_session_tournaments_server::_Convert_string_to_registration_reason( + utils::extract_json_string(registrationJson, _T("reason"), errc) + ); + } + + web::json::value arbitrationJson = utils::extract_json_field(propertiesSystemJson, _T("arbitration"), errc, false); + if (!arbitrationJson.is_null()) + { + web::json::value resultsJson = utils::extract_json_field(arbitrationJson, _T("results"), errc, false); + if (!resultsJson.is_null() && resultsJson.is_object()) + { + web::json::object resultsObj = resultsJson.as_object(); + for (const auto& result : resultsObj) + { + const auto& team = result.first; + auto tournamentTeamResult = tournament_team_result::_Deserialize(result.second); + if (tournamentTeamResult.err()) + { + errc = tournamentTeamResult.err(); + } + returnResult.m_results[team] = tournamentTeamResult.payload(); + } + } + } + + auto teamJson = utils::extract_json_field(constantsSystemJson, _T("teamSessionRef"), errc, false); + auto teamSessionResult = multiplayer_session_reference::_Deserialize(teamJson); + if (teamSessionResult.err()) + { + errc = teamSessionResult.err(); + } + returnResult.m_tournamentTeamSessionRef = teamSessionResult.payload(); + + auto titleIdString = utils::extract_json_string(json, _T("activeTitleId"), errc); + if (!titleIdString.empty()) + { + returnResult.m_activeTitleId = utils::string_t_to_uint32(titleIdString); + } + + returnResult.m_joinTime = utils::extract_json_time(json, _T("joinTime"), errc); + returnResult.m_initializationFailure = _Convert_string_to_multiplayer_metric_stage(utils::extract_json_string(json, _T("initializationFailure"), errc)); + returnResult.m_initializationEpisode = utils::extract_json_int(json, _T("initializationEpisode"), errc); + returnResult.m_matchmakingResultServerMeasurementsJson = utils::extract_json_field(constantsSystemMatchmakingResultJson, _T("serverMeasurements"), errc, false); + + return returnResult; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_member_request.cpp b/Source/Services/Multiplayer/multiplayer_session_member_request.cpp new file mode 100644 index 00000000..21c4054d --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_member_request.cpp @@ -0,0 +1,576 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/multiplayer.h" +#include "utils.h" +#include "multiplayer_internal.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_member_request::multiplayer_session_member_request(): + m_writeRequest(false), + m_writeConstants(false), + m_writeIsActive(false), + m_isActive(false), + m_writeSecureDeviceAddressBase64(false), + m_addInitializePropertyToRequest(false), + m_initializeRequested(false), + m_writeMemberMeasurementsJson(false), + m_writeMemberServerMeasurementsJson(false), + m_writeMembersInGroup(false), + m_writeSubscribedChangeType(false), + m_changeTypes(multiplayer_session_change_types::none) +{ +} + +multiplayer_session_member_request::multiplayer_session_member_request( + _In_ bool writeRequest, + _In_ string_t memberId, + _In_ string_t xboxUserId, + _In_ web::json::value memberConstants, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializeRequested + ) : + m_writeRequest(writeRequest), + m_memberId(std::move(memberId)), + m_xboxUserId(std::move(xboxUserId)), + m_customConstants(std::move(memberConstants)), + m_addInitializePropertyToRequest(addInitializePropertyToRequest), + m_initializeRequested(initializeRequested), + m_writeConstants(false), + m_writeIsActive(false), + m_isActive(false), + m_writeSecureDeviceAddressBase64(false), + m_writeMemberMeasurementsJson(false), + m_writeMemberServerMeasurementsJson(false), + m_writeMembersInGroup(false), + m_writeSubscribedChangeType(false), + m_changeTypes(multiplayer_session_change_types::none) +{ + m_writeConstants = !m_customConstants.is_null(); +} + +bool +multiplayer_session_member_request::write_request() const +{ + return m_writeRequest; +} + +bool +multiplayer_session_member_request::write_constants() const +{ + return m_writeConstants; +} + +const string_t& +multiplayer_session_member_request::member_id() const +{ + return m_memberId; +} + +const web::json::value& +multiplayer_session_member_request::custom_constants() const +{ + return m_customConstants; +} + +const web::json::value& +multiplayer_session_member_request::custom_properties() const +{ + return m_customProperties; +} + +void +multiplayer_session_member_request::set_custom_properties( + _In_ web::json::value customProperties + ) +{ + m_customProperties = std::move(customProperties); +} + +std::error_code +multiplayer_session_member_request::set_custom_properties_property( + _In_ string_t name, + _In_ web::json::value customProperty + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + m_customProperties[name.c_str()] = customProperty; + + return xbox_live_error_code::no_error; +} + +const string_t& +multiplayer_session_member_request::xbox_user_id() const +{ + return m_xboxUserId; +} + +bool +multiplayer_session_member_request::is_active() const +{ + return m_isActive; +} + +void +multiplayer_session_member_request::set_is_active( + _In_ bool isActive + ) +{ + m_isActive = isActive; +} + +bool +multiplayer_session_member_request::write_is_active() const +{ + return m_writeIsActive; +} + +void +multiplayer_session_member_request::set_write_is_active( + _In_ bool writeIsActive + ) +{ + m_writeIsActive = writeIsActive; +} + +const string_t& +multiplayer_session_member_request::service_device_address_base64() const +{ + return m_serviceDeviceAddressBase64; +} + +void +multiplayer_session_member_request::set_secure_device_address_base64( + _In_ string_t deviceAddress + ) +{ + m_serviceDeviceAddressBase64 = std::move(deviceAddress); +} + +bool +multiplayer_session_member_request::write_secure_device_address_base64() const +{ + return m_writeSecureDeviceAddressBase64; +} + +void +multiplayer_session_member_request::set_write_secure_device_address_base64( + _In_ bool shouldWrite + ) +{ + m_writeSecureDeviceAddressBase64 = shouldWrite; +} + +void +multiplayer_session_member_request::set_role_info( + _In_ const std::unordered_map& roles + ) +{ + m_roles = roles; +} + +bool +multiplayer_session_member_request::does_initialized_requested_exist() const +{ + return m_addInitializePropertyToRequest; +} + +bool +multiplayer_session_member_request::initialize_requested() const +{ + return m_initializeRequested; +} + +bool +multiplayer_session_member_request::write_member_measurements_json() const +{ + return m_writeMemberMeasurementsJson; +} + +void +multiplayer_session_member_request::set_write_member_measurements_json( + _In_ bool shouldWrite + ) +{ + m_writeMemberMeasurementsJson = shouldWrite; +} + +void +multiplayer_session_member_request::set_member_measurements_json( + _In_ web::json::value memberMeasurements + ) +{ + m_memberMeasurementsJson = std::move(memberMeasurements); +} + +const web::json::value& +multiplayer_session_member_request::member_measurements_json() const +{ + return m_memberMeasurementsJson; +} + +const web::json::value& +multiplayer_session_member_request::member_server_measurements_json() const +{ + return m_memberServerMeasurementsJson; +} + +void +multiplayer_session_member_request::set_member_server_measurements_json( + _In_ web::json::value json + ) +{ + m_memberServerMeasurementsJson = std::move(json); +} + +bool +multiplayer_session_member_request::write_member_server_measurements_json() const +{ + return m_writeMemberServerMeasurementsJson; +} + +void +multiplayer_session_member_request::set_write_member_server_measurements_json( + _In_ bool shouldWrite + ) +{ + m_writeMemberServerMeasurementsJson = shouldWrite; +} + +std::vector +multiplayer_session_member_request::members_in_group() const +{ + return m_membersInGroup; +} + +void +multiplayer_session_member_request::set_members_in_group( + _In_ std::vector membersInGroup + ) +{ + m_membersInGroup = std::move(membersInGroup); +} + +bool +multiplayer_session_member_request::write_members_in_group() const +{ + return m_writeMembersInGroup; +} + +void +multiplayer_session_member_request::set_write_members_in_group( + _In_ bool writeMembersInGroup + ) +{ + m_writeMembersInGroup = writeMembersInGroup; +} + +const std::vector& +multiplayer_session_member_request::groups() const +{ + return m_groups; +} + +void +multiplayer_session_member_request::set_groups( + _In_ std::vector groups + ) +{ + m_groups = std::move(groups); +} + +const std::vector& +multiplayer_session_member_request::encounters() const +{ + return m_encounters; +} + +void +multiplayer_session_member_request::set_encounters( + _In_ std::vector encounters + ) +{ + m_encounters = std::move(encounters); +} + +bool +multiplayer_session_member_request::write_subscribed_change_types() const +{ + return m_writeSubscribedChangeType; +} + +void +multiplayer_session_member_request::set_write_subscribed_change_types( + _In_ bool shouldWrite + ) +{ + m_writeSubscribedChangeType = shouldWrite; +} + +multiplayer_session_change_types +multiplayer_session_member_request::subscribed_change_types() const +{ + return m_changeTypes; +} + +void +multiplayer_session_member_request::set_subscribed_change_types( + _In_ multiplayer_session_change_types changeTypes + ) +{ + m_changeTypes = changeTypes; +} + +const string_t& +multiplayer_session_member_request::subscription_id() const +{ + return m_subscriptionId; +} + +void +multiplayer_session_member_request::set_subscription_id( + _In_ string_t subscriptionId + ) +{ + m_subscriptionId = std::move(subscriptionId); +} + +const string_t& +multiplayer_session_member_request::rta_connection_id() const +{ + return m_rtaConnectionId; +} + +void +multiplayer_session_member_request::set_rta_connection_id( + _In_ string_t connectionId + ) +{ + m_rtaConnectionId = connectionId; +} + +const std::unordered_map& +multiplayer_session_member_request::results() const +{ + return m_results; +} + +void +multiplayer_session_member_request::set_result( + _In_ const string_t& team, + _In_ const tournament_team_result& result + ) +{ + if (!m_results.insert(std::make_pair(team, result)).second) + { + m_results[team] = result; + } +} + +void +multiplayer_session_member_request::set_results( + _In_ const std::unordered_map& results + ) +{ + m_results = results; +} + +std::vector +multiplayer_session_member_request::get_vector_view_for_change_types( + _In_ multiplayer_session_change_types changeTypes + ) +{ + std::vector resultVector; + if ((changeTypes & static_cast(multiplayer_session_change_types::everything)) == multiplayer_session_change_types::everything) + { + resultVector.push_back(_T("everything")); + } + if ((changeTypes & multiplayer_session_change_types::host_device_token_change) == multiplayer_session_change_types::host_device_token_change) + { + resultVector.push_back(_T("host")); + } + if ((changeTypes & multiplayer_session_change_types::initialization_state_change) == multiplayer_session_change_types::initialization_state_change) + { + resultVector.push_back(_T("initialization")); + } + if ((changeTypes & multiplayer_session_change_types::matchmaking_status_change) == multiplayer_session_change_types::matchmaking_status_change) + { + resultVector.push_back(_T("matchmakingStatus")); + } + if ((changeTypes & multiplayer_session_change_types::tournament_property_change) == multiplayer_session_change_types::tournament_property_change) + { + resultVector.push_back(_T("tournaments")); + } + if ((changeTypes & multiplayer_session_change_types::member_list_change) == multiplayer_session_change_types::member_list_change) + { + resultVector.push_back(_T("membersList")); + } + if ((changeTypes & multiplayer_session_change_types::member_status_change) == multiplayer_session_change_types::member_status_change) + { + resultVector.push_back(_T("membersStatus")); + } + if ((changeTypes & multiplayer_session_change_types::session_joinability_change) == multiplayer_session_change_types::session_joinability_change) + { + resultVector.push_back(_T("joinability")); + } + if ((changeTypes & multiplayer_session_change_types::custom_property_change) == multiplayer_session_change_types::custom_property_change) + { + resultVector.push_back(_T("customProperty")); + } + if ((changeTypes & multiplayer_session_change_types::member_custom_property_change) == multiplayer_session_change_types::member_custom_property_change) + { + resultVector.push_back(_T("membersCustomProperty")); + } + + return resultVector; +} + +web::json::value +multiplayer_session_member_request::serialize() +{ + web::json::value serializedObject; + if (m_writeRequest || m_writeConstants) + { + web::json::value systemConstantsJson; + systemConstantsJson[_T("xuid")] = web::json::value::string(m_xboxUserId); + + if (m_addInitializePropertyToRequest) + { + systemConstantsJson[_T("initialize")] = web::json::value(m_initializeRequested); + } + + web::json::value constantsJson; + constantsJson[_T("system")] = systemConstantsJson; + if (m_writeConstants && !m_customConstants.is_null()) + { + constantsJson[_T("custom")] = m_customConstants; + } + serializedObject[_T("constants")] = std::move(constantsJson); + } + + web::json::value propertiesJson; + web::json::value systemPropertiesJson; + + if (m_writeIsActive) + { + systemPropertiesJson[_T("active")] = web::json::value(m_isActive); + if (!m_isActive) + { + systemPropertiesJson[_T("ready")] = web::json::value(m_isActive); + } + else + { + if (!m_rtaConnectionId.empty()) + { + systemPropertiesJson[_T("connection")] = web::json::value::string(m_rtaConnectionId); + } + } + } + + if (m_roles.size() > 0) + { + web::json::value rolesJson; + for (const auto& role : m_roles) + { + rolesJson[role.first] = web::json::value::string(role.second); + } + serializedObject[_T("roles")] = rolesJson; + } + + if (m_writeSubscribedChangeType) + { + web::json::value subscriptionJson = web::json::value::null(); + + if (m_changeTypes != multiplayer_session_change_types::none) + { + subscriptionJson[_T("id")] = web::json::value::string(m_subscriptionId); + subscriptionJson[_T("changeTypes")] = utils::serialize_vector( + utils::json_string_serializer, + get_vector_view_for_change_types(m_changeTypes) + ); + } + + systemPropertiesJson[_T("subscription")] = subscriptionJson; + } + + if (m_results.size() > 0) + { + web::json::value arbitrationResultsJson; + for (const auto& result : m_results) + { + web::json::value teamResultJson; + teamResultJson[_T("outcome")] = web::json::value::string(multiplayer_service::_Convert_game_result_state_to_string(result.second.state())); + if (result.second.state() == tournament_game_result_state::rank) + { + teamResultJson[_T("ranking")] = web::json::value::number(result.second.ranking()); + } + arbitrationResultsJson[result.first] = teamResultJson; + } + systemPropertiesJson[_T("arbitration")][_T("results")] = arbitrationResultsJson; + } + + if (m_writeSecureDeviceAddressBase64) + { + systemPropertiesJson[_T("secureDeviceAddress")] = web::json::value::string(m_serviceDeviceAddressBase64); + } + + if (m_writeMembersInGroup) + { + systemPropertiesJson[_T("initializationGroup")] = utils::serialize_vector(utils::json_int_serializer, m_membersInGroup); + } + + if (!m_groups.empty()) + { + systemPropertiesJson[_T("groups")] = utils::serialize_vector(utils::json_string_serializer, m_groups); + } + + if (!m_encounters.empty()) + { + systemPropertiesJson[_T("encounters")] = utils::serialize_vector(utils::json_string_serializer, m_encounters); + } + + if (m_writeMemberMeasurementsJson) + { + systemPropertiesJson[_T("measurements")] = m_memberMeasurementsJson; + } + + if (m_writeMemberServerMeasurementsJson) + { + systemPropertiesJson[_T("serverMeasurements")] = m_memberServerMeasurementsJson; + } + + if (!systemPropertiesJson.is_null()) + { + propertiesJson[_T("system")] = std::move(systemPropertiesJson); + } + + if (!m_customProperties.is_null()) + { + propertiesJson[_T("custom")] = m_customProperties; + } + + if (!propertiesJson.is_null()) + { + serializedObject[_T("properties")] = std::move(propertiesJson); + } + + return serializedObject; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_properties.cpp b/Source/Services/Multiplayer/multiplayer_session_properties.cpp new file mode 100644 index 00000000..09394947 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_properties.cpp @@ -0,0 +1,325 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "utils.h" +#include "xsapi/multiplayer.h" +#include +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +std::mutex multiplayer_session_properties::m_lock; + +multiplayer_session_properties::multiplayer_session_properties() : + m_joinRestriction(multiplayer_session_restriction::unknown), + m_readRestriction(multiplayer_session_restriction::unknown) +{ + m_matchmakingTargetSessionConstants = web::json::value::object(); + m_customPropertiesJson = web::json::value::object(); + m_sessionRequest = std::make_shared(); +} + +multiplayer_session_properties& multiplayer_session_properties::_Deep_copy( + _In_ const multiplayer_session_properties& other + ) +{ + m_customPropertiesJson = other.m_customPropertiesJson; + m_keywords = other.m_keywords; + m_sessionOwnerIndices = other.m_sessionOwnerIndices; + m_turnCollection = other.m_turnCollection; + m_joinRestriction = other.m_joinRestriction; + m_matchmakingTargetSessionConstants = other.m_matchmakingTargetSessionConstants; + m_host = other.m_host; + m_serverConnectionString = other.m_serverConnectionString; + m_serverConnectionStringCandidates = other.m_serverConnectionStringCandidates; + m_closed = other.m_closed; + + // We will set this from the session deep_copy. + m_sessionRequest = std::make_shared(); + + return *this; +} + +const std::vector& +multiplayer_session_properties::keywords() const +{ + std::lock_guard lock(m_lock); + return m_keywords; +} + +void +multiplayer_session_properties::set_keywords( + _In_ std::vector keywords + ) +{ + std::lock_guard lock(m_lock); + m_keywords = std::move(keywords); + m_sessionRequest->set_session_properties_keywords(m_keywords); +} + +multiplayer_session_restriction +multiplayer_session_properties::join_restriction() const +{ + std::lock_guard lock(m_lock); + return m_joinRestriction; +} + +std::error_code +multiplayer_session_properties::set_join_restriction( + _In_ multiplayer_session_restriction joinRestriction + ) +{ + std::lock_guard lock(m_lock); + if (joinRestriction < multiplayer_session_restriction::none || + joinRestriction > multiplayer_session_restriction::followed) + { + return xbox_live_error_code::invalid_argument; + } + + m_joinRestriction = joinRestriction; + m_sessionRequest->set_join_restriction(m_joinRestriction); + return xbox_live_error_code::no_error; +} + +multiplayer_session_restriction +multiplayer_session_properties::read_restriction() const +{ + std::lock_guard lock(m_lock); + return m_readRestriction; +} + +std::error_code +multiplayer_session_properties::set_read_restriction( + _In_ multiplayer_session_restriction readRestriction + ) +{ + std::lock_guard lock(m_lock); + if (readRestriction < multiplayer_session_restriction::none || + readRestriction > multiplayer_session_restriction::followed) + { + return xbox_live_error_code::invalid_argument; + } + + m_readRestriction = std::move(readRestriction); + m_sessionRequest->set_read_restriction(m_readRestriction); + return xbox_live_error_code::no_error; +} + +const std::vector>& +multiplayer_session_properties::turn_collection() const +{ + std::lock_guard lock(m_lock); + return m_turnCollection; +} + +const web::json::value& +multiplayer_session_properties::matchmaking_target_session_constants_json() const +{ + std::lock_guard lock(m_lock); + return m_matchmakingTargetSessionConstants; +} + +const web::json::value& +multiplayer_session_properties::session_custom_properties_json() const +{ + std::lock_guard lock(m_lock); + return m_customPropertiesJson; +} + +const string_t& +multiplayer_session_properties::matchmaking_server_connection_string() const +{ + return m_serverConnectionString; +} + +const std::vector& +multiplayer_session_properties::server_connection_string_candidates() const +{ + std::lock_guard lock(m_lock); + return m_serverConnectionStringCandidates; +} + +const std::vector& +multiplayer_session_properties::session_owner_indices() const +{ + std::lock_guard lock(m_lock); + return m_sessionOwnerIndices; +} + +const string_t& +multiplayer_session_properties::host_device_token() const +{ + return m_host; +} + +bool +multiplayer_session_properties::closed() const +{ + std::lock_guard lock(m_lock); + return m_closed; +} + +void +multiplayer_session_properties::_Initialize( + _In_ std::shared_ptr sessionRequest, + _In_ std::vector> members + ) +{ + m_sessionRequest = std::move(sessionRequest); + std::vector> turnCollection; + if (!m_turnIndexList.empty() && !members.empty()) + { + for (uint32_t memberIndex : m_turnIndexList) + { + for (const auto& member : members) + { + if (member->member_id() == memberIndex) + { + turnCollection.push_back(member); + break; + } + } + } + } + m_turnCollection = turnCollection; +} + +std::error_code +multiplayer_session_properties::set_turn_collection( + _In_ std::vector> turnCollection + ) +{ + if (turnCollection.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + std::lock_guard lock(m_lock); + std::vector turnIndexVector; + + for (const auto& member : turnCollection) + { + turnIndexVector.push_back(member->member_id()); + } + m_sessionRequest->set_session_properties_turns(turnIndexVector); + m_turnCollection = std::move(turnCollection); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session_properties::_Set_session_custom_property_json( + _In_ const string_t& name, + _In_ const web::json::value& valueJson + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + std::lock_guard lock(m_lock); + web::json::value customProperty; + if (!valueJson.is_null()) + { + customProperty = valueJson; + } + + if (m_sessionRequest->session_properties_custom_properties().is_null()) + { + m_sessionRequest->set_session_custom_properties(web::json::value()); + } + + web::json::value customProperties = m_sessionRequest->session_properties_custom_properties(); + if (customProperty.is_null()) + { + customProperties[name] = web::json::value::null(); + m_sessionRequest->set_session_custom_properties(customProperties); + } + else + { + customProperties[name] = customProperty; + } + + m_sessionRequest->set_session_custom_properties(customProperties); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session_properties::_Delete_session_custom_property_json( + _In_ const string_t& name + ) +{ + if (name.empty()) + { + return xbox_live_error_code::invalid_argument; + } + + _Set_session_custom_property_json(name, web::json::value::null()); + + return xbox_live_error_code::no_error; +} + +std::error_code +multiplayer_session_properties::_Set_matchmaking_target_session_constants_json( + _In_ const web::json::value& matchmakingTargetSessionConstantsJson + ) +{ + std::lock_guard lock(m_lock); + m_sessionRequest->set_write_matchmaking_session_constants(true); + m_matchmakingTargetSessionConstants = matchmakingTargetSessionConstantsJson; + m_sessionRequest->set_session_properties_target_sessions_constants( m_matchmakingTargetSessionConstants ); + + return xbox_live_error_code::no_error; +} + +xbox_live_result +multiplayer_session_properties::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_properties returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value systemJson = utils::extract_json_field(json, _T("system"), errc, true); + web::json::value systemMatchmakingJson = utils::extract_json_field(systemJson, _T("matchmaking"), errc, false); + web::json::value systemMatchmakingClientResultJson = utils::extract_json_field(systemMatchmakingJson, _T("clientResult"), errc, false); + + returnResult.m_keywords = utils::extract_json_vector(utils::json_string_extractor, systemJson, _T("keywords"), errc, false); + returnResult.m_sessionOwnerIndices = utils::extract_json_vector(utils::json_int_extractor, systemJson, _T("owners"), errc, false); + returnResult.m_turnIndexList = utils::extract_json_vector(utils::json_int_extractor, systemJson, _T("turn"), errc, false); + string_t joinRestrictionString = utils::extract_json_string(systemJson, _T("joinRestriction"), errc); + string_t readRestrictionString = utils::extract_json_string(systemJson, _T("readRestriction"), errc); + if (!joinRestrictionString.empty()) + { + returnResult.m_joinRestriction = multiplayer_session_states::_Convert_string_to_multiplayer_session_restriction(joinRestrictionString); + } + + if (!readRestrictionString.empty()) + { + returnResult.m_readRestriction = multiplayer_session_states::_Convert_string_to_multiplayer_session_restriction(readRestrictionString); + } + + returnResult.m_closed = utils::extract_json_bool(systemJson, _T("closed"), errc); + + returnResult.m_matchmakingTargetSessionConstants = utils::extract_json_field(systemMatchmakingJson, _T("targetSessionConstants"), errc, false); + returnResult.m_customPropertiesJson = utils::extract_json_field(json, _T("custom"), errc, false); + + returnResult.m_host = utils::extract_json_string(systemJson, _T("host"), errc); + returnResult.m_serverConnectionString = utils::extract_json_string(systemMatchmakingJson, _T("serverConnectionString"), errc); + returnResult.m_serverConnectionStringCandidates = utils::extract_json_vector(utils::json_string_extractor, systemJson, _T("serverConnectionStringCandidates"), errc, false); + + return xbox_live_result(returnResult, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_reference.cpp b/Source/Services/Multiplayer/multiplayer_session_reference.cpp new file mode 100644 index 00000000..a768c0dc --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_reference.cpp @@ -0,0 +1,146 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "utils.h" +#include "user_context.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_reference::multiplayer_session_reference() +{ +} + +multiplayer_session_reference::multiplayer_session_reference( + _In_ string_t serviceConfigurationId, + _In_ string_t sessionTemplateName, + _In_ string_t sessionName + ) +{ + XSAPI_ASSERT(!serviceConfigurationId.empty()); + XSAPI_ASSERT(!sessionTemplateName.empty()); + XSAPI_ASSERT(!sessionName.empty()); + + m_serviceConfigurationId = std::move(serviceConfigurationId); + m_sessionTemplateName = std::move(sessionTemplateName); + m_sessionName = std::move(sessionName); +} + +#ifndef DEFAULT_MOVE_ENABLED +_XSAPIIMP multiplayer_session_reference::multiplayer_session_reference(multiplayer_session_reference&& other) +{ + *this = std::move(other); +} + +_XSAPIIMP multiplayer_session_reference& multiplayer_session_reference::operator= (multiplayer_session_reference&& other) +{ + if (this != &other) + { + m_serviceConfigurationId = std::move(other.service_configuration_id()); + m_sessionName = std::move(other.session_name()); + m_sessionTemplateName = std::move(other.session_template_name()); + } + + return *this; +} +#endif + +const string_t& +multiplayer_session_reference::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const string_t& +multiplayer_session_reference::session_template_name() const +{ + return m_sessionTemplateName; +} + +const string_t& +multiplayer_session_reference::session_name() const +{ + return m_sessionName; +} + +bool +multiplayer_session_reference::is_null() const +{ + return m_serviceConfigurationId.empty() || m_sessionTemplateName.empty() || m_sessionName.empty(); +} + +web::json::value +multiplayer_session_reference::_Serialize() const +{ + web::json::value serializedObject; + + serializedObject[_T("scid")] = web::json::value::string(m_serviceConfigurationId); + serializedObject[_T("templateName")] = web::json::value::string(m_sessionTemplateName); + serializedObject[_T("name")] = web::json::value::string(m_sessionName); + + return serializedObject; +} + +string_t +multiplayer_session_reference::to_uri_path() const +{ + stringstream_t uriStream; + uriStream << "/serviceconfigs/"; + uriStream << m_serviceConfigurationId; + uriStream << "/sessiontemplates/"; + uriStream << m_sessionTemplateName; + uriStream << "/sessions/"; + uriStream << m_sessionName; + + return uriStream.str(); +} + +multiplayer_session_reference +multiplayer_session_reference::parse_from_uri_path( + _In_ const string_t& path + ) +{ + std::vector pathComponents = utils::string_split(path, L'/'); + + // / 0 / 1 / 2 / 3 / 4 / 5 + // /serviceconfigs/{scid}/sessiontemplates/{session-template-name}/sessions/{session-name} + if (pathComponents.size() > 5) + { + return multiplayer_session_reference( + pathComponents.at(1).c_str(), + pathComponents.at(3).c_str(), + pathComponents.at(5).c_str() + ); + } + else + { + return multiplayer_session_reference(); + } +} + +xbox_live_result +multiplayer_session_reference::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null() || json.size() == 0) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto response = multiplayer_session_reference( + utils::extract_json_string(json, _T("scid"), errc, true), + utils::extract_json_string(json, _T("templateName"), errc, true), + utils::extract_json_string(json, _T("name"), errc, true) + ); + + return xbox_live_result(response, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_request.cpp b/Source/Services/Multiplayer/multiplayer_session_request.cpp new file mode 100644 index 00000000..ccc169b4 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_request.cpp @@ -0,0 +1,688 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "user_context.h" +#include "xsapi/multiplayer.h" +#include "utils.h" +#include +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +std::shared_ptr multiplayer_session_request::create_deep_copy() +{ + auto copy = std::make_shared(); + copy->deep_copy_from(*this); + return copy; +} + +void multiplayer_session_request::deep_copy_from( + _In_ const multiplayer_session_request& other + ) +{ + xbox::services::system::xbox_live_mutex& lock = const_cast(other).m_lock; + std::lock_guard guard(lock.get()); + + m_sessionReference = other.m_sessionReference; + m_sessionConstants = other.m_sessionConstants == nullptr ? nullptr : other.m_sessionConstants; + m_memberRequest = other.m_memberRequest; + m_sessionPropertiesKeywords = other.m_sessionPropertiesKeywords; + m_sessionPropertiesTurns = other.m_sessionPropertiesTurns; + m_joinRestriction = other.m_joinRestriction; + m_readRestriction = other.m_readRestriction; + m_sessionPropertiesCustomProperties = other.m_sessionPropertiesCustomProperties; + m_writeMatchmakingClientResult = other.m_writeMatchmakingClientResult; + m_writeMatchmakingSessionConstants = other.m_writeMatchmakingSessionConstants; + m_sessionPropertiesTargetSessionsConstants = other.m_sessionPropertiesTargetSessionsConstants; + m_writeInitializationStatus = other.m_writeInitializationStatus; + m_initializationSucceeded = other.m_initializationSucceeded; + m_writeHostDeviceToken = other.m_writeHostDeviceToken; + m_hostDeviceToken = other.m_hostDeviceToken; + m_writeMatchmakingServerConnectionPath = other.m_writeMatchmakingServerConnectionPath; + m_matchmakingServerConnectionPath = other.m_matchmakingServerConnectionPath; + m_writeMatchmakingResubmit = other.m_writeMatchmakingResubmit; + m_matchmakingMatchResubmit = other.m_matchmakingMatchResubmit; + m_writeServerConnectionStringCandidates = other.m_writeServerConnectionStringCandidates; + m_serverConnectionStringCandidates = other.m_serverConnectionStringCandidates; + m_members = other.m_members; + m_servers = other.m_servers; + m_memberRequestIndex = other.m_memberRequestIndex; + m_writeClosed = other.m_writeClosed; + m_closed = other.m_closed; +} + +multiplayer_session_request::multiplayer_session_request() : + m_joinRestriction(multiplayer_session_restriction::unknown), + m_readRestriction(multiplayer_session_restriction::unknown), + m_writeMatchmakingClientResult(false), + m_writeMatchmakingSessionConstants(false), + m_writeInitializationStatus(false), + m_initializationSucceeded(false), + m_writeHostDeviceToken(false), + m_writeMatchmakingServerConnectionPath(false), + m_writeMatchmakingResubmit(false), + m_matchmakingMatchResubmit(false), + m_writeServerConnectionStringCandidates(false), + m_memberRequestIndex(0), + m_bLeaveSession(false), + m_writeClosed(false), + m_closed(false) +{ + m_sessionConstants = std::make_shared(); + m_sessionPropertiesCustomProperties = web::json::value(); + m_sessionPropertiesTargetSessionsConstants = web::json::value(); + m_servers = web::json::value(); +} + +multiplayer_session_request::multiplayer_session_request( + _In_opt_ std::shared_ptr multiplayerSessionConstants + ) : + m_sessionConstants(std::move(multiplayerSessionConstants)), + m_joinRestriction(multiplayer_session_restriction::unknown), + m_readRestriction(multiplayer_session_restriction::unknown), + m_writeMatchmakingClientResult(false), + m_writeMatchmakingSessionConstants(false), + m_writeInitializationStatus(false), + m_initializationSucceeded(false), + m_writeHostDeviceToken(false), + m_writeMatchmakingServerConnectionPath(false), + m_writeMatchmakingResubmit(false), + m_matchmakingMatchResubmit(false), + m_writeServerConnectionStringCandidates(false), + m_memberRequestIndex(0), + m_bLeaveSession(false), + m_writeClosed(false), + m_closed(false) +{ +} + +std::shared_ptr +multiplayer_session_request::add_member_request( + _In_ bool writeRequest, + _In_ bool isMe, + _In_ string_t xboxUserId, + _In_ web::json::value memberConstants, + _In_ bool addInitializePropertyToRequest, + _In_ bool initializedRequested + ) +{ + std::lock_guard lock(m_lock.get()); + stringstream_t memberId; + string_t meString = isMe ? _T("me") : _T("reserve_"); + memberId << meString; + if (!isMe) + { + memberId << m_memberRequestIndex; + } + std::shared_ptr memberRequest = std::make_shared( + writeRequest, + memberId.str(), + std::move(xboxUserId), + std::move(memberConstants), + addInitializePropertyToRequest, + initializedRequested + ); + + if (!isMe) + { + m_memberRequestIndex++; + } + + m_members.push_back(memberRequest); + return memberRequest; +} + +const multiplayer_session_reference& +multiplayer_session_request::session_reference() const +{ + return m_sessionReference; +} + +void +multiplayer_session_request::set_session_reference( + _In_ multiplayer_session_reference sessionReference + ) +{ + m_sessionReference = std::move(sessionReference); +} + +void +multiplayer_session_request::leave_session() +{ + m_bLeaveSession = true; +} + +void +multiplayer_session_request::set_leave_session( + _In_ bool leaveSession + ) +{ + m_bLeaveSession = leaveSession; +} + +std::shared_ptr +multiplayer_session_request::session_constants() const +{ + return m_sessionConstants; +} + +void +multiplayer_session_request::set_session_constants( + _In_ std::shared_ptr sessionConstants + ) +{ + m_sessionConstants = sessionConstants; +} + +const std::vector& +multiplayer_session_request::session_properties_keywords() const +{ + return m_sessionPropertiesKeywords; +} + +void +multiplayer_session_request::set_session_properties_keywords( + _In_ std::vector keywords + ) +{ + m_sessionPropertiesKeywords = std::move(keywords); +} + +const std::vector& +multiplayer_session_request::session_properties_turns() const +{ + return m_sessionPropertiesTurns; +} + +void +multiplayer_session_request::set_session_properties_turns( + _In_ std::vector sessionProperties + ) +{ + m_sessionPropertiesTurns = std::move(sessionProperties); +} + +multiplayer_session_restriction +multiplayer_session_request::join_restriction() const +{ + return m_joinRestriction; +} + +void +multiplayer_session_request::set_join_restriction( + _In_ multiplayer_session_restriction joinRestriction + ) +{ + m_joinRestriction = joinRestriction; +} + +multiplayer_session_restriction +multiplayer_session_request::read_restriction() const +{ + return m_readRestriction; +} + +void +multiplayer_session_request::set_read_restriction( + _In_ multiplayer_session_restriction readRestriction + ) +{ + m_readRestriction = readRestriction; +} + +const web::json::value& +multiplayer_session_request::session_properties_custom_properties() const +{ + return m_sessionPropertiesCustomProperties; +} + +void +multiplayer_session_request::set_session_custom_properties( + _In_ web::json::value sessionCustomProperties + ) +{ + m_sessionPropertiesCustomProperties = std::move(sessionCustomProperties); +} + +bool +multiplayer_session_request::write_matchmaking_client_result() const +{ + return m_writeMatchmakingClientResult; +} + +void +multiplayer_session_request::set_write_matchmaking_client_result( +_In_ bool writeMatchmakingClientResult +) +{ + m_writeMatchmakingClientResult = writeMatchmakingClientResult; +} + +bool +multiplayer_session_request::write_matchmaking_session_constants() const +{ + return m_writeMatchmakingSessionConstants; +} + +void +multiplayer_session_request::set_write_matchmaking_session_constants( + _In_ bool matchmakingSessionConstant + ) +{ + m_writeMatchmakingSessionConstants = matchmakingSessionConstant; +} + +const web::json::value& +multiplayer_session_request::session_properties_target_sessions_constants() const +{ + return m_sessionPropertiesTargetSessionsConstants; +} + +void +multiplayer_session_request::set_session_properties_target_sessions_constants( + _In_ web::json::value targetSessionsConstants + ) +{ + m_sessionPropertiesTargetSessionsConstants = std::move(targetSessionsConstants); +} + +bool +multiplayer_session_request::write_initialization_status() const +{ + return m_writeInitializationStatus; +} + +void +multiplayer_session_request::set_write_initialization_status( + _In_ bool status + ) +{ + m_writeInitializationStatus = status; +} + +bool +multiplayer_session_request::initialization_succeeded() const +{ + return m_initializationSucceeded; +} + +void +multiplayer_session_request::set_initialization_succeeded( + _In_ bool succeeded + ) +{ + m_initializationSucceeded = succeeded; +} + +bool +multiplayer_session_request::write_host_device_token() const +{ + return m_writeHostDeviceToken; +} + +void +multiplayer_session_request::set_write_host_device_token( + _In_ bool writeToken + ) +{ + m_writeHostDeviceToken = writeToken; +} + +const string_t& +multiplayer_session_request::host_device_token() const +{ + return m_hostDeviceToken; +} + +void +multiplayer_session_request::set_host_device_token( + _In_ string_t deviceToken + ) +{ + m_hostDeviceToken = std::move(deviceToken); +} + +bool +multiplayer_session_request::write_matchmaking_server_connection_path() const +{ + return m_writeMatchmakingServerConnectionPath; +} + + +void +multiplayer_session_request::set_write_matchmaking_server_connection_path( + _In_ bool writePath + ) +{ + m_writeMatchmakingServerConnectionPath = writePath; +} + +const string_t& +multiplayer_session_request::matchmaking_server_connection_path() const +{ + return m_matchmakingServerConnectionPath; +} + + +void +multiplayer_session_request::set_matchmaking_server_connection_path( + _In_ string_t serverPath + ) +{ + m_matchmakingServerConnectionPath = std::move(serverPath); +} + +bool +multiplayer_session_request::write_matchmaking_resubmit() const +{ + return m_writeMatchmakingResubmit; +} + +void +multiplayer_session_request::set_write_matchmaking_resubmit( + _In_ bool writeMatchmakingResubmit + ) +{ + m_writeMatchmakingResubmit = writeMatchmakingResubmit; +} + +bool +multiplayer_session_request::matchmaking_match_resubmit() const +{ + return m_matchmakingMatchResubmit; +} + +void +multiplayer_session_request::set_matchmaking_match_resubmit( + _In_ bool matchmakingResubmit + ) +{ + m_matchmakingMatchResubmit = matchmakingResubmit; +} + +bool +multiplayer_session_request::write_server_connection_string_candidates() const +{ + return m_writeServerConnectionStringCandidates; +} + +void +multiplayer_session_request::set_write_server_connection_string_candidates( + _In_ bool writeCandidates + ) +{ + m_writeServerConnectionStringCandidates = writeCandidates; +} + +const std::vector& +multiplayer_session_request::server_connection_string_candidates() const +{ + return m_serverConnectionStringCandidates; +} + +void +multiplayer_session_request::set_server_connection_string_candidates( + _In_ std::vector candidates + ) +{ + m_serverConnectionStringCandidates = std::move(candidates); +} + +const std::vector>& +multiplayer_session_request::members() const +{ + return m_members; +} + +void +multiplayer_session_request::set_members( + _In_ std::vector> members + ) +{ + m_members = std::move(members); +} + +web::json::value +multiplayer_session_request::servers() const +{ + return m_servers; +} + +void +multiplayer_session_request::set_servers( + _In_ web::json::value servers + ) +{ + m_servers = servers; +} + +bool +multiplayer_session_request::write_closed() const +{ + return m_writeClosed; +} + +void +multiplayer_session_request::set_write_closed( + _In_ bool writeClosed + ) +{ + m_writeClosed = writeClosed; +} + +bool +multiplayer_session_request::closed() const +{ + return m_closed; +} + +void +multiplayer_session_request::set_closed( + _In_ bool closed + ) +{ + m_closed = closed; +} + +void +multiplayer_session_request::set_mutable_role_settings( + _In_ const std::unordered_map& roleTypes + ) +{ + m_roleTypes = std::move(roleTypes); +} + +web::json::value +multiplayer_session_request::create_properties_json() +{ + web::json::value jsonProperties; + web::json::value jsonPropertiesSystem; + if (!m_sessionPropertiesKeywords.empty()) + { + jsonPropertiesSystem[_T("keywords")] = utils::serialize_vector(utils::json_string_serializer, m_sessionPropertiesKeywords); + } + + if (!m_sessionPropertiesTurns.empty()) + { + jsonPropertiesSystem[_T("turn")] = utils::serialize_vector(utils::json_int_serializer, m_sessionPropertiesTurns); + } + + if (m_joinRestriction != multiplayer_session_restriction::unknown) + { + auto joinRestrictionToString = multiplayer_session_states::_Convert_multiplayer_session_restriction_to_string(m_joinRestriction); + jsonPropertiesSystem[_T("joinRestriction")] = web::json::value::string( + joinRestrictionToString.payload() + ); + } + + if (m_readRestriction != multiplayer_session_restriction::unknown) + { + auto readRestrictionToString = multiplayer_session_states::_Convert_multiplayer_session_restriction_to_string(m_readRestriction); + jsonPropertiesSystem[_T("readRestriction")] = web::json::value::string( + readRestrictionToString.payload() + ); + } + + if (m_writeClosed) + { + jsonPropertiesSystem[_T("closed")] = web::json::value(m_closed); + } + + if (m_writeMatchmakingClientResult || m_writeMatchmakingSessionConstants || m_writeMatchmakingServerConnectionPath) + { + jsonPropertiesSystem[_T("matchmaking")] = create_matchmaking_json(); + } + + if (m_writeMatchmakingResubmit) + { + jsonPropertiesSystem[_T("matchmakingResubmit")] = web::json::value(m_matchmakingMatchResubmit); + } + + if (m_writeInitializationStatus) + { + jsonPropertiesSystem[_T("initializationSucceeded")] = web::json::value(m_initializationSucceeded); + } + + if (m_writeHostDeviceToken) + { + jsonPropertiesSystem[_T("host")] = web::json::value(m_hostDeviceToken); + } + + if (m_writeServerConnectionStringCandidates) + { + jsonPropertiesSystem[_T("serverConnectionStringCandidates")] = utils::serialize_vector( + utils::json_string_serializer, + m_serverConnectionStringCandidates + ); + } + + if (!jsonPropertiesSystem.is_null()) + { + jsonProperties[_T("system")] = jsonPropertiesSystem; + } + + if (!m_sessionPropertiesCustomProperties.is_null()) + { + jsonProperties[_T("custom")] = m_sessionPropertiesCustomProperties; + } + + return jsonProperties; +} + +web::json::value +multiplayer_session_request::create_matchmaking_json() +{ + web::json::value jsonMatchmaking; + + if (!m_sessionPropertiesTargetSessionsConstants.is_null()) + { + jsonMatchmaking[_T("targetSessionConstants")] = m_sessionPropertiesTargetSessionsConstants; + } + + if (m_writeMatchmakingServerConnectionPath) + { + jsonMatchmaking[_T("serverConnectionString")] = web::json::value::string(m_matchmakingServerConnectionPath); + } + + return jsonMatchmaking; +} + +web::json::value +multiplayer_session_request::create_role_types_json() +{ + web::json::value serializedObject; + if (m_roleTypes.size() > 0) + { + web::json::value roleTypeJson; + for (const auto& roleType : m_roleTypes) + { + web::json::value rolesJson; + auto roles = roleType.second.roles(); + for (const auto& role : roles) + { + web::json::value roleJson; + auto roleInfo = role.second; + if (roleInfo.max_members_count() > 0) + { + roleJson[_T("max")] = roleInfo.max_members_count(); + } + if (roleInfo.target_count() > 0) + { + roleJson[_T("target")] = roleInfo.target_count(); + } + rolesJson[role.first] = roleJson; + } + roleTypeJson[_T("roles")] = rolesJson; + serializedObject[roleType.first] = roleTypeJson; + } + } + return serializedObject; +} + +web::json::value +multiplayer_session_request::serialize() +{ + web::json::value serializedObject = web::json::value::object(); + std::lock_guard lock(m_lock.get()); + + if (m_sessionConstants != nullptr) + { + web::json::value sessionConstantsJson = m_sessionConstants->_Serialize(); + if (!sessionConstantsJson.is_null()) + { + serializedObject[_T("constants")] = sessionConstantsJson; + } + } + + web::json::value roleTypesJson = create_role_types_json(); + if (!roleTypesJson.is_null()) + { + serializedObject[_T("roleTypes")] = std::move(roleTypesJson); + } + + web::json::value jsonProperties = create_properties_json(); + if (!jsonProperties.is_null()) + { + serializedObject[_T("properties")] = jsonProperties; + } + + if (!m_members.empty() || m_bLeaveSession) + { + web::json::value memberListJson; + for (const auto& member : m_members) + { + web::json::value memberJson = member->serialize(); + if (!memberJson.is_null()) + { + memberListJson[member->member_id()] = memberJson; + } + } + + if (m_bLeaveSession) + { + // Write "me" : null to leave session. + memberListJson[_T("me")] = web::json::value(); + } + + if (!memberListJson.is_null()) + { + serializedObject[_T("members")] = memberListJson; + } + } + + if (!m_servers.is_null()) + { + serializedObject[_T("servers")] = m_servers; + } + + return serializedObject; +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_role_types.cpp b/Source/Services/Multiplayer/multiplayer_session_role_types.cpp new file mode 100644 index 00000000..7e4c0bc1 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_role_types.cpp @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_role_types::multiplayer_session_role_types() +{ +} + +const std::unordered_map& +multiplayer_session_role_types::role_types() const +{ + return m_roleTypes; +} + +xbox_live_result +multiplayer_session_role_types::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + multiplayer_session_role_types returnResult; + std::error_code errc = xbox_live_error_code::no_error; + + web::json::object roleTypesObj = json.as_object(); + for (const auto& roleType : roleTypesObj) + { + auto roleTypeResult = multiplayer_role_type::_Deserialize(roleType.second); + if (roleTypeResult.err()) + { + errc = roleTypeResult.err(); + } + returnResult.m_roleTypes[roleType.first] = roleTypeResult.payload(); + } + + return xbox_live_result(returnResult, errc); + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_states.cpp b/Source/Services/Multiplayer/multiplayer_session_states.cpp new file mode 100644 index 00000000..e43dc035 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_states.cpp @@ -0,0 +1,224 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "utils.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_states::multiplayer_session_states() : + m_accepted(0), + m_joinRestriction(multiplayer_session_restriction::unknown), + m_status(multiplayer_session_status::unknown), + m_visibility(multiplayer_session_visibility::unknown), + m_myTurn(false) +{ +} + +const utility::datetime& +multiplayer_session_states::start_time() const +{ + return m_startTime; +} + +const multiplayer_session_reference& +multiplayer_session_states::session_reference() const +{ + return m_multiplayerSessionReference; +} + +multiplayer_session_status +multiplayer_session_states::status() const +{ + return m_status; +} + +multiplayer_session_visibility +multiplayer_session_states::visibility() const +{ + return m_visibility; +} + +bool +multiplayer_session_states::is_my_turn() const +{ + return m_myTurn; +} + +const string_t& +multiplayer_session_states::xbox_user_id() const +{ + return m_xboxUserId; +} + +uint32_t +multiplayer_session_states::accepted_member_count() const +{ + return m_accepted; +} + +multiplayer_session_restriction +multiplayer_session_states::join_restriction() const +{ + return m_joinRestriction; +} + +const std::vector& +multiplayer_session_states::keywords() const +{ + return m_keywords; +} + +multiplayer_session_restriction +multiplayer_session_states::_Convert_string_to_multiplayer_session_restriction( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("none")) == 0) + { + return multiplayer_session_restriction::none; + } + else if (utils::str_icmp(value, _T("local")) == 0) + { + return multiplayer_session_restriction::local; + } + else if (utils::str_icmp(value, _T("followed")) == 0) + { + return multiplayer_session_restriction::followed; + } + + return multiplayer_session_restriction::unknown; +} + +const xbox_live_result +multiplayer_session_states::_Convert_multiplayer_session_restriction_to_string( + _In_ multiplayer_session_restriction joinRestriction + ) +{ + switch (joinRestriction) + { + case multiplayer_session_restriction::unknown: return xbox_live_result(_T("unknown")); + + case multiplayer_session_restriction::none: return xbox_live_result(_T("none")); + + case multiplayer_session_restriction::local: return xbox_live_result(_T("local")); + + case multiplayer_session_restriction::followed: return xbox_live_result(_T("followed")); + + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Enum out of range"); + } +} + +multiplayer_session_status +multiplayer_session_states::_Convert_string_to_session_status( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("active")) == 0) + { + return multiplayer_session_status::active; + } + else if (utils::str_icmp(value, _T("inactive")) == 0) + { + return multiplayer_session_status::inactive; + } + else if (utils::str_icmp(value, _T("reserved")) == 0) + { + return multiplayer_session_status::reserved; + } + + return multiplayer_session_status::unknown; +} + +multiplayer_session_visibility +multiplayer_session_states::_Convert_string_to_session_visibility( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("private")) == 0) + { + return multiplayer_session_visibility::private_session; + } + else if (utils::str_icmp(value, _T("visible")) == 0) + { + return multiplayer_session_visibility::visible; + } + else if (utils::str_icmp(value, _T("full")) == 0) + { + return multiplayer_session_visibility::full; + } + else if (utils::str_icmp(value, _T("open")) == 0) + { + return multiplayer_session_visibility::open; + } + + return multiplayer_session_visibility::unknown; +} + +const xbox_live_result +multiplayer_session_states::_Convert_multiplayer_session_visibility_to_string(_In_ multiplayer_session_visibility sessionVisibility) +{ + switch (sessionVisibility) + { + case multiplayer_session_visibility::unknown: return xbox_live_result(_T("unknown")); + case multiplayer_session_visibility::any: return xbox_live_result(_T("any")); + case multiplayer_session_visibility::private_session: return xbox_live_result(_T("private")); + case multiplayer_session_visibility::visible: return xbox_live_result(_T("visible")); + case multiplayer_session_visibility::full: return xbox_live_result(_T("full")); + case multiplayer_session_visibility::open: return xbox_live_result(_T("open")); + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Enum out of range"); + } +} + +xbox_live_result +multiplayer_session_states::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_states returnResult; + if (json.is_null()) return xbox_live_result(returnResult); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value sessionRefJson = utils::extract_json_field(json, _T("sessionRef"), errc, true); + + returnResult.m_multiplayerSessionReference = multiplayer_session_reference( + utils::extract_json_string(sessionRefJson, _T("scid"), errc), + utils::extract_json_string(sessionRefJson, _T("templateName"), errc), + utils::extract_json_string(sessionRefJson, _T("name"), errc) + ); + + returnResult.m_myTurn = utils::extract_json_bool(json, _T("myTurn"), errc); + string_t sessionStatus = utils::extract_json_string(json, _T("status"), errc); + if (!sessionStatus.empty()) + { + returnResult.m_status = _Convert_string_to_session_status(std::move(sessionStatus)); + } + + string_t sessionVisibility = utils::extract_json_string(json, _T("visibility"), errc); + if (!sessionVisibility.empty()) + { + returnResult.m_visibility = _Convert_string_to_session_visibility(sessionVisibility); + } + + string_t joinRestriction = utils::extract_json_string(json, _T("joinRestriction"), errc); + if (!joinRestriction.empty()) + { + returnResult.m_joinRestriction = _Convert_string_to_multiplayer_session_restriction(joinRestriction); + } + + returnResult.m_startTime = utils::extract_json_time(json, _T("startTime"), errc); + returnResult.m_xboxUserId = utils::extract_json_string(json, _T("xuid"), errc); + returnResult.m_accepted = utils::extract_json_int(json, _T("accepted"), errc); + returnResult.m_keywords = utils::extract_json_vector(utils::json_string_extractor, json, _T("keywords"), errc, false); + + return returnResult; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_session_tournaments_server.cpp b/Source/Services/Multiplayer/multiplayer_session_tournaments_server.cpp new file mode 100644 index 00000000..b68d57e3 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_session_tournaments_server.cpp @@ -0,0 +1,253 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" + +using namespace xbox::services::tournaments; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_session_tournaments_server::multiplayer_session_tournaments_server() : + m_registrationState(tournament_registration_state::unknown), + m_registrationReason(tournament_registration_reason::unknown), + m_lastGameResultSource(tournament_game_result_source::none), + m_isNull(true) +{ +} + +const xbox::services::tournaments::tournament_reference& +multiplayer_session_tournaments_server::tournament_reference() const +{ + return m_tournamentRef; +} + +const std::unordered_map& +multiplayer_session_tournaments_server::teams() const +{ + return m_teams; +} + +tournament_registration_state +multiplayer_session_tournaments_server::registration_state() const +{ + return m_registrationState; +} + +tournament_registration_reason +multiplayer_session_tournaments_server::registration_reason() const +{ + return m_registrationReason; +} + +const utility::datetime& +multiplayer_session_tournaments_server::next_game_start_time() const +{ + return m_nextGameStartTime; +} + +const multiplayer_session_reference& +multiplayer_session_tournaments_server::next_game_session_reference() const +{ + return m_nextGameSessionReference; +} + +const utility::datetime& +multiplayer_session_tournaments_server::last_game_end_time() const +{ + return m_lastGameEndTime; +} + +tournament_team_result +multiplayer_session_tournaments_server::last_team_result() const +{ + return m_lastTeamResult; +} + +tournament_game_result_source +multiplayer_session_tournaments_server::last_game_result_source() const +{ + return m_lastGameResultSource; +} + +bool +multiplayer_session_tournaments_server::_Is_null() const +{ + return m_isNull; +} + +bool +multiplayer_session_tournaments_server::_Is_same(const multiplayer_session_tournaments_server& other) const +{ + if (m_lastGameEndTime != other.last_game_end_time() || + m_lastGameResultSource != other.last_game_result_source() || + m_lastTeamResult.state() != other.last_team_result().state() || + m_lastTeamResult.ranking() != other.last_team_result().ranking() || + m_nextGameSessionReference._Serialize() != other.next_game_session_reference()._Serialize() || + m_nextGameStartTime != other.next_game_start_time() || + m_registrationReason != other.registration_reason() || + m_registrationState != other.registration_state()) + { + return false; + } + return true; +} + +tournament_registration_state +multiplayer_session_tournaments_server::_Convert_string_to_registration_result(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("pending")) == 0) + { + return tournament_registration_state::pending; + } + else if (utils::str_icmp(value, _T("rejected")) == 0) + { + return tournament_registration_state::rejected; + } + else if (utils::str_icmp(value, _T("withdrawn")) == 0) + { + return tournament_registration_state::withdrawn; + } + else if (utils::str_icmp(value, _T("registered")) == 0) + { + return tournament_registration_state::registered; + } + else if (utils::str_icmp(value, _T("completed")) == 0) + { + return tournament_registration_state::completed; + } + + return tournament_registration_state::unknown; +} + +tournament_registration_reason +multiplayer_session_tournaments_server::_Convert_string_to_registration_reason(_In_ const string_t& value) +{ + if (utils::str_icmp(value, _T("RegistrationClosed")) == 0) + { + return tournament_registration_reason::registration_closed; + } + else if (utils::str_icmp(value, _T("MemberAlreadyRegistered")) == 0) + { + return tournament_registration_reason::member_already_registered; + } + else if (utils::str_icmp(value, _T("TournamentFull")) == 0) + { + return tournament_registration_reason::tournament_full; + } + else if (utils::str_icmp(value, _T("TeamEliminated")) == 0) + { + return tournament_registration_reason::team_eliminated; + } + else if (utils::str_icmp(value, _T("TournamentCompleted")) == 0) + { + return tournament_registration_reason::tournament_completed; + } + + return tournament_registration_reason::unknown; +} + +xbox_live_result +multiplayer_session_tournaments_server::_Deserialize( + _In_ const web::json::value& json + ) +{ + multiplayer_session_tournaments_server returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + auto constantsJson = utils::extract_json_field(json, _T("constants"), errc, true); + auto systemConstantsJson = utils::extract_json_field(constantsJson, _T("system"), errc, true); + + auto tournamentRefJson = utils::extract_json_field(systemConstantsJson, _T("tournamentRef"), errc, true); + if (!tournamentRefJson.is_null()) + { + auto tournamentResult = xbox::services::tournaments::tournament_reference::_Deserialize(tournamentRefJson); + if (tournamentResult.err()) + { + errc = tournamentResult.err(); + } + returnObject.m_tournamentRef = tournamentResult.payload(); + } + + auto teamsJson = utils::extract_json_field(systemConstantsJson, _T("teams"), errc, false); + if (!teamsJson.is_null() && teamsJson.is_object()) + { + web::json::object teamsObj = teamsJson.as_object(); + for (const auto& team : teamsObj) + { + auto sessionRefJson = utils::extract_json_field(team.second, _T("teamSessionRef"), true); + auto sessionResult = multiplayer_session_reference::_Deserialize(sessionRefJson); + if (!sessionResult.err()) + { + returnObject.m_teams[team.first] = sessionResult.payload(); + } + else + { + errc = sessionResult.err(); + } + } + } + + auto propertyJson = utils::extract_json_field(json, _T("properties"), errc, false); + auto systemPropertyJson = utils::extract_json_field(propertyJson, _T("system"), errc, false); + + auto registrationJson = utils::extract_json_field(systemPropertyJson, _T("registration"), errc, false); + if (!registrationJson.is_null()) + { + returnObject.m_registrationState = multiplayer_session_tournaments_server::_Convert_string_to_registration_result( + utils::extract_json_string(registrationJson, _T("state"), errc) + ); + returnObject.m_registrationReason = multiplayer_session_tournaments_server::_Convert_string_to_registration_reason( + utils::extract_json_string(registrationJson, _T("reason"), errc) + ); + } + + auto rendezvousJson = utils::extract_json_field(systemPropertyJson, _T("rendezvous"), errc, false); + if (!rendezvousJson.is_null()) + { + returnObject.m_nextGameStartTime = utils::extract_json_time(rendezvousJson, _T("startTime"), errc, false); + + auto nextGameJson = utils::extract_json_field(rendezvousJson, _T("gameSessionRef"), errc, false); + if (!nextGameJson.is_null()) + { + auto gameSessionResult = multiplayer_session_reference::_Deserialize(nextGameJson); + if (gameSessionResult.err()) + { + errc = gameSessionResult.err(); + } + returnObject.m_nextGameSessionReference = gameSessionResult.payload(); + } + } + + auto lastGameJson = utils::extract_json_field(systemPropertyJson, _T("lastGame"), errc, false); + if (!lastGameJson.is_null()) + { + returnObject.m_lastGameEndTime = utils::extract_json_time(lastGameJson, _T("endTime"), errc, false); + auto lastGameResultJson = utils::extract_json_field(lastGameJson, _T("result"), errc, false); + if (!lastGameResultJson.is_null()) + { + auto tournamentTeamResult = tournament_team_result::_Deserialize(lastGameResultJson); + if (tournamentTeamResult.err()) + { + errc = tournamentTeamResult.err(); + } + returnObject.m_lastTeamResult = tournamentTeamResult.payload(); + returnObject.m_lastGameResultSource = multiplayer_service::_Convert_string_to_game_result_source( + utils::extract_json_string(lastGameResultJson, _T("source"), errc) + ); + } + } + + returnObject.m_isNull = false; + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_subscription.cpp b/Source/Services/Multiplayer/multiplayer_subscription.cpp new file mode 100644 index 00000000..316e6642 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_subscription.cpp @@ -0,0 +1,178 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +using namespace xbox::services::real_time_activity; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_subscription::multiplayer_subscription( + _In_ const std::function& multiplayerSessionChangeHandler, + _In_ const std::function& multiplayerSubscriptionLostHandler, + _In_ const std::function& subscriptionErrorHandler + ) : + real_time_activity_subscription(subscriptionErrorHandler), + m_multiplayerSessionChangeHandler(multiplayerSessionChangeHandler), + m_multiplayerSubscriptionLostHandler(multiplayerSubscriptionLostHandler) +{ + XSAPI_ASSERT(m_multiplayerSessionChangeHandler != nullptr); + XSAPI_ASSERT(m_multiplayerSubscriptionLostHandler != nullptr); + + m_resourceUri = _T("https://sessiondirectory.xboxlive.com/connections/"); +} + +const string_t& +multiplayer_subscription::rta_connection_id() const +{ + return m_mpConnectionId; +} + +void +multiplayer_subscription::on_subscription_created( + _In_ uint32_t id, + _In_ const web::json::value& data + ) +{ + xbox_live_result result; + if (!data.is_null()) + { + real_time_activity_subscription::on_subscription_created(id, data); + std::error_code errc; + + bool connectionWasEmpty = m_mpConnectionId.empty(); + m_mpConnectionId = utils::extract_json_string(data, _T("ConnectionId"), errc, true); + + result = xbox_live_result( + m_mpConnectionId, + errc + ); + + if (errc) + { + result._Set_err_message("JSON deserialization failed"); + return; + } + + if (connectionWasEmpty) + { + m_resourceUri.append(m_mpConnectionId); + } + } + else + { + result = xbox_live_result( + xbox_live_error_code::json_error, + "Data not found on subscription" + ); + } + + task.set(result); +} + +void +multiplayer_subscription::on_event_received( + _In_ const web::json::value& data + ) +{ + std::error_code errc; + web::json::array shoulderTaps = utils::extract_json_as_array(utils::extract_json_field(data, _T("shoulderTaps"), errc, true), errc); + if (errc && m_subscriptionErrorHandler) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON deserialization failure" + ) + ); + } + + for (const auto& tapValue : shoulderTaps) + { + string_t resourceName = utils::extract_json_string(tapValue, _T("resource"), true); + std::vector nameComponents = utils::string_split(resourceName, '~'); + + if (nameComponents.size() != 3) + { + if(m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "Resource has too many values" + ) + ); + } + + continue; + } + + multiplayer_session_reference sessionRef( + nameComponents[0], + nameComponents[1], + nameComponents[2] + ); + + uint64_t changeNumber = utils::extract_json_int(tapValue, _T("changeNumber"), false); + string_t branch = utils::extract_json_string(tapValue, _T("branch"), false); + + multiplayer_session_change_event_args changeEventArgs( + sessionRef, + branch, + changeNumber + ); + + if (m_multiplayerSessionChangeHandler != nullptr) + { + m_multiplayerSessionChangeHandler(changeEventArgs); + } + } +} + +void +multiplayer_subscription::_Set_state( + _In_ real_time_activity_subscription_state newState + ) +{ + // if state is change from pending subscribe to closed, subscription failed. + if (m_state == real_time_activity_subscription_state::pending_subscribe && newState == real_time_activity_subscription_state::closed) + { + task.set(xbox_live_result(xbox_live_error_code::runtime_error, "multiplayer subscription failure")); + } + + if (m_state != real_time_activity_subscription_state::closed && newState == real_time_activity_subscription_state::closed) + { + // Because the title could disable subscriptions and destruct the XboxLiveContext right after, + // multiplayer_service may no longer exist. + if (m_multiplayerSubscriptionLostHandler != nullptr) + { + auto subscriptionHandler = m_multiplayerSubscriptionLostHandler; + pplx::create_task([subscriptionHandler]() + { + try + { + subscriptionHandler(); + } + catch (...) + { + } + }); + } + } + + real_time_activity_subscription::_Set_state(newState); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Multiplayer/multiplayer_transfer_handle_post_request.cpp b/Source/Services/Multiplayer/multiplayer_transfer_handle_post_request.cpp new file mode 100644 index 00000000..f6c4f0c0 --- /dev/null +++ b/Source/Services/Multiplayer/multiplayer_transfer_handle_post_request.cpp @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +#include "multiplayer_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_BEGIN + +multiplayer_transfer_handle_post_request::multiplayer_transfer_handle_post_request() : + m_version(0) +{ +} + +multiplayer_transfer_handle_post_request::multiplayer_transfer_handle_post_request( + _In_ multiplayer_session_reference targetSessionReference, + _In_ multiplayer_session_reference originSessionReference, + _In_ uint32_t version + ) : + m_targetSessionReference(std::move(targetSessionReference)), + m_originSessionReference(std::move(originSessionReference)), + m_version(version) +{ + XSAPI_ASSERT(!m_targetSessionReference.is_null()); + XSAPI_ASSERT(!m_originSessionReference.is_null()); +} + +const multiplayer_session_reference& +multiplayer_transfer_handle_post_request::origin_session_reference() const +{ + return m_originSessionReference; +} + +const multiplayer_session_reference& +multiplayer_transfer_handle_post_request::target_session_reference() const +{ + return m_targetSessionReference; +} + +uint32_t +multiplayer_transfer_handle_post_request::version() const +{ + return m_version; +} + +web::json::value +multiplayer_transfer_handle_post_request::serialize() const +{ + web::json::value serializedObject; + + serializedObject[_T("type")] = web::json::value::string(_T("transfer")); + serializedObject[_T("sessionRef")] = m_targetSessionReference._Serialize(); + serializedObject[_T("version")] = web::json::value(m_version); + serializedObject[_T("originSessionRef")] = m_originSessionReference._Serialize(); + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_MULTIPLAYER_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.cpp b/Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.cpp new file mode 100644 index 00000000..a7759979 --- /dev/null +++ b/Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.cpp @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "DevicePresenceChangeEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +DevicePresenceChangeEventArgs::DevicePresenceChangeEventArgs( + _In_ xbox::services::presence::device_presence_change_event_args cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.h b/Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.h new file mode 100644 index 00000000..4a53da9b --- /dev/null +++ b/Source/Services/Presence/WinRT/DevicePresenceChangeEventArgs_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceDeviceType_WinRT.h" +#include "PresenceRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// +/// Contains information about a device presence change event. +/// +public ref class DevicePresenceChangeEventArgs sealed +{ +public: + /// + /// The Xbox user ID for the user present on the device. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The type of device related to the presence information. + /// + DEFINE_PROP_GET_ENUM_OBJ(DeviceType, device_type, PresenceDeviceType); + + /// + /// Indicates whether the user is logged on to the device. + /// + DEFINE_PROP_GET_OBJ(IsUserLoggedOnDevice, is_user_logged_on_device, bool); + +internal: + DevicePresenceChangeEventArgs(_In_ xbox::services::presence::device_presence_change_event_args cppObj); + +private: + _In_ xbox::services::presence::device_presence_change_event_args m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.cpp b/Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.cpp new file mode 100644 index 00000000..157f4558 --- /dev/null +++ b/Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.cpp @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "DevicePresenceChangeSubscription_WinRT.h" + +using namespace Microsoft::Xbox::Services::RealTimeActivity; +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +DevicePresenceChangeSubscription::DevicePresenceChangeSubscription( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ +} + +RealTimeActivitySubscriptionState +DevicePresenceChangeSubscription::State::get() +{ + return static_cast(m_cppObj->state()); +} + +std::shared_ptr +DevicePresenceChangeSubscription::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.h b/Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.h new file mode 100644 index 00000000..67e81d3c --- /dev/null +++ b/Source/Services/Presence/WinRT/DevicePresenceChangeSubscription_WinRT.h @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceRecord_WinRT.h" +#include "RealTimeActivitySubscriptionState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// +/// Contains information about a device presence subscription. +/// +public ref class DevicePresenceChangeSubscription sealed +{ +public: + /// + /// The current state of the subscription. + /// + property Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState State{ Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState get(); } + + /// + /// The resource uri for the request. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ResourceUri, resource_uri); + + /// + /// The unique subscription id for the request. + /// + DEFINE_PTR_PROP_GET_OBJ(SubscriptionId, subscription_id, uint32_t); + + /// + /// The xbox user id the subscription is for + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + +internal: + DevicePresenceChangeSubscription(_In_ std::shared_ptr cppObj); + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.cpp new file mode 100644 index 00000000..d88afdb5 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.cpp @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceBroadcastRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceBroadcastRecord::PresenceBroadcastRecord( + _In_ xbox::services::presence::presence_broadcast_record cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.h b/Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.h new file mode 100644 index 00000000..8dc9e414 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceBroadcastRecord_WinRT.h @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN +/// +/// Represents a record of data about the broadcast. +/// +/// +/// The record is only returned if the client specifies an Entertainment Discovery Services(EDS) service version(x - xbl - contract - version) of 3 or later. +/// + +public ref class PresenceBroadcastRecord sealed +{ +public: + /// + /// Id for this broadcast as defined by the broadcasting service. + /// + DEFINE_PROP_GET_STR_OBJ(BroadcastId, broadcast_id); + + /// + /// The GUID uniquely identifying the broadcasting session. + /// + DEFINE_PROP_GET_STR_OBJ(Session, session); + + /// + /// Name of the streaming provider. + /// + DEFINE_PROP_GET_STR_OBJ(Provider, provider); + + /// + /// Approximate number of current viewers. + /// + DEFINE_PROP_GET_OBJ(ViewerCount, viewer_count, uint32); + + /// + /// UTC timestamp when the broadcast was started. + /// + DEFINE_PROP_GET_DATETIME_OBJ(StartTime, start_time); + +internal: + PresenceBroadcastRecord(_In_ xbox::services::presence::presence_broadcast_record cppObj); + +private: + xbox::services::presence::presence_broadcast_record m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceData_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceData_WinRT.cpp new file mode 100644 index 00000000..b0ee8a52 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceData_WinRT.cpp @@ -0,0 +1,75 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceData_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::presence; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceData::PresenceData( + _In_ presence_data cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_presenceTokenIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString( + m_cppObj.presence_token_ids() + )->GetView(); +} + +PresenceData::PresenceData( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ presenceId + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj = presence_data( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(presenceId) + ) + ); + + m_presenceTokenIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString( + m_cppObj.presence_token_ids() + )->GetView(); +} + +PresenceData::PresenceData( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ presenceId, + _In_ Windows::Foundation::Collections::IVectorView^ presenceTokenIds + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj = presence_data( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(presenceId), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(presenceTokenIds) + ) + ); + + m_presenceTokenIds = presenceTokenIds; +} + +Windows::Foundation::Collections::IVectorView^ +PresenceData::PresenceTokenIds::get() +{ + return m_presenceTokenIds; +} + +const xbox::services::presence::presence_data& +PresenceData::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceData_WinRT.h b/Source/Services/Presence/WinRT/PresenceData_WinRT.h new file mode 100644 index 00000000..368f4391 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceData_WinRT.h @@ -0,0 +1,73 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN +/// +/// Represents data supporting Rich Presence features. +/// + +public ref class PresenceData sealed +{ +public: + /// + /// Initializes a new instance of the PresenceData class. + /// + /// The service configuration ID (SCID) that identifies where the presence strings are defined by Id. + /// Id of the presence string that should be used. + PresenceData( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ presenceId + ); + + /// + /// Initializes a new instance of the PresenceData class. + /// + /// The service configuration ID (SCID) that identifies where the presence strings are defined by Id. + /// Id of the presence string that should be used. + /// Ids of the strings that should be used to replace the tokens in the presence string. + PresenceData( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ presenceId, + _In_ Windows::Foundation::Collections::IVectorView^ presenceTokenIds + ); + + /// + /// ID of the service configuration containing the presence strings. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The ID of a presence string that is defined in the service configuration. + /// For example, PresenceId = "1" could equal "Playing {0} on {1}" in the service configuration. + /// The service configuration might map token 0 to Maps and token 1 to MapId + /// + DEFINE_PROP_GET_STR_OBJ(PresenceId, presence_id); + + /// + /// The IDs of the strings to replace the format string tokens found in the presence string. These strings are also defined in the service configuration. + /// The ID values in the collection map to the strings associated with the token arguments found in the PresenceId. + /// For example let's say this vector view contained the values "4" and "1" and PresenceId = "1" equals "Playing {0} on {1}" in the service configuration. + /// The service configuration might map Token 0 = Maps, where MapId = "4" equals "Hometown". + /// The service configuration might map Token 1 = Difficulty, where DifficultyId = "1" equals "Casual" + /// + property Windows::Foundation::Collections::IVectorView^ PresenceTokenIds { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + PresenceData(_In_ xbox::services::presence::presence_data cppObj); + const xbox::services::presence::presence_data& GetCppObj() const; + +private: + xbox::services::presence::presence_data m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_presenceTokenIds; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceDetailLevel_WinRT.h b/Source/Services/Presence/WinRT/PresenceDetailLevel_WinRT.h new file mode 100644 index 00000000..8ce1991b --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceDetailLevel_WinRT.h @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// Defines values that determine the level of presence detail return from the service. Choosing proper detail level could help the performance of the API. +public enum class PresenceDetailLevel +{ + /// Default detail level. + Default = xbox::services::presence::presence_detail_level::default_level, + + /// User detail level. User presence info only, no device, title, or rich presence info. + User = xbox::services::presence::presence_detail_level::user, + + /// Device detail level. User and device presence info only, no title, or rich presence info. + Device = xbox::services::presence::presence_detail_level::device, + + /// Title detail level. User, device, and title presence info only, no rich presence info. + Title = xbox::services::presence::presence_detail_level::title, + + /// All detail possible. User, device, title, and rich presence info will be provided. + All = xbox::services::presence::presence_detail_level::all +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.cpp new file mode 100644 index 00000000..1abf945d --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.cpp @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceDeviceRecord_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceDeviceRecord::PresenceDeviceRecord( + _In_ xbox::services::presence::presence_device_record cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_presenceTitleRecords = UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + m_cppObj.presence_title_records() + )->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +PresenceDeviceRecord::PresenceTitleRecords::get() +{ + return m_presenceTitleRecords; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.h b/Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.h new file mode 100644 index 00000000..6aa663cf --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceDeviceRecord_WinRT.h @@ -0,0 +1,37 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceTitleRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN +/// +/// Represents a device record for Rich Presence. +/// + +public ref class PresenceDeviceRecord sealed +{ +public: + /// + /// The device type associated with this record. + /// + DEFINE_PROP_GET_ENUM_OBJ(DeviceType, device_type, PresenceDeviceType); + + property Windows::Foundation::Collections::IVectorView^ PresenceTitleRecords { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + PresenceDeviceRecord(_In_ xbox::services::presence::presence_device_record cppObj); + +private: + xbox::services::presence::presence_device_record m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_presenceTitleRecords; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceDeviceType_WinRT.h b/Source/Services/Presence/WinRT/PresenceDeviceType_WinRT.h new file mode 100644 index 00000000..64a4183a --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceDeviceType_WinRT.h @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// Defines values that indicate the device type associate with a PresenceTitleRecord. +public enum class PresenceDeviceType +{ + /// Unknown device + Unknown = xbox::services::presence::presence_device_type::unknown, + + /// Windows Phone device + WindowsPhone = xbox::services::presence::presence_device_type::windows_phone, + + /// Windows Phone 7 device + WindowsPhone7 = xbox::services::presence::presence_device_type::windows_phone_7, + + /// Web device (like Xbox.com) + Web = xbox::services::presence::presence_device_type::web, + + /// Xbox360 device + Xbox360 = xbox::services::presence::presence_device_type::xbox_360, + + /// Games for Windows LIVE device + PC = xbox::services::presence::presence_device_type::pc, + + /// Xbox LIVE for Windows device + Windows8 = xbox::services::presence::presence_device_type::windows_8, + + /// Xbox One device + XboxOne = xbox::services::presence::presence_device_type::xbox_one, + + /// Windows One Core device + WindowsOneCore = xbox::services::presence::presence_device_type::windows_one_core, + + /// Windows One Core Mobile device + WindowsOneCoreMobile = xbox::services::presence::presence_device_type::windows_one_core_mobile, +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceMediaIdType_WinRT.h b/Source/Services/Presence/WinRT/PresenceMediaIdType_WinRT.h new file mode 100644 index 00000000..3ce2ff0d --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceMediaIdType_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// Defines values that indicate the media id types for media presence data. +public enum class PresenceMediaIdType +{ + /// Unknown media Id. + Unknown = xbox::services::presence::presence_media_id_type::unknown, + + /// Bing media Id. + Bing = xbox::services::presence::presence_media_id_type::bing, + + /// MediaProvider media Id. + MediaProvider = xbox::services::presence::presence_media_id_type::media_provider +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.cpp new file mode 100644 index 00000000..a940cd76 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.cpp @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceMediaRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceMediaRecord::PresenceMediaRecord( + _In_ xbox::services::presence::presence_media_record cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.h b/Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.h new file mode 100644 index 00000000..92d9fa0a --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceMediaRecord_WinRT.h @@ -0,0 +1,44 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceMediaIdType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN +/// +/// Represents a media record for Rich Presence. +/// + +public ref class PresenceMediaRecord sealed +{ +public: + /// + /// ID of the media used by the Bing catalog or the provider catalog. + /// + DEFINE_PROP_GET_STR_OBJ(MediaId, media_id); + + /// + /// The ID type of the media. + /// + DEFINE_PROP_GET_ENUM_OBJ(MediaIdType, media_id_type, PresenceMediaIdType); + + /// + /// Localized name of the media content. + /// + DEFINE_PROP_GET_STR_OBJ(Name, name); + +internal: + PresenceMediaRecord(_In_ xbox::services::presence::presence_media_record cppObj); + +private: + xbox::services::presence::presence_media_record m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceRecord_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceRecord_WinRT.cpp new file mode 100644 index 00000000..6baa3411 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceRecord_WinRT.cpp @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceRecord_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceRecord::PresenceRecord( + _In_ xbox::services::presence::presence_record cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_presenceDeviceRecords = UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + m_cppObj.presence_device_records() + )->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +PresenceRecord::PresenceDeviceRecords::get() +{ + return m_presenceDeviceRecords; +} + +bool PresenceRecord::IsUserPlayingTitle(_In_ uint32_t titleId) +{ + return m_cppObj.is_user_playing_title(titleId); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceRecord_WinRT.h b/Source/Services/Presence/WinRT/PresenceRecord_WinRT.h new file mode 100644 index 00000000..3b6d7e8d --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceRecord_WinRT.h @@ -0,0 +1,52 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "UserPresenceState_WinRT.h" +#include "PresenceTitleRecord_WinRT.h" +#include "PresenceDeviceRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN +/// +/// Represents a record for Rich Presence. +/// + +public ref class PresenceRecord sealed +{ +public: + /// + /// The Xbox user ID. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The user's presence state. + /// + DEFINE_PROP_GET_ENUM_OBJ(UserState, user_state, UserPresenceState); + + /// + /// Collection of PresenceTitleRecord objects returned by a request. + /// + property Windows::Foundation::Collections::IVectorView^ PresenceDeviceRecords { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// Returns whether the user is playing this title id + /// + bool IsUserPlayingTitle(_In_ uint32_t titleId); + +internal: + PresenceRecord(_In_ xbox::services::presence::presence_record cppObj); + +private: + xbox::services::presence::presence_record m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_presenceDeviceRecords; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceService_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceService_WinRT.cpp new file mode 100644 index 00000000..9156b602 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceService_WinRT.cpp @@ -0,0 +1,418 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceService_WinRT.h" +#include "Utils_WinRT.h" +#include "XboxLiveContextSettings_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace xbox::services::presence; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceService::PresenceService( + _In_ xbox::services::presence::presence_service cppObj + ) : + m_cppObj(cppObj) +{ + m_devicePresenceChangeEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + m_titlePresenceChangeEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + + m_devicePresenceChangeEventBind->AddDevicePresenceChangeEvent(); + m_titlePresenceChangeEventBind->AddTitlePresenceChangeEvent(); +} + +PresenceService::~PresenceService() +{ + m_devicePresenceChangeEventBind->RemoveDevicePresenceChangeEvent(m_cppObj); + m_titlePresenceChangeEventBind->RemoveTitlePresenceChangeEvent(m_cppObj); +} + +DevicePresenceChangeEventBind::DevicePresenceChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::presence::presence_service& cppObj + ) : + m_setting(setting), + m_cppObj(cppObj) +{ +} + +void +DevicePresenceChangeEventBind::RemoveDevicePresenceChangeEvent( + _In_ xbox::services::presence::presence_service& cppObj + ) +{ + cppObj.remove_device_presence_changed_handler(m_functionContext); +} + +void +DevicePresenceChangeEventBind::DevicePresenceChangeRouter( + _In_ const xbox::services::presence::device_presence_change_event_args& presenceChangeEventArgs + ) +{ + PresenceService^ presenceService = m_setting.Resolve(); + if (presenceService != nullptr) + { + if (m_cppObj._Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([presenceService, presenceChangeEventArgs]() + { + presenceService->RaiseDevicePresenceChange(ref new DevicePresenceChangeEventArgs(presenceChangeEventArgs)); + })); + } + else + { + presenceService->RaiseDevicePresenceChange(ref new DevicePresenceChangeEventArgs(presenceChangeEventArgs)); + } + } +} + +void DevicePresenceChangeEventBind::AddDevicePresenceChangeEvent() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_cppObj.add_device_presence_changed_handler([thisWeakPtr](_In_ const xbox::services::presence::device_presence_change_event_args& presenceChangeEventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->DevicePresenceChangeRouter(presenceChangeEventArgs); + } + }); +} + +TitlePresenceChangeEventBind::TitlePresenceChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::presence::presence_service& cppObj + ) : + m_setting(setting), + m_cppObj(cppObj) +{ +} + +void +TitlePresenceChangeEventBind::RemoveTitlePresenceChangeEvent( + _In_ xbox::services::presence::presence_service& cppObj + ) +{ + cppObj.remove_title_presence_changed_handler(m_functionContext); +} + +void +TitlePresenceChangeEventBind::TitlePresenceChangeRouter( + _In_ const xbox::services::presence::title_presence_change_event_args& presenceChangeEventArgs + ) +{ + PresenceService^ presenceService = m_setting.Resolve(); + + if (presenceService != nullptr) + { + if (m_cppObj._Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([presenceService, presenceChangeEventArgs]() + { + presenceService->RaiseTitlePresenceChange(ref new TitlePresenceChangeEventArgs(presenceChangeEventArgs)); + })); + } + else + { + presenceService->RaiseTitlePresenceChange(ref new TitlePresenceChangeEventArgs(presenceChangeEventArgs)); + } + } +} + +void TitlePresenceChangeEventBind::AddTitlePresenceChangeEvent() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_cppObj.add_title_presence_changed_handler([thisWeakPtr](_In_ const xbox::services::presence::title_presence_change_event_args& presenceChangeEventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->TitlePresenceChangeRouter(presenceChangeEventArgs); + } + }); +} + +void +PresenceService::RaiseDevicePresenceChange(_In_ DevicePresenceChangeEventArgs^ args) +{ + DevicePresenceChanged(this, args); +} + +void +PresenceService::RaiseTitlePresenceChange(_In_ TitlePresenceChangeEventArgs^ args) +{ + TitlePresenceChanged(this, args); +} + +Windows::Foundation::IAsyncAction^ +PresenceService::SetPresenceAsync( + _In_ bool isUserActiveInTitle + ) +{ + auto task = m_cppObj.set_presence(isUserActiveInTitle) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncAction^ +PresenceService::SetPresenceAsync( + _In_ bool isUserActiveInTitle, + _In_opt_ PresenceData^ presenceData + ) +{ + presence_data data; + + if (presenceData != nullptr) + { + data = presenceData->GetCppObj(); + } + + auto task = m_cppObj.set_presence(isUserActiveInTitle, data) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +PresenceService::GetPresenceAsync( + _In_ String^ xboxUserId + ) +{ + THROW_INVALIDARGUMENT_IF(xboxUserId == nullptr || xboxUserId->IsEmpty()); + + auto task = m_cppObj.get_presence(STRING_T_FROM_PLATFORM_STRING(xboxUserId)) + .then([](xbox_live_result record) + { + THROW_IF_ERR(record); + return ref new PresenceRecord(record.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +PresenceService::GetPresenceForMultipleUsersAsync( + _In_ IVectorView^ xboxUserIds + ) +{ + THROW_INVALIDARGUMENT_IF(xboxUserIds == nullptr || xboxUserIds->Size == 0); + + auto task = m_cppObj.get_presence_for_multiple_users( + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds) + ) + .then([](xbox_live_result> records) + { + THROW_IF_ERR(records); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + records.payload() + )->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +PresenceService::GetPresenceForMultipleUsersAsync( + _In_ IVectorView^ xboxUserIds, + _In_opt_ IVectorView^ deviceTypes, + _In_opt_ IVectorView^ titleIds, + _In_ PresenceDetailLevel detailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) +{ + std::vector types; + + if (deviceTypes != nullptr) + { + for (const auto& deviceType : deviceTypes) + { + types.push_back(static_cast(deviceType)); + } + } + + std::vector ids; + if (titleIds != nullptr) + { + for (const auto& titleId : titleIds) + { + ids.push_back(titleId); + } + } + + auto task = m_cppObj.get_presence_for_multiple_users( + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIds), + types, + ids, + static_cast(detailLevel), + onlineOnly, + broadcastingOnly + ) + .then([](xbox_live_result> records) + { + THROW_IF_ERR(records); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + records.payload() + )->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +PresenceService::GetPresenceForSocialGroupAsync( + _In_ String^ socialGroup + ) +{ + auto task = m_cppObj.get_presence_for_social_group( + STRING_T_FROM_PLATFORM_STRING(socialGroup) + ) + .then([](xbox_live_result> records) + { + THROW_IF_ERR(records); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + records.payload() + )->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +PresenceService::GetPresenceForSocialGroupAsync( + _In_ String^ socialGroup, + _In_opt_ String^ socialGroupOwnerXboxuserId, + _In_opt_ IVectorView^ deviceTypes, + _In_opt_ IVectorView^ titleIds, + _In_ PresenceDetailLevel detailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) +{ + std::vector types; + + if (deviceTypes != nullptr) + { + for (const auto& deviceType : deviceTypes) + { + types.push_back(static_cast(deviceType)); + } + } + + std::vector ids; + + if (titleIds != nullptr) + { + for (const auto& titleId : titleIds) + { + ids.push_back(titleId); + } + } + + auto task = m_cppObj.get_presence_for_social_group( + STRING_T_FROM_PLATFORM_STRING(socialGroup), + STRING_T_FROM_PLATFORM_STRING(socialGroupOwnerXboxuserId), + types, + ids, + static_cast(detailLevel), + onlineOnly, + broadcastingOnly + ) + .then([](xbox_live_result> records) + { + THROW_IF_ERR(records); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + records.payload() + )->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +DevicePresenceChangeSubscription^ +PresenceService::SubscribeToDevicePresenceChange( + _In_ Platform::String^ xboxUserId + ) +{ + std::shared_ptr subscription; + auto subscriptionResult = m_cppObj.subscribe_to_device_presence_change( + xboxUserId->Data() + ); + THROW_IF_ERR(subscriptionResult); + subscription = subscriptionResult.payload(); + + return ref new DevicePresenceChangeSubscription(subscription); +} + +void +PresenceService::UnsubscribeFromDevicePresenceChange( + _In_ DevicePresenceChangeSubscription^ subscription + ) +{ + auto unsubscribeResult = m_cppObj.unsubscribe_from_device_presence_change( + subscription->GetCppObj() + ); + + THROW_IF_ERR(unsubscribeResult); +} + +TitlePresenceChangeSubscription^ +PresenceService::SubscribeToTitlePresenceChange( + _In_ Platform::String^ xboxUserId, + _In_ uint32 titleId + ) +{ + std::shared_ptr subscription; + auto subscriptionResult = m_cppObj.subscribe_to_title_presence_change( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + titleId + ); + + THROW_IF_ERR(subscriptionResult); + subscription = subscriptionResult.payload(); + + return ref new TitlePresenceChangeSubscription(subscription); +} + +void +PresenceService::UnsubscribeFromTitlePresenceChange( + _In_ TitlePresenceChangeSubscription^ subscription + ) +{ + auto unsubscribeResult = m_cppObj.unsubscribe_from_title_presence_change( + subscription->GetCppObj() + ); + + THROW_IF_ERR(unsubscribeResult); +} + +const xbox::services::presence::presence_service& +PresenceService::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceService_WinRT.h b/Source/Services/Presence/WinRT/PresenceService_WinRT.h new file mode 100644 index 00000000..fd5793eb --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceService_WinRT.h @@ -0,0 +1,226 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "PresenceData_WinRT.h" +#include "PresenceRecord_WinRT.h" +#include "PresenceDetailLevel_WinRT.h" +#include "DevicePresenceChangeSubscription_WinRT.h" +#include "DevicePresenceChangeEventArgs_WinRT.h" +#include "TitlePresenceChangeSubscription_WinRT.h" +#include "TitlePresenceChangeEventArgs_WinRT.h" +#include "xsapi/xbox_live_context_settings.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +ref class PresenceService; + +class DevicePresenceChangeEventBind : public std::enable_shared_from_this +{ +public: + DevicePresenceChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::presence::presence_service& cppObj + ); + + void AddDevicePresenceChangeEvent(); + + void RemoveDevicePresenceChangeEvent( + _In_ xbox::services::presence::presence_service& cppObj + ); + + void DevicePresenceChangeRouter(_In_ const xbox::services::presence::device_presence_change_event_args& presenceChangeEventArgs); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + xbox::services::presence::presence_service m_cppObj; +}; + +class TitlePresenceChangeEventBind : public std::enable_shared_from_this +{ +public: + TitlePresenceChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::presence::presence_service& cppObj + ); + + void AddTitlePresenceChangeEvent(); + + void RemoveTitlePresenceChangeEvent( + _In_ xbox::services::presence::presence_service& cppObj + ); + + void TitlePresenceChangeRouter(_In_ const xbox::services::presence::title_presence_change_event_args& presenceChangeEventArgs); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + xbox::services::presence::presence_service m_cppObj; +}; + +/// +/// Represents a service for Rich Presence features. +/// +public ref class PresenceService sealed +{ +public: + /// + /// Registers for device presence change notifications. Event handlers will receive DevicePresenceChangeEventArgs^. + /// + event Windows::Foundation::EventHandler^ DevicePresenceChanged; + + /// + /// Registers for title presence change notifications. Event handlers will receive TitlePresenceChangeEventArgs^. + /// + event Windows::Foundation::EventHandler^ TitlePresenceChanged; + + /// + /// Sets presence info for the current user context. + /// + /// Indicates if the current user context is currently active or inactive in the title. + /// The application can choose to set this based on an amount of inactivity. + /// Calls V1 POST /users/xuid({xuid})/devices/current/titles/current + Windows::Foundation::IAsyncAction^ SetPresenceAsync( + _In_ bool isUserActiveInTitle + ); + + /// + /// Sets presence info for the current user context. + /// + /// Indicates if the current user context is currently active or inactive in the title. + /// The application can choose to set this based on an amount of inactivity. + /// Current user's presence data. (Optional) + /// Calls V1 POST /users/xuid({xuid})/devices/current/titles/current + Windows::Foundation::IAsyncAction^ SetPresenceAsync( + _In_ bool isUserActiveInTitle, + _In_opt_ PresenceData^ presenceData + ); + + /// + /// Gets presence info for a specific Xbox User Id. + /// + /// The Xbox User ID of the user to get presence for + /// Calls V3 GET /users/xuid({xuid}) + Windows::Foundation::IAsyncOperation^ GetPresenceAsync( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Gets presence info for multiple users. This returns all possible titles on all device, defaults to all detail, + /// and does not filter out users who are offline or broadcasting. + /// + /// The name of the users to get presence for. + /// Calls V3 POST /users/batch + Windows::Foundation::IAsyncOperation^>^ GetPresenceForMultipleUsersAsync( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ); + + /// + /// Gets presence info for multiple users with filters. + /// + /// The name of the users to get presence for. + /// List of device types. If the input is null; defaults to all possible deviceTypes. (Optional) + /// List of titleIds for filtering the result. If the input is null, defaults to all possible titles. (Optional) + /// Detail level of the result. Defaults to all details + /// If true, API will filter out records for users that are offline + /// If true, API will filter out records for users that are not broadcasting. + /// Calls V3 POST /users/batch + Windows::Foundation::IAsyncOperation^>^ GetPresenceForMultipleUsersAsync( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_opt_ Windows::Foundation::Collections::IVectorView^ deviceTypes, + _In_opt_ Windows::Foundation::Collections::IVectorView^ titleIds, + _In_ PresenceDetailLevel detailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + /// + /// Gets presence info for a specific group of users. + /// + /// The name of the group of users to get presence for. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// Calls V3 GET /users/xuid({xuid})/groups/{socialGroup} + Windows::Foundation::IAsyncOperation^>^ GetPresenceForSocialGroupAsync( + _In_ Platform::String^ socialGroup + ); + + /// + /// Gets presence info for a specific group of users. + /// + /// The name of the group of users to get presence for. + /// The user whose group should be targeted. If the input is null, current user will be used. (Optional) + /// List of device types. If the input is null; defaults to all possible deviceTypes. (Optional) + /// List of titleIds for filtering the result. If the input is null, defaults to all possible titles. (Optional) + /// Detail level of the result. Defaults to all details + /// If true, API will filter out records for users that are offline + /// If true, API will filter out records for users that are not broadcasting. + /// Calls V3 POST /users/batch + Windows::Foundation::IAsyncOperation^>^ GetPresenceForSocialGroupAsync( + _In_ Platform::String^ socialGroup, + _In_opt_ Platform::String^ socialGroupOwnerXboxuserId, + _In_opt_ Windows::Foundation::Collections::IVectorView^ deviceTypes, + _In_opt_ Windows::Foundation::Collections::IVectorView^ titleIds, + _In_ PresenceDetailLevel detailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + /// + /// Subscribes to device presence change notifications via the DevicePresenceChanged event + /// + /// The Xbox User ID of the person of the subscription + /// RealTimeActivityDevicePresenceChangeSubscription containing the initial value of the PresenceDeviceRecord + /// Register for device presence changes via the DevicePresenceChanged event + DevicePresenceChangeSubscription^ SubscribeToDevicePresenceChange( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Unsubscribes a previously created device presence change subscription + /// + /// The subscription object to unsubscribe + void UnsubscribeFromDevicePresenceChange( + _In_ DevicePresenceChangeSubscription^ subscription + ); + + /// + /// Subscribes to title presence change notifications via the TitlePresenceChanged event + /// + /// The Xbox User ID of the person of the subscription + /// The title ID of the subscription + /// RealTimeActivityDevicePresenceChangeSubscription containing the initial value of the PresenceDeviceRecord + /// Register for device presence changes via the DevicePresenceChanged event + TitlePresenceChangeSubscription^ SubscribeToTitlePresenceChange( + _In_ Platform::String^ xboxUserId, + _In_ uint32 titleId + ); + + /// + /// Unsubscribes a previously created title presence change subscription + /// + /// The subscription object to unsubscribe + void UnsubscribeFromTitlePresenceChange( + _In_ TitlePresenceChangeSubscription^ subscription + ); + +internal: + PresenceService(_In_ xbox::services::presence::presence_service cppObj); + void RaiseDevicePresenceChange(_In_ DevicePresenceChangeEventArgs^ args); + void RaiseTitlePresenceChange(_In_ TitlePresenceChangeEventArgs^ args); + + const xbox::services::presence::presence_service& GetCppObj() const; + +private: + ~PresenceService(); + xbox::services::presence::presence_service m_cppObj; + std::shared_ptr m_devicePresenceChangeEventBind; + std::shared_ptr m_titlePresenceChangeEventBind; +}; +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.cpp b/Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.cpp new file mode 100644 index 00000000..9d2428a7 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.cpp @@ -0,0 +1,29 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PresenceTitleRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +PresenceTitleRecord::PresenceTitleRecord( + _In_ xbox::services::presence::presence_title_record cppObj + ) : + m_cppObj(cppObj) +{ + m_broadcastRecord = ref new PresenceBroadcastRecord(m_cppObj.broadcast_record()); +} + +PresenceBroadcastRecord^ +PresenceTitleRecord::BroadcastRecord::get() +{ + return m_broadcastRecord; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.h b/Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.h new file mode 100644 index 00000000..2425a774 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceTitleRecord_WinRT.h @@ -0,0 +1,67 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceDeviceType_WinRT.h" +#include "PresenceTitleViewState_WinRT.h" +#include "PresenceBroadcastRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN +/// +/// Represents a record containing data about title presence. +/// + +public ref class PresenceTitleRecord sealed +{ +public: + /// + /// The title ID. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The title name. + /// + DEFINE_PROP_GET_STR_OBJ(TitleName, title_name); + + /// + /// The UTC timestamp when the record was last updated. + /// + DEFINE_PROP_GET_DATETIME_OBJ(LastModifiedDate, last_modified_date); + + /// + /// The active state for the title. + /// + DEFINE_PROP_GET_OBJ(IsTitleActive, is_title_active, bool); + + /// + /// The formatted and localized presence string. + /// + DEFINE_PROP_GET_STR_OBJ(Presence, presence); + + /// + /// The title view state. + /// + DEFINE_PROP_GET_ENUM_OBJ(TitleViewState, presence_title_view, PresenceTitleViewState); + + /// + /// The broadcast information of what the user is broadcasting. + /// + property PresenceBroadcastRecord^ BroadcastRecord { PresenceBroadcastRecord^ get(); } + +internal: + PresenceTitleRecord(_In_ xbox::services::presence::presence_title_record cppObj); + +private: + xbox::services::presence::presence_title_record m_cppObj; + PresenceBroadcastRecord^ m_broadcastRecord; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/PresenceTitleViewState_WinRT.h b/Source/Services/Presence/WinRT/PresenceTitleViewState_WinRT.h new file mode 100644 index 00000000..024635e2 --- /dev/null +++ b/Source/Services/Presence/WinRT/PresenceTitleViewState_WinRT.h @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// Defines values that indicate the title's view state as last reported to the Presence Service. +public enum class PresenceTitleViewState +{ + /// Unknown view state. + Unknown = xbox::services::presence::presence_title_view_state::unknown, + + /// The title's view is using the full screen. + FullScreen = xbox::services::presence::presence_title_view_state::full_screen, + + /// The title's view is using part of the screen with another application snapped. + Filled = xbox::services::presence::presence_title_view_state::filled, + + /// The title's view is snapped with another application using a part of the screen. + Snapped = xbox::services::presence::presence_title_view_state::snapped, + + /// The title's running in the background and is not visible. + Background = xbox::services::presence::presence_title_view_state::background +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.cpp b/Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.cpp new file mode 100644 index 00000000..a6397f8e --- /dev/null +++ b/Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.cpp @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TitlePresenceChangeEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +TitlePresenceChangeEventArgs::TitlePresenceChangeEventArgs( + _In_ xbox::services::presence::title_presence_change_event_args cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.h b/Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.h new file mode 100644 index 00000000..234fd2f2 --- /dev/null +++ b/Source/Services/Presence/WinRT/TitlePresenceChangeEventArgs_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceRecord_WinRT.h" +#include "TitlePresenceState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// +/// Contains information about a title presence change event. +/// +public ref class TitlePresenceChangeEventArgs sealed +{ +public: + /// + /// The Xbox user ID for the user present on the device. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The ID for the title that uses the subscription. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32); + + /// + /// The new title presence state. + /// + DEFINE_PROP_GET_ENUM_OBJ(TitleState, title_state, TitlePresenceState); + +internal: + TitlePresenceChangeEventArgs(_In_ xbox::services::presence::title_presence_change_event_args cppObj); + +private: + xbox::services::presence::title_presence_change_event_args m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.cpp b/Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.cpp new file mode 100644 index 00000000..3a5b09c7 --- /dev/null +++ b/Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.cpp @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TitlePresenceChangeSubscription_WinRT.h" + +using namespace Microsoft::Xbox::Services::RealTimeActivity; +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +TitlePresenceChangeSubscription::TitlePresenceChangeSubscription( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +RealTimeActivitySubscriptionState +TitlePresenceChangeSubscription::State::get() +{ + return static_cast(m_cppObj->state()); +} + +std::shared_ptr +TitlePresenceChangeSubscription::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.h b/Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.h new file mode 100644 index 00000000..7d6178a5 --- /dev/null +++ b/Source/Services/Presence/WinRT/TitlePresenceChangeSubscription_WinRT.h @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" +#include "PresenceRecord_WinRT.h" +#include "RealTimeActivitySubscriptionState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// +/// Contains information about a title presence subscription. +/// +public ref class TitlePresenceChangeSubscription sealed +{ +public: + /// + /// The current state of the subscription. + /// + property Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState State{ Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState get(); } + + /// + /// The resource uri for the request. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ResourceUri, resource_uri); + + /// + /// The unique subscription id for the request. + /// + DEFINE_PTR_PROP_GET_OBJ(SubscriptionId, subscription_id, uint32_t); + + /// + /// The xbox user id the subscription is for + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The title for the subscription + /// + DEFINE_PTR_PROP_GET_OBJ(TitleId, title_id, uint32_t); + +internal: + TitlePresenceChangeSubscription(_In_ std::shared_ptr cppObj); + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/TitlePresenceState_WinRT.h b/Source/Services/Presence/WinRT/TitlePresenceState_WinRT.h new file mode 100644 index 00000000..ad6b666a --- /dev/null +++ b/Source/Services/Presence/WinRT/TitlePresenceState_WinRT.h @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// Defines values that indicate the title presence state for a user. +public enum class TitlePresenceState +{ + /// + /// Indicates this is a Unknown state. + /// + Unknown = xbox::services::presence::title_presence_state::unknown, + + /// + /// Indicates the user started playing the title. + /// + Started = xbox::services::presence::title_presence_state::started, + + /// + /// Indicates the user ended playing the title. + /// + Ended = xbox::services::presence::title_presence_state::ended +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/WinRT/UserPresenceState_WinRT.h b/Source/Services/Presence/WinRT/UserPresenceState_WinRT.h new file mode 100644 index 00000000..74839357 --- /dev/null +++ b/Source/Services/Presence/WinRT/UserPresenceState_WinRT.h @@ -0,0 +1,31 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_BEGIN + +/// Defines values that indicate the user presence state on Xbox Live. +public enum class UserPresenceState +{ + /// The state is unknown. + Unknown = xbox::services::presence::user_presence_state::unknown, + + /// User is signed in to Xbox LIVE and active in a title. + Online = xbox::services::presence::user_presence_state::online, + + /// User is signed-in to Xbox LIVE, but inactive in all titles. + Away = xbox::services::presence::user_presence_state::away, + + /// User is not signed in to Xbox LIVE. + Offline = xbox::services::presence::user_presence_state::offline +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Presence/device_presence_change_event_args.cpp b/Source/Services/Presence/device_presence_change_event_args.cpp new file mode 100644 index 00000000..f2d5c2d9 --- /dev/null +++ b/Source/Services/Presence/device_presence_change_event_args.cpp @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +device_presence_change_event_args::device_presence_change_event_args() : + m_deviceType(presence_device_type::unknown), + m_isUserLoggedOnDevice(false) +{ +} + +device_presence_change_event_args::device_presence_change_event_args( + _In_ string_t xboxUserId, + _In_ presence_device_type deviceType, + _In_ bool isUserLoggedOnDevice + ) : + m_xboxUserId(std::move(xboxUserId)), + m_deviceType(deviceType), + m_isUserLoggedOnDevice(isUserLoggedOnDevice) +{ +} + +const string_t& +device_presence_change_event_args::xbox_user_id() const +{ + return m_xboxUserId; +} + +presence_device_type +device_presence_change_event_args::device_type() const +{ + return m_deviceType; +} + +bool +device_presence_change_event_args::is_user_logged_on_device() const +{ + return m_isUserLoggedOnDevice; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/device_presence_change_subscription.cpp b/Source/Services/Presence/device_presence_change_subscription.cpp new file mode 100644 index 00000000..db2b6ed8 --- /dev/null +++ b/Source/Services/Presence/device_presence_change_subscription.cpp @@ -0,0 +1,154 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +device_presence_change_subscription::device_presence_change_subscription( + _In_ string_t xboxUserId, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ) : + real_time_activity_subscription(subscriptionErrorHandler), + m_xboxUserId(std::move(xboxUserId)), + m_devicePresenceChangeHandler(handler) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + XSAPI_ASSERT(handler != nullptr); + + stringstream_t uri; + uri << _T("https://userpresence.xboxlive.com/users/xuid(") << m_xboxUserId << _T(")/devices"); + + m_resourceUri = uri.str(); +} + +void +device_presence_change_subscription::on_subscription_created( + _In_ uint32_t id, + _In_ const web::json::value& data + ) +{ + real_time_activity_subscription::on_subscription_created(id, data); + xbox_live_result devicePresenceChangeArgs; + + if (!data.is_null()) + { + auto initialPresenceRecord = presence_record::_Deserialize(data); + + if (!initialPresenceRecord.err()) + { + if (m_devicePresenceChangeHandler != nullptr) + { + for (const auto& deviceRecord : initialPresenceRecord.payload().presence_device_records()) + { + auto deviceType = deviceRecord.device_type(); + + m_devicePresenceChangeHandler( + device_presence_change_event_args( + m_xboxUserId, + deviceType, + true + ) + ); + } + } + } + else + { + if (m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON Deserialization Failure" + ) + ); + } + } + } + else + { + if (m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON Not Found" + ) + ); + } + } +} + +void +device_presence_change_subscription::on_event_received( + _In_ const web::json::value& data + ) +{ + std::error_code errc; + auto dataAsString = utils::extract_json_as_string(data, errc); + xbox_live_result eventArgs; + if (!errc) + { + std::vector devicePresenceValues = utils::string_split(dataAsString, ':'); + + if (devicePresenceValues.size() != 2) + { + if (m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON deserialization failed" + ) + ); + } + + return; + } + + if (m_devicePresenceChangeHandler != nullptr) + { + m_devicePresenceChangeHandler( + device_presence_change_event_args( + m_xboxUserId, + presence_device_record::_Convert_string_to_presence_device_type(devicePresenceValues[0]), + utils::str_icmp(devicePresenceValues[1], _T("true")) == 0 + ) + ); + } + } + else + { + if (m_subscriptionErrorHandler != nullptr) + { + LOG_DEBUG("device_presence_change_subscription error happened"); + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON deserialization failed" + ) + ); + } + } +} + +const string_t& +device_presence_change_subscription::xbox_user_id() const +{ + return m_xboxUserId; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/media_presence_data.cpp b/Source/Services/Presence/media_presence_data.cpp new file mode 100644 index 00000000..5f3464a0 --- /dev/null +++ b/Source/Services/Presence/media_presence_data.cpp @@ -0,0 +1,72 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "presence_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +media_presence_data::media_presence_data() : + m_shouldSerialize(false) +{ +} + +media_presence_data::media_presence_data( + _In_ string_t mediaId, + _In_ presence_media_id_type mediaIdType + ) : + m_mediaId(std::move(mediaId)), + m_presenceMediaIdType(mediaIdType), + m_shouldSerialize(true) +{ + XSAPI_ASSERT(!m_mediaId.empty()); + XSAPI_ASSERT( + m_presenceMediaIdType > presence_media_id_type::bing && + m_presenceMediaIdType < presence_media_id_type::media_provider + ); +} + +bool +media_presence_data::should_serialize() const +{ + return m_shouldSerialize; +} + +const string_t& +media_presence_data::media_id() const +{ + return m_mediaId; +} + +const presence_media_id_type +media_presence_data::media_id_type() const +{ + return m_presenceMediaIdType; +} + +web::json::value +media_presence_data::serialize() const +{ + web::json::value serializedObject; + serializedObject[_T("id")] = web::json::value::string(m_mediaId); + + if (m_presenceMediaIdType == presence_media_id_type::bing) + { + serializedObject[_T("idType")] = web::json::value::string(_T("bing")); + } + else if (m_presenceMediaIdType == presence_media_id_type::media_provider) + { + serializedObject[_T("idType")] = web::json::value::string(_T("provider")); + } + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_activity_data.cpp b/Source/Services/Presence/presence_activity_data.cpp new file mode 100644 index 00000000..01d92484 --- /dev/null +++ b/Source/Services/Presence/presence_activity_data.cpp @@ -0,0 +1,55 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "utils.h" +#include "presence_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_activity_data::presence_activity_data() : + m_shouldSerialize(false) +{ +} + +presence_activity_data::presence_activity_data( + _In_ presence_data presenceData, + _In_ media_presence_data mediaPresenceData + ) : + m_presenceData(std::move(presenceData)), + m_mediaPresenceData(std::move(mediaPresenceData)) +{ + m_shouldSerialize = (m_presenceData._Should_serialize() || m_mediaPresenceData.should_serialize()); +} + +bool +presence_activity_data::should_serialize() const +{ + return m_shouldSerialize; +} + +web::json::value +presence_activity_data::serialize() const +{ + web::json::value serializedObject; + + if (m_presenceData._Should_serialize()) + { + serializedObject[_T("richPresence")] = m_presenceData._Serialize(); + } + if (m_mediaPresenceData.should_serialize()) + { + serializedObject[_T("media")] = m_mediaPresenceData.serialize(); + } + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_broadcast_record.cpp b/Source/Services/Presence/presence_broadcast_record.cpp new file mode 100644 index 00000000..2f4d3be6 --- /dev/null +++ b/Source/Services/Presence/presence_broadcast_record.cpp @@ -0,0 +1,88 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_broadcast_record::presence_broadcast_record(): + m_viewerCount(0) +{ +} + +const string_t& +presence_broadcast_record::broadcast_id() const +{ + return m_broadcastId; +} + +const string_t& +presence_broadcast_record::session() const +{ + return m_session; +} + +const string_t& +presence_broadcast_record::provider() const +{ + return m_provider; +} + +uint32_t +presence_broadcast_record::viewer_count() const +{ + return m_viewerCount; +} + +const utility::datetime& +presence_broadcast_record::start_time() const +{ + return m_startTime; +} + +bool presence_broadcast_record::operator!=( + _In_ const presence_broadcast_record& rhs + ) const +{ + if ( + m_broadcastId != rhs.m_broadcastId || + m_provider != rhs.m_provider || + m_session != rhs.m_session || + m_startTime != rhs.m_startTime || + m_viewerCount != rhs.m_viewerCount + ) + { + return true; + } + + return false; +} + +xbox_live_result +presence_broadcast_record::_Deserialize( + _In_ const web::json::value& inputJson + ) +{ + presence_broadcast_record returnObject; + if (inputJson.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + returnObject.m_broadcastId = utils::extract_json_string(inputJson, _T("id"), errc); + returnObject.m_session = utils::extract_json_string(inputJson, _T("session"), errc); + returnObject.m_provider = utils::extract_json_string(inputJson, _T("provider"), errc); + returnObject.m_viewerCount = utils::extract_json_int(inputJson, _T("viewers"), errc); + returnObject.m_startTime = utils::extract_json_time(inputJson, _T("started"), errc); + + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_data.cpp b/Source/Services/Presence/presence_data.cpp new file mode 100644 index 00000000..c49512e4 --- /dev/null +++ b/Source/Services/Presence/presence_data.cpp @@ -0,0 +1,92 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_data::presence_data() : + m_shouldSerialize(false) +{ +} + +presence_data::presence_data( + _In_ string_t serviceConfigurationId, + _In_ string_t presenceId + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_presenceId(std::move(presenceId)), + m_shouldSerialize(true) +{ + XSAPI_ASSERT(!m_serviceConfigurationId.empty()); + XSAPI_ASSERT(!m_presenceId.empty()); +} + +presence_data::presence_data( + _In_ string_t serviceConfigurationId, + _In_ string_t presenceId, + _In_ std::vector presenceTokenIds + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_presenceId(std::move(presenceId)), + m_presenceTokenIds(std::move(presenceTokenIds)), + m_shouldSerialize(true) +{ + XSAPI_ASSERT(!m_serviceConfigurationId.empty()); + XSAPI_ASSERT(!m_presenceId.empty()); + XSAPI_ASSERT(!m_presenceTokenIds.empty()); +#ifndef NDEBUG + for (const auto& token : m_presenceTokenIds) + { + XSAPI_ASSERT(!token.empty()); + } +#endif +} + +const string_t& +presence_data::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const string_t& +presence_data::presence_id() const +{ + return m_presenceId; +} + +bool +presence_data::_Should_serialize() const +{ + return m_shouldSerialize; +} + +const std::vector& +presence_data::presence_token_ids() const +{ + return m_presenceTokenIds; +} + +web::json::value +presence_data::_Serialize() const +{ + web::json::value serializedObject; + + serializedObject[_T("id")] = web::json::value::string(m_presenceId); + serializedObject[_T("scid")] = web::json::value::string(m_serviceConfigurationId); + if (!m_presenceTokenIds.empty()) + { + serializedObject[_T("params")] = utils::serialize_vector(utils::json_string_serializer, m_presenceTokenIds); + } + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_device_record.cpp b/Source/Services/Presence/presence_device_record.cpp new file mode 100644 index 00000000..ad336ffe --- /dev/null +++ b/Source/Services/Presence/presence_device_record.cpp @@ -0,0 +1,203 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_device_record::presence_device_record() +{ +} + +presence_device_record::presence_device_record( + _In_ presence_device_type deviceType + ) : + m_deviceType(deviceType) +{ +} + +presence_device_type +presence_device_record::device_type() const +{ + return m_deviceType; +} + +const std::vector& +presence_device_record::presence_title_records() const +{ + return m_presenceTitleRecords; +} + +bool presence_device_record::operator!=( + _In_ const presence_device_record& rhs + ) +{ + if (m_presenceTitleRecords.size() != rhs.m_presenceTitleRecords.size()) + { + return true; + } + + auto lhsTitleMap = create_map_from_title_records(m_presenceTitleRecords); + auto rhsTitleMap = create_map_from_title_records(rhs.m_presenceTitleRecords); + for (const auto& lhsTitlePair : lhsTitleMap) + { + if (rhsTitleMap.find(lhsTitlePair.first) == rhsTitleMap.end() || lhsTitlePair.second != rhsTitleMap[lhsTitlePair.first]) + { + return true; + } + } + + for (const auto& rhsTitlePair : rhsTitleMap) + { + if (lhsTitleMap.find(rhsTitlePair.first) == lhsTitleMap.end()) + { + return true; + } + } + + return false; +} + +presence_device_type +presence_device_record::_Convert_string_to_presence_device_type( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("WindowsPhone")) == 0) + { + return presence_device_type::windows_phone; + } + else if (utils::str_icmp(value, _T("WindowsPhone7")) == 0) + { + return presence_device_type::windows_phone_7; + } + else if (utils::str_icmp(value, _T("Web")) == 0) + { + return presence_device_type::web; + } + else if (utils::str_icmp(value, _T("Xbox360")) == 0) + { + return presence_device_type::xbox_360; + } + else if (utils::str_icmp(value, _T("PC")) == 0) + { + return presence_device_type::pc; + } + else if (utils::str_icmp(value, _T("MoLive")) == 0) + { + return presence_device_type::windows_8; + } + else if (utils::str_icmp(value, _T("XboxOne")) == 0 || + utils::str_icmp(value, _T("MCapensis")) == 0) + { + return presence_device_type::xbox_one; + } + else if (utils::str_icmp(value, _T("WindowsOneCore")) == 0) + { + return presence_device_type::windows_one_core; + } + else if (utils::str_icmp(value, _T("WindowsOneCoreMobile")) == 0) + { + return presence_device_type::windows_one_core_mobile; + } + + return presence_device_type::unknown; +} + +string_t +presence_device_record::_Convert_presence_device_type_to_string( + _In_ presence_device_type deviceType + ) +{ + switch (deviceType) + { + case presence_device_type::windows_phone: + return _T("WindowsPhone"); + + case presence_device_type::windows_phone_7: + return _T("WindowsPhone7"); + + case presence_device_type::web: + return _T("Web"); + + case presence_device_type::xbox_360: + return _T("Xbox360"); + + case presence_device_type::pc: + return _T("PC"); + + case presence_device_type::windows_8: + return _T("MoLive"); + + case presence_device_type::xbox_one: + return _T("XboxOne"); + + case presence_device_type::windows_one_core: + return _T("WindowsOneCore"); + + case presence_device_type::windows_one_core_mobile: + return _T("WindowsOneCoreMobile"); + + default: + return string_t(); + } +} + +std::unordered_map +presence_device_record::create_map_from_title_records( + _In_ const std::vector& titleRecords + ) const +{ + std::unordered_map returnMap; + for (const auto& titleRecord : titleRecords) + { + returnMap[titleRecord.title_id()] = titleRecord; + } + + return returnMap; +} + +void +presence_device_record::_Add_title_record( + _In_ uint32_t titleId, + _In_ title_presence_state titlePresenceState + ) +{ + presence_title_record presenceTitleRecord(titleId, titlePresenceState); + m_presenceTitleRecords.push_back(presenceTitleRecord); +} + +xbox_live_result +presence_device_record::_Deserialize( + _In_ const web::json::value& inputJson + ) +{ + presence_device_record returnObject; + if (inputJson.is_null()) return xbox_live_result(returnObject); + std::error_code errc = xbox_live_error_code::no_error; + + presence_device_type type = _Convert_string_to_presence_device_type( + utils::extract_json_string(inputJson, _T("type"), errc) + ); + + returnObject.m_presenceTitleRecords = utils::extract_json_vector( + presence_title_record::_Deserialize, + inputJson, + _T("titles"), + errc, + false + ); + + returnObject.m_deviceType = type; + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_internal.h b/Source/Services/Presence/presence_internal.h new file mode 100644 index 00000000..f2c835e4 --- /dev/null +++ b/Source/Services/Presence/presence_internal.h @@ -0,0 +1,307 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "system_internal.h" + +namespace xbox { namespace services { namespace presence { + +/// +/// Represents media supporting Rich Presence features. +/// +class media_presence_data +{ +public: + /// + /// Initializes a new instance of the MediaPresenceData class. + /// + /// Id of the media used by the Bing catalog or the MediaProvider catalog. + /// Type of the mediaId parameter. The type identifies how the service should interpret the Id. + media_presence_data( + _In_ string_t mediaId, + _In_ presence_media_id_type mediaIdType + ); + + /// + /// ID of the media being consumed. + /// + const string_t& media_id() const; + + /// + /// The type of MediaId. This will be MediaIdType::Bing for Xbox media, or MediaIdType::MediaPlatform for others. + /// + const presence_media_id_type media_id_type() const; + + media_presence_data(); + + bool should_serialize() const; + web::json::value serialize() const; + +private: + string_t m_mediaId; + presence_media_id_type m_presenceMediaIdType; + bool m_shouldSerialize; +}; + +class presence_activity_data +{ +public: + presence_activity_data(); + + /// + /// Represents activity data supporting Rich Presence features. + /// + ///Identifies a string used to indicate presence. + ///Identifies a string used to indicate media presence. + presence_activity_data( + _In_ presence_data presenceData, + _In_ media_presence_data mediaPresenceData + ); + + bool should_serialize() const; + + web::json::value serialize() const; + +private: + presence_data m_presenceData; + media_presence_data m_mediaPresenceData; + bool m_shouldSerialize; +}; + +class presence_user_batch_request +{ +public: + /// + /// Retrieves the current presence data for multiple users or a specific social group with additional options to scope results. + /// + /// A list of Xbox user IDs. + /// A specific social group. + /// The Xbox user ID of the social group owner. + /// The device types to return presence data for. + /// The title IDs to return presence data for. + /// Value indicating the level of granularity in returned presence data + /// Indicates if returned values are scoped to users that are online. + /// Indicates if returned values are scoped to users that are currently broadcasting. + presence_user_batch_request( + _In_ std::vector xboxUserIds, + _In_ string_t socialGroup, + _In_ string_t socialGroupOwnerXboxUserId, + _In_ std::vector deviceTypes, + _In_ std::vector titleIds, + _In_ presence_detail_level presenceDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + static string_t convert_detail_level_to_string( + _In_ presence_detail_level level + ); + web::json::value serialize() const; + +private: + std::vector m_xboxUserIds; + string_t m_socialGroup; + string_t m_socialGroupOwnerXboxUserId; + std::vector m_deviceTypes; + std::vector m_titleIds; + presence_detail_level m_presenceDetailLevel; + bool m_onlineOnly; + bool m_broadcastingOnly; +}; + +class presence_title_request +{ +public: + /// + /// Retrieves the current user presence data. + /// + /// Indicates if the user is active. + /// Contains current user presence data. + /// Contains current media presence data. + presence_title_request( + _In_ bool isUserActive, + _In_ presence_data presenceData = presence_data(), + _In_ media_presence_data mediaPresenceData = media_presence_data() + ); + + web::json::value serialize(); + +private: + bool m_isUserActive; + presence_activity_data m_presenceActivityData; +}; + +class presence_service_impl : public std::enable_shared_from_this +{ +public: + presence_service_impl( + _In_ std::shared_ptr realTimeActivityService, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + xbox_live_result> subscribe_to_title_presence_change( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId + ); + + xbox_live_result unsubscribe_from_title_presence_change( + _In_ std::shared_ptr subscription + ); + + function_context add_title_presence_changed_handler(_In_ std::function handler); + + void remove_title_presence_changed_handler(_In_ function_context context); + + xbox_live_result> subscribe_to_device_presence_change( + _In_ const string_t& xboxUserId + ); + + xbox_live_result unsubscribe_from_device_presence_change( + _In_ std::shared_ptr subscription + ); + + function_context add_device_presence_changed_handler( + _In_ std::function handler + ); + + void remove_device_presence_changed_handler( + _In_ function_context context + ); + + pplx::task> set_presence( + _In_ bool isUserActiveInTitle + ); + + pplx::task> set_presence( + _In_ bool isUserActiveInTitle, + _In_ presence_data presenceData + ); + + pplx::task> get_presence( + _In_ const string_t& xboxUserId + ); + + pplx::task>> get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds + ); + + pplx::task>> get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level presenceDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + pplx::task>> get_presence_for_social_group( + _In_ const string_t& socialGroup + ); + + pplx::task>> get_presence_for_social_group( + _In_ const string_t& socialGroup, + _In_ const string_t& socialGroupOwnerXboxUserId, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level peoplehubDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ); + + std::shared_ptr _Xbox_live_context_settings() { return m_xboxLiveContextSettings; } + + ~presence_service_impl(); + + // test hook + static void set_presence_set_finished_handler(const std::function& onSetPresenceFinish) { s_onSetPresenceFinish = onSetPresenceFinish; } + + +private: + string_t set_presence_sub_path( + _In_ const string_t& xboxUserId + ); + + string_t get_presence_sub_path( + _In_ const string_t& xboxUserId + ); + + string_t get_presence_user_batch_subpath(); + + string_t get_presence_for_social_group_subpath( + _In_ const string_t& xboxUserId, + _In_ const string_t& socialGroup + ); + + pplx::task> set_presence_helper( + _In_ bool isUserActiveInTitle, + _In_ presence_data presenceData + ); + + static std::function s_onSetPresenceFinish; + + void device_presence_changed(_In_ const device_presence_change_event_args& eventArgs); + void title_presence_changed(_In_ const title_presence_change_event_args& eventArgs); + + xbox::services::system::xbox_live_mutex m_titlePresenceChangeHandlerLock; + xbox::services::system::xbox_live_mutex m_devicePresenceChangeHandlerLock; + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + + std::shared_ptr m_realTimeActivityService; + std::unordered_map> m_devicePresenceChangeHandler; + std::unordered_map> m_titlePresenceChangeHandler; + function_context m_devicePresenceChangeHandlerCounter; + function_context m_titlePresenceChangeHandlerCounter; + + friend class presence_writer; +}; + +#if !TV_API + +class presence_writer : public std::enable_shared_from_this +{ +public: + static std::shared_ptr get_presence_writer_singleton(); + presence_writer(); + + void start_writer(_In_ std::shared_ptr presenceServiceImpl); + void stop_writer(_In_ const string_t& xboxLiveUserId); + void handle_timer_trigger(); + + void set_inactive_in_title(_In_ std::shared_ptr presenceServiceImpl); + void set_active_in_title(); + + static const uint32_t s_defaultHeartBeatDelayInMins = 5; + + size_t tracking_count() { return m_presenceServices.size(); } + +private: + void start_timer(_In_ std::weak_ptr thisWeakPtr); + + xbox::services::system::xbox_live_mutex m_lock; + bool m_writerInProgress; + std::unordered_map> m_presenceServices; + int m_heartBeatDelayInMins; + +#ifdef __cplusplus_winrt + Windows::System::Threading::ThreadPoolTimer^ m_timer; +#else + bool m_timerComplete; +#endif + + std::atomic m_isCallInProgress; + +}; +#endif + +}}} \ No newline at end of file diff --git a/Source/Services/Presence/presence_media_record.cpp b/Source/Services/Presence/presence_media_record.cpp new file mode 100644 index 00000000..18561f78 --- /dev/null +++ b/Source/Services/Presence/presence_media_record.cpp @@ -0,0 +1,73 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_media_record::presence_media_record() : + m_mediaIdType(presence_media_id_type::unknown) +{ +} + +const string_t& +presence_media_record::media_id() const +{ + return m_mediaId; +} + +presence_media_id_type +presence_media_record::media_id_type() const +{ + return m_mediaIdType; +} + +const string_t& +presence_media_record::name() const +{ + return m_name; +} + +xbox_live_result +presence_media_record::_Deserialize( + _In_ const web::json::value& inputJson + ) +{ + presence_media_record returnObject; + if (inputJson.is_null()) return xbox_live_result(returnObject); + + returnObject.m_mediaId = utils::extract_json_string(inputJson, _T("id")); + returnObject.m_mediaIdType = _Convert_string_to_media_id_type( + utils::extract_json_string(inputJson, _T("idType")) + ); + returnObject.m_name = utils::extract_json_string(inputJson, _T("name")); + + return returnObject; +} + +presence_media_id_type +presence_media_record::_Convert_string_to_media_id_type( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("bing")) == 0) + { + return presence_media_id_type::bing; + } + else if (utils::str_icmp(value, _T("provider")) == 0) + { + return presence_media_id_type::media_provider; + } + + return presence_media_id_type::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_record.cpp b/Source/Services/Presence/presence_record.cpp new file mode 100644 index 00000000..72c4d437 --- /dev/null +++ b/Source/Services/Presence/presence_record.cpp @@ -0,0 +1,115 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if TV_API || UWP_API || UNIT_TEST_SERVICES +#include "social_manager_internal.h" +#endif +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_record::presence_record(): + m_userState(user_presence_state::unknown) +{ +} + +const string_t& +presence_record::xbox_user_id() const +{ + return m_xboxUserId; +} + +user_presence_state +presence_record::user_state() const +{ + return m_userState; +} + +const std::vector& +presence_record::presence_device_records() const +{ + return m_presenceDeviceRecords; +} + +xbox_live_result +presence_record::_Deserialize( + _In_ const web::json::value& json + ) +{ + presence_record returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + returnObject.m_xboxUserId = utils::extract_json_string(json, _T("xuid"), errc); + returnObject.m_userState = _Convert_string_to_user_presence_state( + utils::extract_json_string(json, _T("state"), errc) + ); + + returnObject.m_presenceDeviceRecords = utils::extract_json_vector( + presence_device_record::_Deserialize, + json, + _T("devices"), + errc, + false + ); + + return xbox_live_result(returnObject, errc); +} + +bool +presence_record::is_user_playing_title( + _In_ uint32_t titleId + ) const +{ + if (m_userState == user_presence_state::offline || m_userState == user_presence_state::unknown) + { + return false; + } + + for (const auto& deviceRecord : m_presenceDeviceRecords) + { + for (const auto& titleRecord : deviceRecord.presence_title_records()) + { + if (titleRecord.title_id() == titleId && titleRecord.is_title_active()) + { + return true; + } + else if (titleRecord.title_id() == titleId) + { + return false; + } + } + } + + return false; +} + +user_presence_state +presence_record::_Convert_string_to_user_presence_state( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("Online")) == 0) + { + return user_presence_state::online; + } + else if (utils::str_icmp(value, _T("Away")) == 0) + { + return user_presence_state::away; + } + else if (utils::str_icmp(value, _T("Offline")) == 0) + { + return user_presence_state::offline; + } + + return user_presence_state::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_service.cpp b/Source/Services/Presence/presence_service.cpp new file mode 100644 index 00000000..143f232c --- /dev/null +++ b/Source/Services/Presence/presence_service.cpp @@ -0,0 +1,208 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "utils.h" +#include "presence_internal.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_service::presence_service() +{ +} + +presence_service::presence_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivityService + ) : + m_presenceServiceImpl(std::make_shared( + realTimeActivityService, + userContext, + xboxLiveContextSettings, + appConfig)) +{ +} + +task> +presence_service::set_presence( + _In_ bool isUserActiveInTitle + ) +{ + return m_presenceServiceImpl->set_presence(isUserActiveInTitle); +} + +task> +presence_service::set_presence( + _In_ bool isUserActiveInTitle, + _In_ presence_data presenceData + ) +{ + return m_presenceServiceImpl->set_presence(isUserActiveInTitle, presenceData); +} + +std::shared_ptr +presence_service::_Xbox_live_context_settings() +{ + return m_presenceServiceImpl->_Xbox_live_context_settings(); +} + +task> +presence_service::get_presence( + _In_ const string_t& xboxUserId + ) +{ + return m_presenceServiceImpl->get_presence(xboxUserId); +} + +task>> +presence_service::get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds + ) +{ + return m_presenceServiceImpl->get_presence_for_multiple_users(xboxUserIds); +} + +task>> +presence_service::get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level presenceDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) +{ + return m_presenceServiceImpl->get_presence_for_multiple_users( + xboxUserIds, + deviceTypes, + titleIds, + presenceDetailLevel, + onlineOnly, + broadcastingOnly + ); +} + +task>> +presence_service::get_presence_for_social_group( + _In_ const string_t& socialGroup + ) +{ + return m_presenceServiceImpl->get_presence_for_social_group(socialGroup); +} + +task>> +presence_service::get_presence_for_social_group( + _In_ const string_t& socialGroup, + _In_ const string_t& socialGroupOwnerXboxUserId, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level peoplehubDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) +{ + return m_presenceServiceImpl->get_presence_for_social_group( + socialGroup, + socialGroupOwnerXboxUserId, + deviceTypes, + titleIds, + peoplehubDetailLevel, + onlineOnly, + broadcastingOnly + ); +} + +function_context +presence_service::add_device_presence_changed_handler( + _In_ std::function handler + ) +{ + return m_presenceServiceImpl->add_device_presence_changed_handler( + handler + ); +} + +void +presence_service::remove_device_presence_changed_handler( + _In_ function_context context + ) +{ + return m_presenceServiceImpl->remove_device_presence_changed_handler( + context + ); +} + +function_context +presence_service::add_title_presence_changed_handler( + _In_ std::function handler + ) +{ + return m_presenceServiceImpl->add_title_presence_changed_handler( + handler + ); +} + +void +presence_service::remove_title_presence_changed_handler( + _In_ function_context context + ) +{ + m_presenceServiceImpl->remove_title_presence_changed_handler( + context + ); +} + +xbox_live_result> +presence_service::subscribe_to_device_presence_change( + _In_ const string_t& xboxUserId + ) +{ + return m_presenceServiceImpl->subscribe_to_device_presence_change( + xboxUserId + ); +} + +xbox_live_result +presence_service::unsubscribe_from_device_presence_change( + _In_ std::shared_ptr subscription + ) +{ + return m_presenceServiceImpl->unsubscribe_from_device_presence_change( + subscription + ); +} + +xbox_live_result> +presence_service::subscribe_to_title_presence_change( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId + ) +{ + return m_presenceServiceImpl->subscribe_to_title_presence_change( + xboxUserId, + titleId + ); +} + +xbox_live_result +presence_service::unsubscribe_from_title_presence_change( + _In_ std::shared_ptr subscription + ) +{ + return m_presenceServiceImpl->unsubscribe_from_title_presence_change( + subscription + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_service_impl.cpp b/Source/Services/Presence/presence_service_impl.cpp new file mode 100644 index 00000000..43094830 --- /dev/null +++ b/Source/Services/Presence/presence_service_impl.cpp @@ -0,0 +1,638 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "xsapi/system.h" +#include "presence_internal.h" +#include "user_context.h" +#include "xbox_system_factory.h" + +using namespace pplx; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +std::function presence_service_impl::s_onSetPresenceFinish; + +presence_service_impl::presence_service_impl( + _In_ std::shared_ptr realTimeActivityService, + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_realTimeActivityService(realTimeActivityService), + m_devicePresenceChangeHandlerCounter(0), + m_titlePresenceChangeHandlerCounter(0), + m_userContext(userContext), + m_xboxLiveContextSettings(xboxLiveContextSettings), + m_appConfig(appConfig) +{ +} + +presence_service_impl::~presence_service_impl() +{ + m_devicePresenceChangeHandler.clear(); + m_titlePresenceChangeHandler.clear(); +} + +function_context +presence_service_impl::add_device_presence_changed_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_devicePresenceChangeHandlerLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_devicePresenceChangeHandlerCounter; + m_devicePresenceChangeHandler[m_devicePresenceChangeHandlerCounter] = std::move(handler); + } + + return context; +} + +void +presence_service_impl::remove_device_presence_changed_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_devicePresenceChangeHandlerLock.get()); + + m_devicePresenceChangeHandler.erase(context); +} + +pplx::task> +presence_service_impl::set_presence( + _In_ bool isUserActiveInTitle + ) +{ + return set_presence_helper(isUserActiveInTitle, presence_data()) + .then([](xbox_live_result result) + { + return xbox_live_result(result.err(), result.err_message()); + }); +} + +pplx::task> +presence_service_impl::set_presence( + _In_ bool isUserActiveInTitle, + _In_ presence_data presenceData + ) +{ + return set_presence_helper(isUserActiveInTitle, std::move(presenceData)) + .then([](xbox_live_result result) + { + return xbox_live_result(result.err(), result.err_message()); + }); +} + + +pplx::task> +presence_service_impl::set_presence_helper( + _In_ bool isUserActiveInTitle, + _In_ presence_data presenceData + ) +{ + string_t xboxUserId = m_userContext->xbox_user_id(); + + string_t pathAndQuery = set_presence_sub_path( + xboxUserId + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("userpresence"), m_appConfig), + pathAndQuery, + xbox_live_api::set_presence_helper + ); + + presence_title_request request( + isUserActiveInTitle, + std::move(presenceData) + ); + + httpCall->set_request_body(request.serialize().serialize()); + httpCall->set_xbox_contract_version_header_value(_T("3")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + uint32_t heartbeatDelay = 0; + auto headers = response->response_headers(); + if (headers.has(_T("X-Heartbeat-After"))) + { + auto heartbeatDelayInSeconds = headers[_T("X-Heartbeat-After")]; + heartbeatDelay = utils::string_t_to_uint32(heartbeatDelayInSeconds) / 60; + } + else + { + heartbeatDelay = 5; + } + + if (s_onSetPresenceFinish) + { + s_onSetPresenceFinish(heartbeatDelay); + } + + return xbox_live_result(heartbeatDelay, response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +function_context +presence_service_impl::add_title_presence_changed_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_titlePresenceChangeHandlerLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_titlePresenceChangeHandlerCounter; + m_titlePresenceChangeHandler[m_titlePresenceChangeHandlerCounter] = std::move(handler); + } + + return context; +} + +void +presence_service_impl::remove_title_presence_changed_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_titlePresenceChangeHandlerLock.get()); + + m_titlePresenceChangeHandler.erase(context); +} + +void +presence_service_impl::device_presence_changed( + _In_ const device_presence_change_event_args& eventArgs + ) +{ + std::unordered_map> devicePresenceChangedHandlersCopy; + + { + std::lock_guard lock(m_devicePresenceChangeHandlerLock.get()); + devicePresenceChangedHandlersCopy = m_devicePresenceChangeHandler; + } + + for (auto& handler : devicePresenceChangedHandlersCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(eventArgs); + } + catch (...) + { + LOG_ERROR("device_presence_changed call threw an exception"); + } + } + } +} + +void +presence_service_impl::title_presence_changed( + _In_ const title_presence_change_event_args& eventArgs +) +{ + std::unordered_map> titlePresenceChangedHandlersCopy; + + { + std::lock_guard lock(m_titlePresenceChangeHandlerLock.get()); + titlePresenceChangedHandlersCopy = m_titlePresenceChangeHandler; + } + + for (auto& handler : titlePresenceChangedHandlersCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(eventArgs); + } + catch (...) + { + LOG_ERROR("title_presence_changed call threw an exception"); + } + } + } +} + +xbox_live_result> +presence_service_impl::subscribe_to_device_presence_change( + _In_ const string_t& xboxUserId + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + + std::shared_ptr deviceSub = std::make_shared( + xboxUserId, + ([thisWeakPtr](const device_presence_change_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->device_presence_changed(eventArgs); + } + }), + ([thisWeakPtr](const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& eventArgs) + { + LOG_DEBUG("device_presence_changed error occurred"); + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->m_realTimeActivityService->_Trigger_subscription_error(eventArgs); + } + }) + ); + + auto subscriptionSucceded = m_realTimeActivityService->_Add_subscription( + deviceSub + ); + + if (!subscriptionSucceded.err()) + { + return xbox_live_result>(deviceSub); + } + + return xbox_live_result>(subscriptionSucceded.err(), subscriptionSucceded.err_message()); +} + +xbox_live_result +presence_service_impl::unsubscribe_from_device_presence_change( + _In_ std::shared_ptr subscription + ) +{ + return m_realTimeActivityService->_Remove_subscription( + subscription + ); +} + +xbox_live_result> +presence_service_impl::subscribe_to_title_presence_change( + _In_ const string_t& xboxUserId, + _In_ uint32_t titleId + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + + std::shared_ptr titleSub = std::make_shared( + xboxUserId, + titleId, + ([thisWeakPtr](const title_presence_change_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->title_presence_changed(eventArgs); + } + }), + ([thisWeakPtr](const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + LOG_DEBUG("title_presence_change error occurred"); + if (pThis != nullptr) + { + pThis->m_realTimeActivityService->_Trigger_subscription_error(eventArgs); + } + }) + ); + + auto subscriptionSucceded = m_realTimeActivityService->_Add_subscription( + titleSub + ); + + if (!subscriptionSucceded.err()) + { + return xbox_live_result>(titleSub); + } + + return xbox_live_result>(subscriptionSucceded.err(), subscriptionSucceded.err_message()); +} + +xbox_live_result +presence_service_impl::unsubscribe_from_title_presence_change( + _In_ std::shared_ptr subscription + ) +{ + return m_realTimeActivityService->_Remove_subscription( + subscription + ); +} + +pplx::task> +presence_service_impl::get_presence( + _In_ const string_t& xboxUserId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(xboxUserId, presence_record, "xboxUserId is empty"); + + string_t pathAndQuery = get_presence_sub_path( + xboxUserId + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("userpresence"), m_appConfig), + pathAndQuery, + xbox_live_api::get_presence + ); + httpCall->set_xbox_contract_version_header_value(_T("3")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + presence_record::_Deserialize(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task>> +presence_service_impl::get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserIds.empty(), std::vector, "xboxUserIds is empty"); + + string_t pathAndQuery = get_presence_user_batch_subpath(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("userpresence"), m_appConfig), + pathAndQuery, + xbox_live_api::get_presence_for_multiple_users + ); + + presence_user_batch_request request( + xboxUserIds, + string_t(), + string_t(), + std::vector(), + std::vector(), + presence_detail_level::default_level, + false, + false + ); + + httpCall->set_request_body(request.serialize().serialize()); + httpCall->set_xbox_contract_version_header_value(_T("3")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto presenceRecords = utils::extract_xbox_live_result_json_vector( + presence_record::_Deserialize, + response->response_body_json(), + errc, + true + ); + + return utils::generate_xbox_live_result>( + presenceRecords, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task>> +presence_service_impl::get_presence_for_multiple_users( + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level presenceDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserIds.empty(), std::vector, "xboxUserIds are empty"); + + string_t pathAndQuery = get_presence_user_batch_subpath(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("userpresence"), m_appConfig), + pathAndQuery, + xbox_live_api::get_presence_for_multiple_users + ); + + presence_user_batch_request request( + xboxUserIds, + string_t(), + string_t(), + deviceTypes, + titleIds, + presenceDetailLevel, + onlineOnly, + broadcastingOnly + ); + + httpCall->set_request_body(request.serialize().serialize()); + httpCall->set_xbox_contract_version_header_value(_T("3")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto responseBody = response->response_body_json(); + auto presenceRecords = utils::extract_xbox_live_result_json_vector( + presence_record::_Deserialize, + responseBody, + errc, + true + ); + + return utils::generate_xbox_live_result>( + presenceRecords, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task>> +presence_service_impl::get_presence_for_social_group( + _In_ const string_t& socialGroup + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(socialGroup, std::vector, "socialGroup is empty"); + string_t xboxUserId = m_userContext->xbox_user_id(); + + string_t pathAndQuery = get_presence_for_social_group_subpath( + xboxUserId, + socialGroup + ); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("userpresence"), m_appConfig), + pathAndQuery, + xbox_live_api::get_presence_for_social_group + ); + httpCall->set_xbox_contract_version_header_value(_T("3")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto presenceRecords = utils::extract_xbox_live_result_json_vector( + presence_record::_Deserialize, + response->response_body_json(), + errc, + true + ); + + return utils::generate_xbox_live_result>( + presenceRecords, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task>> +presence_service_impl::get_presence_for_social_group( + _In_ const string_t& socialGroup, + _In_ const string_t& socialGroupOwnerXboxUserId, + _In_ const std::vector& deviceTypes, + _In_ const std::vector& titleIds, + _In_ presence_detail_level peoplehubDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(socialGroup, std::vector, "socialGroup is empty"); + + string_t pathAndQuery = get_presence_user_batch_subpath(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("userpresence"), m_appConfig), + pathAndQuery, + xbox_live_api::get_presence_for_social_group + ); + + presence_user_batch_request request( + std::vector(), + socialGroup, + socialGroupOwnerXboxUserId, + deviceTypes, + titleIds, + peoplehubDetailLevel, + onlineOnly, + broadcastingOnly + ); + + httpCall->set_request_body(request.serialize().serialize()); + httpCall->set_xbox_contract_version_header_value(_T("3")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto presenceRecords = utils::extract_xbox_live_result_json_vector( + presence_record::_Deserialize, + response->response_body_json(), + errc, + true + ); + + return utils::generate_xbox_live_result>( + presenceRecords, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +string_t +presence_service_impl::set_presence_sub_path( + _In_ const string_t& xboxUserId + ) +{ + stringstream_t subpath; + subpath << _T("/users/xuid("); + subpath << xboxUserId; + subpath << _T(")/devices/current/titles/current"); + return subpath.str(); +} + +string_t +presence_service_impl::get_presence_sub_path( + _In_ const string_t& xboxUserId + ) +{ + stringstream_t subpath; + subpath << _T("/users/xuid("); + subpath << xboxUserId; + subpath << _T(")?level=all"); + return subpath.str(); +} + +string_t +presence_service_impl::get_presence_user_batch_subpath() +{ + return _T("/users/batch"); +} + +string_t +presence_service_impl::get_presence_for_social_group_subpath( + _In_ const string_t& xboxUserId, + _In_ const string_t& socialGroup + ) +{ + stringstream_t subpath; + subpath << _T("/users/xuid("); + subpath << xboxUserId; + subpath << _T(")/groups/"); + subpath << socialGroup; + subpath << _T("?level=all"); + + return subpath.str(); +} + + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_title_record.cpp b/Source/Services/Presence/presence_title_record.cpp new file mode 100644 index 00000000..8afa6ea5 --- /dev/null +++ b/Source/Services/Presence/presence_title_record.cpp @@ -0,0 +1,160 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_title_record::presence_title_record() : + m_titleViewState(presence_title_view_state::unknown), + m_titleId(0), + m_isTitleActive(false) +{ +} + +presence_title_record::presence_title_record( + _In_ uint32_t titleId, + _In_ title_presence_state titlePresenceState + ) : + m_titleId(titleId), + m_titleViewState(presence_title_view_state::unknown) +{ + _Set_title_state(titlePresenceState); +} + +uint32_t +presence_title_record::title_id() const +{ + return m_titleId; +} + +const string_t& +presence_title_record::title_name() const +{ + return m_titleName; +} + +const utility::datetime +presence_title_record::last_modified_date() const +{ + return m_lastModifiedDate; +} + +bool +presence_title_record::is_title_active() const +{ + return m_isTitleActive; +} + +const string_t& +presence_title_record::presence() const +{ + return m_presence; +} + +presence_title_view_state +presence_title_record::presence_title_view() const +{ + return m_titleViewState; +} + +const presence_broadcast_record& +presence_title_record::broadcast_record() const +{ + return m_broadcastRecord; +} + +void +presence_title_record::_Set_title_state( + _In_ title_presence_state state + ) +{ + m_isTitleActive = (state == title_presence_state::started); +} + +bool +presence_title_record::operator!=( + _In_ const presence_title_record& rhs + ) const +{ + return ( + m_broadcastRecord != rhs.m_broadcastRecord || + m_isTitleActive != rhs.m_isTitleActive || + m_lastModifiedDate != rhs.m_lastModifiedDate || + m_presence != rhs.m_presence || + m_titleId != rhs.m_titleId || + m_titleName != rhs.m_titleName || + m_titleViewState != rhs.m_titleViewState + ); +} + +xbox_live_result +presence_title_record::_Deserialize( + _In_ const web::json::value& json + ) +{ + presence_title_record returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + auto activityJson = utils::extract_json_field(json, _T("activity"), errc, false); + + returnObject.m_titleId = utils::string_t_to_uint32(utils::extract_json_string(json, _T("id"), errc)); + returnObject.m_titleName = utils::extract_json_string(json, _T("name"), errc); + returnObject.m_lastModifiedDate = utils::extract_json_time(json, _T("lastModified"), errc); + + string_t state = utils::extract_json_string(json, _T("state"), errc); + returnObject.m_isTitleActive = (!state.empty() && utils::str_icmp(state, _T("active")) == 0); + returnObject.m_presence = utils::extract_json_string(activityJson, _T("richPresence"), errc); + returnObject.m_titleViewState = _Convert_string_to_presence_title_view_state( + utils::extract_json_string(json, _T("placement"), errc) + ); + + auto broadcastRecord = presence_broadcast_record::_Deserialize( + utils::extract_json_field(activityJson, _T("broadcast"), errc, false) + ); + + if (broadcastRecord.err()) + { + errc = broadcastRecord.err(); + } + + returnObject.m_broadcastRecord = broadcastRecord.payload(); + + return xbox_live_result(returnObject, errc); +} + +presence_title_view_state +presence_title_record::_Convert_string_to_presence_title_view_state( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("full")) == 0) + { + return presence_title_view_state::full_screen; + } + else if (utils::str_icmp(value, _T("fill")) == 0) + { + return presence_title_view_state::filled; + } + else if (utils::str_icmp(value, _T("snapped")) == 0) + { + return presence_title_view_state::snapped; + } + else if (utils::str_icmp(value, _T("background")) == 0) + { + return presence_title_view_state::background; + } + + return presence_title_view_state::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_title_request.cpp b/Source/Services/Presence/presence_title_request.cpp new file mode 100644 index 00000000..afc7570f --- /dev/null +++ b/Source/Services/Presence/presence_title_request.cpp @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "utils.h" +#include "presence_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_title_request::presence_title_request( + _In_ bool isUserActive, + _In_ presence_data presenceData, + _In_ media_presence_data mediaPresenceData + ) : + m_isUserActive(isUserActive) +{ + m_presenceActivityData = presence_activity_data( + std::move(presenceData), + std::move(mediaPresenceData) + ); +} + +web::json::value +presence_title_request::serialize() +{ + web::json::value serializedObject; + string_t state = m_isUserActive ? _T("active") : _T("inactive"); + serializedObject[_T("state")] = web::json::value::string(state); + + if (m_presenceActivityData.should_serialize()) + { + serializedObject[_T("activity")] = m_presenceActivityData.serialize(); + } + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_user_batch_request.cpp b/Source/Services/Presence/presence_user_batch_request.cpp new file mode 100644 index 00000000..f08e1bd8 --- /dev/null +++ b/Source/Services/Presence/presence_user_batch_request.cpp @@ -0,0 +1,127 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "presence_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +presence_user_batch_request::presence_user_batch_request( + _In_ std::vector xboxUserIds, + _In_ string_t socialGroup, + _In_ string_t socialGroupOwnerXboxUserId, + _In_ std::vector deviceTypes, + _In_ std::vector titleIds, + _In_ presence_detail_level presenceDetailLevel, + _In_ bool onlineOnly, + _In_ bool broadcastingOnly + ) : + m_xboxUserIds(std::move(xboxUserIds)), + m_socialGroup(std::move(socialGroup)), + m_socialGroupOwnerXboxUserId(std::move(socialGroupOwnerXboxUserId)), + m_presenceDetailLevel(presenceDetailLevel), + m_onlineOnly(onlineOnly), + m_broadcastingOnly(broadcastingOnly) +{ + XSAPI_ASSERT(!m_xboxUserIds.empty() || !m_socialGroup.empty()); + XSAPI_ASSERT(m_xboxUserIds.empty() || m_socialGroup.empty()); + + for (auto& deviceType : deviceTypes) + { + m_deviceTypes.push_back( + presence_device_record::_Convert_presence_device_type_to_string(deviceType) + ); + } + + for (const auto& titleId : titleIds) + { + stringstream_t titleIdStream; + titleIdStream << titleId; + m_titleIds.push_back( + titleIdStream.str() + ); + } +} + +string_t +presence_user_batch_request::convert_detail_level_to_string( + _In_ presence_detail_level level + ) +{ + switch (level) + { + case presence_detail_level::user: + return _T("user"); + + case presence_detail_level::device: + return _T("device"); + + case presence_detail_level::title: + return _T("title"); + + case presence_detail_level::all: + return _T("all"); + + default: + return _T(""); + } +} + + +web::json::value +presence_user_batch_request::serialize() const +{ + web::json::value serializedObject; + + if (!m_xboxUserIds.empty()) + { + serializedObject[_T("users")] = utils::serialize_vector( + utils::json_string_serializer, + m_xboxUserIds + ); + } + else if (!m_socialGroup.empty()) + { + serializedObject[_T("group")] = web::json::value::string(m_socialGroup); + if (!m_socialGroupOwnerXboxUserId.empty()) + { + serializedObject[_T("groupXuid")] = web::json::value::string(m_socialGroupOwnerXboxUserId); + } + } + + if (m_deviceTypes.size() > 0) + { + serializedObject[_T("deviceTypes")] = utils::serialize_vector( + utils::json_string_serializer, + m_deviceTypes + ); + } + + if (m_titleIds.size() > 0) + { + serializedObject[_T("titles")] = utils::serialize_vector( + utils::json_string_serializer, + m_titleIds + ); + } + + string_t presenceDetailLevel = convert_detail_level_to_string(m_presenceDetailLevel); + if (!presenceDetailLevel.empty()) + { + serializedObject[_T("level")] = web::json::value::string(presenceDetailLevel); + } + + serializedObject[_T("onlineOnly")] = web::json::value::boolean(m_onlineOnly); + serializedObject[_T("broadcastingOnly")] = web::json::value::boolean(m_broadcastingOnly); + + return serializedObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/presence_writer.cpp b/Source/Services/Presence/presence_writer.cpp new file mode 100644 index 00000000..2daecaed --- /dev/null +++ b/Source/Services/Presence/presence_writer.cpp @@ -0,0 +1,250 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/presence.h" +#include "xsapi/services.h" +#include "user_context.h" +#include "presence_internal.h" +#ifdef __cplusplus_winrt +#include "Utils_WinRT.h" +#include "utils.h" + +using namespace Windows::System::Threading; +#endif + +#define PRESENCE_DELAY_IN_MILLISECONDS 60 * 1000 + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +std::shared_ptr +presence_writer::get_presence_writer_singleton() +{ + return get_xsapi_singleton()->s_presenceWriterSingleton; +} + +presence_writer::presence_writer() : + m_writerInProgress(false), + m_heartBeatDelayInMins(0), + m_isCallInProgress(false) +{ +} + +#ifdef __cplusplus_winrt +void presence_writer::start_timer(_In_ std::weak_ptr thisWeakPtr) +{ + Windows::Foundation::TimeSpan delay = Microsoft::Xbox::Services::System::UtilsWinRT::ConvertSecondsToTimeSpan(std::chrono::minutes(1)); + m_timer = ThreadPoolTimer::CreatePeriodicTimer( + ref new TimerElapsedHandler([thisWeakPtr](ThreadPoolTimer^ source) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->handle_timer_trigger(); + } + }), + delay + ); +} +#else +void +presence_writer::start_timer( + _In_ std::weak_ptr thisWeakPtr) +{ + m_timerComplete = false; + while (true) + { + if (m_timerComplete) + { + break; + } + int delayInMilliseconds = 60 * 1000; // call handle_timer_trigger() every minute + utils::sleep(delayInMilliseconds); + if (m_timerComplete) + { + break; + } + // Do write in the end so that it has the same logic as winrt timer + handle_timer_trigger(); + } +} +#endif + +void +presence_writer::start_writer( + _In_ std::shared_ptr presenceServiceImpl + ) +{ + bool startWriter = false; + + { + std::lock_guard guard(m_lock.get()); + if (!m_writerInProgress) + { + m_writerInProgress = true; + startWriter = true; + } + + const string_t& id = presenceServiceImpl->m_userContext->xbox_user_id(); + if (m_presenceServices.find(id) == m_presenceServices.end()) + { + LOG_INFO("Add new presence service into writer"); + m_presenceServices.insert(std::make_pair(id, presenceServiceImpl)); + + try + { + // For the first presence wirte. + presenceServiceImpl->set_presence(true); + } + catch (...) + { + LOGS_WARN << "Failed setting presence for: " << presenceServiceImpl->m_userContext->xbox_user_id(); + if (m_writerInProgress) + { + m_writerInProgress = false; + startWriter = false; + } + } + } + else + { + LOG_INFO("Presence service for the user already exsit, return"); + return; + } + } + + if (startWriter) + { + // Start timer that will write presence after certain time. + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::create_task([thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->start_timer(thisWeakPtr); + } + }); + } +} + +void +presence_writer::handle_timer_trigger() +{ + LOG_INFO("Start presence writer timer trigger"); + m_heartBeatDelayInMins--; + if (m_heartBeatDelayInMins > 0) + { + return; + } + + set_active_in_title(); +} + +void +presence_writer::stop_writer( + _In_ const string_t& xboxLiveUserId + ) +{ + std::lock_guard guard(m_lock.get()); + if (m_writerInProgress) + { + auto presenceService = m_presenceServices.find(xboxLiveUserId); + if (presenceService != m_presenceServices.end()) + { + set_inactive_in_title(presenceService->second); + m_presenceServices.erase(presenceService); + } + + if (m_presenceServices.empty()) + { + m_writerInProgress = false; + m_heartBeatDelayInMins = 0; + } + +#ifdef __cplusplus_winrt + if (m_timer) + { + m_timer->Cancel(); + } +#else + m_timerComplete = true; +#endif + } +} + +void +presence_writer::set_inactive_in_title( + _In_ std::shared_ptr presenceServiceImpl + ) +{ + // Set the presence to be not in this title + try + { + presenceServiceImpl->set_presence(false); + } + catch (...) + { + LOG_ERROR("Set presence inactive fail"); + } +} + +void +presence_writer::set_active_in_title() +{ + bool expected = false; + if (m_isCallInProgress.compare_exchange_strong(expected, true)) + { + LOG_INFO("Start presence writing."); + + std::lock_guard guard(m_lock.get()); + + std::vector>> writeTasks; + for (auto& presencePair : m_presenceServices) + { + auto& presenceService = presencePair.second; + if (presenceService != nullptr) + { + writeTasks.push_back(pplx::create_task(presenceService->set_presence_helper(true, presence_data()))); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + pplx::when_all(writeTasks.begin(), writeTasks.end()) + .then([thisWeakPtr](std::vector> results) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + + pThis->m_isCallInProgress.store(false); + LOG_INFO("Presence writing finish."); + + // only look at the last result + auto heartBeat = (results.end() -1); + if (!heartBeat->err()) + { + pThis->m_heartBeatDelayInMins = heartBeat->payload(); + } + else + { + LOGS_ERROR <<"Error detected on presence writing, using default interval for next write:" + << heartBeat->err() << ", msg:" << heartBeat->err_message(); + // Ignore failures + pThis->m_heartBeatDelayInMins = s_defaultHeartBeatDelayInMins; + } + + }); + } + } + else + { + LOG_INFO("Writting in progress, skip presence writing."); + } + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END diff --git a/Source/Services/Presence/title_presence_change_event_args.cpp b/Source/Services/Presence/title_presence_change_event_args.cpp new file mode 100644 index 00000000..50fb4697 --- /dev/null +++ b/Source/Services/Presence/title_presence_change_event_args.cpp @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +title_presence_change_event_args::title_presence_change_event_args() : + m_titleId(0), + m_titleState(title_presence_state::unknown) +{ +} + +title_presence_change_event_args::title_presence_change_event_args( + _In_ string_t xboxUserId, + _In_ uint32_t titleId, + _In_ title_presence_state titleState + ) : + m_xboxUserId(xboxUserId.c_str()), + m_titleId(titleId), + m_titleState(titleState) +{ +} + +const string_t& +title_presence_change_event_args::xbox_user_id() const +{ + return m_xboxUserId; +} + +uint32_t +title_presence_change_event_args::title_id() const +{ + return m_titleId; +} + +title_presence_state +title_presence_change_event_args::title_state() const +{ + return m_titleState; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Presence/title_presence_change_subscription.cpp b/Source/Services/Presence/title_presence_change_subscription.cpp new file mode 100644 index 00000000..926b7948 --- /dev/null +++ b/Source/Services/Presence/title_presence_change_subscription.cpp @@ -0,0 +1,177 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/presence.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_BEGIN + +title_presence_change_subscription::title_presence_change_subscription( + _In_ string_t xboxUserId, + _In_ uint32_t titleId, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ) : + real_time_activity_subscription(subscriptionErrorHandler), + m_xboxUserId(std::move(xboxUserId)), + m_titleId(titleId), + m_handler(handler) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + XSAPI_ASSERT(handler != nullptr); + + stringstream_t uri; + uri << _T("https://userpresence.xboxlive.com/users/xuid(") << m_xboxUserId << _T(")/titles/") << m_titleId; + + m_resourceUri = uri.str(); +} + +void +title_presence_change_subscription::on_subscription_created( + _In_ uint32_t id, + _In_ const web::json::value& data + ) +{ + real_time_activity_subscription::on_subscription_created(id, data); + title_presence_change_event_args presenceEventArgs; + + if (!data.is_null()) + { + auto initialPresenceRecord = presence_record::_Deserialize(data); + bool isPlaying = false; + + if (!initialPresenceRecord.err()) + { + auto& presenceDeviceRecords = initialPresenceRecord.payload().presence_device_records(); + for (const auto& deviceRecord : presenceDeviceRecords) + { + for (const auto& titleRecord : deviceRecord.presence_title_records()) + { + if (titleRecord.title_id() == m_titleId) + { + isPlaying = true; + break; + } + } + + if (isPlaying) + { + break; + } + } + + presenceEventArgs = title_presence_change_event_args( + title_presence_change_event_args( + m_xboxUserId, + m_titleId, + isPlaying ? title_presence_state::started : title_presence_state::ended + ) + ); + + } + else + { + if(m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + initialPresenceRecord.err(), + "JSON deserialization failure" + ) + ); + } + + return; + } + } + else + { + if(m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON not found on subscription" + ) + ); + } + + return; + } + + if (m_handler != nullptr) + { + m_handler(presenceEventArgs); + } +} + +void +title_presence_change_subscription::on_event_received( + _In_ const web::json::value& data + ) +{ + if (m_handler && !data.is_null()) + { + std::error_code errc; + auto titlePresenceValue = utils::extract_json_as_string(data, errc); + + title_presence_state titlePresenceState = title_presence_state::unknown; + if (!errc) + { + if (utils::str_icmp(titlePresenceValue, _T("started")) == 0) + { + titlePresenceState = title_presence_state::started; + } + else if (utils::str_icmp(titlePresenceValue, _T("ended")) == 0) + { + titlePresenceState = title_presence_state::ended; + } + } + else + { + if(m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON deserialization failure" + ) + ); + } + + return; + } + + auto presenceEventArgs = title_presence_change_event_args( + m_xboxUserId, + m_titleId, + std::move(titlePresenceState) + ); + + m_handler(presenceEventArgs); + } +} + +const string_t& +title_presence_change_subscription::xbox_user_id() const +{ + return m_xboxUserId; +} + +uint32_t +title_presence_change_subscription::title_id() const +{ + return m_titleId; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_CPP_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.cpp b/Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.cpp new file mode 100644 index 00000000..2ae5582d --- /dev/null +++ b/Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.cpp @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "MultiplePermissionsCheckResult_WinRT.h" + +using namespace Platform; +using namespace Microsoft::Xbox::Services::System; +using namespace Microsoft::Xbox::Services::Privacy; +using namespace Windows::Foundation::Collections; +using namespace xbox::services::privacy; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +MultiplePermissionsCheckResult::MultiplePermissionsCheckResult( + _In_ xbox::services::privacy::multiple_permissions_check_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_items = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.items())->GetView(); +} + +IVectorView^ +MultiplePermissionsCheckResult::Items::get() +{ + return m_items; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.h b/Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.h new file mode 100644 index 00000000..957b7eb5 --- /dev/null +++ b/Source/Services/Privacy/WinRT/MultiplePermissionsCheckResult_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/privacy.h" +#include "PermissionCheckResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +/// +/// Contains the results of multiple permission checks. +/// +public ref class MultiplePermissionsCheckResult sealed +{ +public: + /// + /// Xbox User Id for the target user of the permission request. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// Contains a collection of results returned when checking multiple permissions for a user. + /// + property Windows::Foundation::Collections::IVectorView^ Items { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + MultiplePermissionsCheckResult( + _In_ xbox::services::privacy::multiple_permissions_check_result cppObj + ); + +private: + xbox::services::privacy::multiple_permissions_check_result m_cppObj; + + Windows::Foundation::Collections::IVectorView^ m_items; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.cpp b/Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.cpp new file mode 100644 index 00000000..062d6e96 --- /dev/null +++ b/Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PermissionCheckResult_WinRT.h" + +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::privacy; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +PermissionCheckResult::PermissionCheckResult( + _In_ xbox::services::privacy::permission_check_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_denyReasons = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.deny_reasons())->GetView(); +} + +IVectorView^ +PermissionCheckResult::DenyReasons::get() +{ + return m_denyReasons; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.h b/Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.h new file mode 100644 index 00000000..8cec3e1a --- /dev/null +++ b/Source/Services/Privacy/WinRT/PermissionCheckResult_WinRT.h @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/privacy.h" +#include "PermissionDenyReason_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN +/// +/// Contains the results of a permission check. +/// + +/// +/// Contains the result of a permission check. +/// +public ref class PermissionCheckResult sealed +{ +public: + /// + /// Indicates if the user is allowed the requested access. + /// + DEFINE_PROP_GET_OBJ(IsAllowed, is_allowed, bool); + + /// + /// The permission requested. + /// + DEFINE_PROP_GET_STR_OBJ(PermissionRequested, permission_requested); + + /// + /// If IsAllowed is false, contains the reasons why the permissions were denied. + /// + property Windows::Foundation::Collections::IVectorView^ DenyReasons { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + PermissionCheckResult( + _In_ xbox::services::privacy::permission_check_result cppObj + ); + +private: + xbox::services::privacy::permission_check_result m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_denyReasons; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.cpp b/Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.cpp new file mode 100644 index 00000000..2a605bfe --- /dev/null +++ b/Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.cpp @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PermissionDenyReason_WinRT.h" + +using namespace xbox::services::privacy; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +PermissionDenyReason::PermissionDenyReason( + _In_ xbox::services::privacy::permission_deny_reason cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.h b/Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.h new file mode 100644 index 00000000..ca5da2dc --- /dev/null +++ b/Source/Services/Privacy/WinRT/PermissionDenyReason_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/privacy.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +/// +/// Contains the reason why permission was denied. +/// +public ref class PermissionDenyReason sealed +{ +public: + /// + /// The reason why permission was denied. + /// + DEFINE_PROP_GET_STR_OBJ(Reason, reason); + + /// + /// If the deny reason is previlege check, this indicates which privilege failed. + /// + DEFINE_PROP_GET_STR_OBJ(RestrictedSetting, restricted_setting); + +internal: + PermissionDenyReason( + _In_ xbox::services::privacy::permission_deny_reason cppObj + ); + +private: + xbox::services::privacy::permission_deny_reason m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.cpp b/Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.cpp new file mode 100644 index 00000000..62654ad3 --- /dev/null +++ b/Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.cpp @@ -0,0 +1,101 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PermissionIdConstants_WinRT.h" +#include "Macros_WinRT.h" + +using namespace Microsoft::Xbox::Services::Privacy; +using namespace Microsoft::Xbox::Services; +using namespace Platform; +using namespace xbox::services::privacy; + +Platform::String^ +PermissionIdConstants::CommunicateUsingText::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::communicate_using_text()); +} + +Platform::String^ +PermissionIdConstants::CommunicateUsingVideo::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::communicate_using_video()); +} + +Platform::String^ +PermissionIdConstants::CommunicateUsingVoice::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::communicate_using_voice()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetProfile::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_profile()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetGameHistory::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_game_history()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetVideoHistory::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_video_history()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetMusicHistory::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_music_history()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetExerciseInfo::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_exercise_info()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetPresence::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_presence()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetVideoStatus::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_video_status()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetMusicStatus::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_music_status()); +} + +Platform::String^ +PermissionIdConstants::PlayMultiplayer::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::play_multiplayer()); +} + +Platform::String^ +PermissionIdConstants::BroadcastWithTwitch::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::broadcast_with_twitch()); +} + +Platform::String^ +PermissionIdConstants::ViewTargetUserCreatedContent::get() +{ + return PLATFORM_STRING_FROM_STRING_T(permission_id_constants::view_target_user_created_content()); +} \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.h b/Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.h new file mode 100644 index 00000000..ca28031d --- /dev/null +++ b/Source/Services/Privacy/WinRT/PermissionIdConstants_WinRT.h @@ -0,0 +1,94 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once +#include "xsapi/privacy.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +/// +/// Manages constant values for permission IDs. +/// +public ref class PermissionIdConstants sealed +{ +public: + /// + /// Check whether or not the user can send a message with text content to the target user. + /// + static property Platform::String^ CommunicateUsingText { Platform::String^ get(); } + + /// + /// Check whether or not the user can communicate using video with the target user. + /// + static property Platform::String^ CommunicateUsingVideo { Platform::String^ get(); } + + /// + /// Check whether or not the user can communicate using voice with the target user. + /// + static property Platform::String^ CommunicateUsingVoice { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the profile of the target user. + /// + static property Platform::String^ ViewTargetProfile { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the game history of the target user. + /// + static property Platform::String^ ViewTargetGameHistory { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the details video watching history of the target user. + /// + static property Platform::String^ ViewTargetVideoHistory { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the detailed music listening history of the target user. + /// + static property Platform::String^ ViewTargetMusicHistory { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the exercise info of the target user. + /// + static property Platform::String^ ViewTargetExerciseInfo { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the online status of the target user. + /// + static property Platform::String^ ViewTargetPresence { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the details of the targets video status (extended online presence). + /// + static property Platform::String^ ViewTargetVideoStatus { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the details of the targets music status (extended online presence). + /// + static property Platform::String^ ViewTargetMusicStatus { Platform::String^ get(); } + + /// + /// Check whether or not a user can play multiplayer with the target user. + /// + static property Platform::String^ PlayMultiplayer { Platform::String^ get(); } + + /// + /// Checks whether or not the user can view information about how audio buffers are broadcast for the target user. + /// + static property Platform::String^ BroadcastWithTwitch { Platform::String^ get(); } + + /// + /// Check whether or not the user can view the user-created content of other users. + /// + static property Platform::String^ ViewTargetUserCreatedContent { Platform::String^ get(); } + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PrivacyService_WinRT.cpp b/Source/Services/Privacy/WinRT/PrivacyService_WinRT.cpp new file mode 100644 index 00000000..50c8ce2c --- /dev/null +++ b/Source/Services/Privacy/WinRT/PrivacyService_WinRT.cpp @@ -0,0 +1,95 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "PrivacyService_WinRT.h" + +using namespace Concurrency; +using namespace xbox::services::privacy; +using namespace Microsoft::Xbox::Services::System; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +PrivacyService::PrivacyService( + _In_ xbox::services::privacy::privacy_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +IAsyncOperation^>^ +PrivacyService::GetAvoidListAsync() +{ + auto task = m_cppObj.get_avoid_or_mute_list(_T("avoid")) + .then([](xbox_live_result> avoidList) + { + THROW_IF_ERR(avoidList); + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(avoidList.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +PrivacyService::GetMuteListAsync() +{ + auto task = m_cppObj.get_avoid_or_mute_list(_T("mute")) + .then([](xbox_live_result> muteList) + { + THROW_IF_ERR(muteList); + return UtilsWinRT::CreatePlatformVectorFromStdVectorString(muteList.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +PrivacyService::CheckPermissionWithTargetUserAsync( + _In_ Platform::String^ permissionId, + _In_ Platform::String^ targetXboxUserId + ) +{ + auto task = m_cppObj.check_permission_with_target_user( + STRING_T_FROM_PLATFORM_STRING(permissionId), + STRING_T_FROM_PLATFORM_STRING(targetXboxUserId) + ) + .then([](xbox_live_result checkResult) + { + THROW_IF_ERR(checkResult) + return ref new PermissionCheckResult(checkResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + + +IAsyncOperation^>^ +PrivacyService::CheckMultiplePermissionsWithMultipleTargetUsersAsync( + _In_ IVectorView^ permissionIds, + _In_ IVectorView^ targetXboxUserIds + ) +{ + auto task = m_cppObj.check_multiple_permissions_with_multiple_target_users( + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(permissionIds), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(targetXboxUserIds) + ) + .then([](xbox_live_result> multiplePermissionsCheckResult) + { + THROW_IF_ERR(multiplePermissionsCheckResult); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(multiplePermissionsCheckResult.payload())->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/WinRT/PrivacyService_WinRT.h b/Source/Services/Privacy/WinRT/PrivacyService_WinRT.h new file mode 100644 index 00000000..37728aba --- /dev/null +++ b/Source/Services/Privacy/WinRT/PrivacyService_WinRT.h @@ -0,0 +1,90 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/privacy.h" +#include "PermissionCheckResult_WinRT.h" +#include "MultiplePermissionsCheckResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_BEGIN + +/// +/// Provides an endpoint for managing privacy settings. +/// +public ref class PrivacyService sealed +{ +public: + + /// + /// Get the list of Xbox Live Ids the calling user should avoid during multiplayer matchmaking. + /// + /// A collection of XboxUserIds that correspond to the calling user's avoid list. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/xuid({xuid})/people/avoid + Windows::Foundation::IAsyncOperation^>^ GetAvoidListAsync(); + + /// + /// Check a single permission with a single target user. + /// + /// The ID of the permission to check. + /// See Microsoft::Xbox::Services::Privacy::PermissionIdConstants for the latest options. + /// The target user's xbox Live ID for validation + /// The permission check result against a single user. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/{requestorId}/permission/validate + /// + Windows::Foundation::IAsyncOperation^ CheckPermissionWithTargetUserAsync( + _In_ Platform::String^ permissionId, + _In_ Platform::String^ targetXboxUserId + ); + + /// + /// Check multiple permissions with multiple target users. + /// + /// The collection of IDs of the permissions to check. + /// See Microsoft::Xbox::Services::Privacy::PermissionIdConstants for the latest options. + /// The collection of target Xbox user IDs to check permissions against. + /// A multiple permission check result which contains a collection of permission information. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// + /// Calls V1 POST /users/{requestorId}/permission/validate + /// + Windows::Foundation::IAsyncOperation^>^ CheckMultiplePermissionsWithMultipleTargetUsersAsync( + _In_ Windows::Foundation::Collections::IVectorView^ permissionIds, + _In_ Windows::Foundation::Collections::IVectorView^ targetXboxUserIds + ); + + /// + /// Get the list of Xbox Live Ids that the calling user should not hear (mute) during multiplayer matchmaking. + /// + /// The collection of Xbox user IDs that represent the mute list for a user. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// + /// Calls V1 GET /users/xuid({xuid})/people/mute + /// + Windows::Foundation::IAsyncOperation^>^ GetMuteListAsync(); + +internal: + PrivacyService( + _In_ xbox::services::privacy::privacy_service cppObj + ); + +private: + xbox::services::privacy::privacy_service m_cppObj; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_END \ No newline at end of file diff --git a/Source/Services/Privacy/multiple_permissions_check_result.cpp b/Source/Services/Privacy/multiple_permissions_check_result.cpp new file mode 100644 index 00000000..cd476eda --- /dev/null +++ b/Source/Services/Privacy/multiple_permissions_check_result.cpp @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/privacy.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_BEGIN + +multiple_permissions_check_result::multiple_permissions_check_result() +{ +} + +const string_t& +multiple_permissions_check_result::xbox_user_id() const +{ + return m_xboxUserId; +} + +const std::vector& +multiple_permissions_check_result::items() const +{ + return m_items; +} + +void multiple_permissions_check_result::initialize( + _In_ uint32_t index, + _In_ const string_t& permissionIdRequested + ) +{ + if( index < m_items.size() ) + { + m_items[index].initialize(permissionIdRequested); + } +} + +xbox_live_result +multiple_permissions_check_result::_Deserializer( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + multiple_permissions_check_result result; + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value userObj = utils::extract_json_field(json, _T("user"), errc, true); + result.m_xboxUserId = utils::extract_json_string(userObj, _T("xuid"), errc, true); + result.m_items = utils::extract_json_vector( + permission_check_result::_Deserializer, + std::move(json), + _T("permissions"), + errc, + true + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_END \ No newline at end of file diff --git a/Source/Services/Privacy/permission_check_result.cpp b/Source/Services/Privacy/permission_check_result.cpp new file mode 100644 index 00000000..38c8c39c --- /dev/null +++ b/Source/Services/Privacy/permission_check_result.cpp @@ -0,0 +1,61 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/privacy.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_BEGIN + +permission_check_result::permission_check_result() : + m_isAllowed(false) +{ +} + +void permission_check_result::initialize( + _In_ const string_t& permissionIdRequested + ) +{ + m_permissionRequested = permissionIdRequested; +} + +bool +permission_check_result::is_allowed() const +{ + return m_isAllowed; +} + +const string_t& +permission_check_result::permission_requested() const +{ + return m_permissionRequested; +} + +const std::vector& +permission_check_result::deny_reasons() const +{ + return m_denyReasons; +} + +xbox_live_result +permission_check_result::_Deserializer( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + permission_check_result result; + + std::error_code errc = xbox_live_error_code::no_error; + result.m_isAllowed = utils::extract_json_bool(json, _T("isAllowed"), errc, true); + result.m_denyReasons = utils::extract_json_vector(permission_deny_reason::_Deserializer, std::move(json), _T("reasons"), errc, false); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_END \ No newline at end of file diff --git a/Source/Services/Privacy/permission_deny_reason.cpp b/Source/Services/Privacy/permission_deny_reason.cpp new file mode 100644 index 00000000..adede03d --- /dev/null +++ b/Source/Services/Privacy/permission_deny_reason.cpp @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/privacy.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_BEGIN + +permission_deny_reason::permission_deny_reason() +{ +} + +const string_t& +permission_deny_reason::reason() const +{ + return m_reason; +} + +const string_t& +permission_deny_reason::restricted_setting() const +{ + return m_restrictedSetting; +} + +xbox_live_result +permission_deny_reason::_Deserializer( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + permission_deny_reason result; + + std::error_code errc = xbox_live_error_code::no_error; + result.m_reason = utils::extract_json_string(json, _T("reason"), errc, true); + result.m_restrictedSetting = utils::extract_json_string(json, _T("restrictedSetting"), errc, false); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_END \ No newline at end of file diff --git a/Source/Services/Privacy/privacy_service.cpp b/Source/Services/Privacy/privacy_service.cpp new file mode 100644 index 00000000..dd312570 --- /dev/null +++ b/Source/Services/Privacy/privacy_service.cpp @@ -0,0 +1,320 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/privacy.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_BEGIN + +// Helper classes for serialization/deserialization +class avoid_list_item +{ +private: + static xbox_live_result deserializer(_In_ const web::json::value& json) + { + if (json.is_null()) return xbox_live_result(xbox_live_error_code::json_error, "Json is null or empty"); + + avoid_list_item result; + + std::error_code errc = xbox_live_error_code::no_error; + result.m_xboxUserId = utils::extract_json_string(json, _T("xuid"), errc, true); + + return xbox_live_result(result, errc); + } + + string_t m_xboxUserId; + + friend class privacy_service; + friend class avoid_list; + template friend class xbox_live_result; +}; + +class avoid_list +{ +private: + static xbox_live_result deserializer(_In_ const web::json::value& json) + { + if (json.is_null()) return xbox_live_result(xbox_live_error_code::json_error, "Json is null or empty"); + + avoid_list result; + + std::error_code errc = xbox_live_error_code::no_error; + result.m_avoidList = utils::extract_json_vector(avoid_list_item::deserializer, json, _T("users"), errc, true); + + return xbox_live_result(result, errc); + } + + std::vector m_avoidList; + + friend class avoid_list_item; + friend class privacy_service; + template friend class xbox_live_result; +}; + +// Privacy service +privacy_service::privacy_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task>> +privacy_service::get_avoid_list() +{ + return get_avoid_or_mute_list(_T("avoid")); +} + +pplx::task>> +privacy_service::get_mute_list() +{ + return get_avoid_or_mute_list(_T("mute")); +} + +pplx::task>> +privacy_service::get_avoid_or_mute_list( + _In_ const string_t& subPathName + ) +{ + string_t xboxUserId = m_userContext->xbox_user_id(); + string_t subPathAndQuery = avoid_mute_list_sub_path(xboxUserId, subPathName); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("privacy"), m_appConfig), + subPathAndQuery, + xbox_live_api::get_avoid_or_mute_list + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto result = avoid_list::deserializer(response->response_body_json()); + + std::vector xuidVector; + + for (auto& item : result.payload().m_avoidList) + { + if (!item.m_xboxUserId.empty()) + { + xuidVector.push_back(item.m_xboxUserId); + } + } + + xbox_live_result> xuidVectorResult( + xuidVector, + result.err(), + result.err_message() + ); + + return utils::generate_xbox_live_result>( + xuidVectorResult, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +const string_t +privacy_service::avoid_mute_list_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& subPathName + ) +{ + web::uri_builder subPathBuilder; + stringstream_t path; + path << _T("/users/xuid("); + path << xboxUserId; + path << _T(")/people/"); + path << subPathName; + + subPathBuilder.append_path(path.str()); + + return subPathBuilder.to_string(); +} + +const string_t +privacy_service::permission_validate_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& setting, + _In_ const string_t& targetXboxUserId + ) +{ + // users/xuid({xuid})/permission/validate?setting={setting}&target=xuid({targetXuid}) + + web::uri_builder subPathBuilder; + stringstream_t path; + path << _T("/users/xuid("); + path << xboxUserId; + path << _T(")/permission/validate"); + + subPathBuilder.append_path(path.str()); + subPathBuilder.append_query(_T("setting"), setting); + + stringstream_t xuidPath; + xuidPath << _T("xuid("); + xuidPath << targetXboxUserId; + xuidPath << _T(")"); + subPathBuilder.append_query(_T("target"), xuidPath.str()); + + return subPathBuilder.to_string(); +} + +const string_t +privacy_service::permission_batch_validate_sub_path( + _In_ const string_t& xboxUserId + ) +{ + // users/xuid({xuid})/permission/validate + + web::uri_builder subPathBuilder; + stringstream_t path; + path << _T("/users/xuid("); + path << xboxUserId; + path << _T(")/permission/validate"); + + subPathBuilder.append_path(path.str()); + + return subPathBuilder.to_string(); +} + +pplx::task> +privacy_service::check_permission_with_target_user( + _In_ const string_t& permissionId, + _In_ const string_t& targetXboxUserId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(permissionId, permission_check_result, "PermissionID is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(targetXboxUserId, permission_check_result, "Target Xbox User Id is empty"); + + string_t xboxUserId = m_userContext->xbox_user_id(); + string_t subpathAndQuery = permission_validate_sub_path(xboxUserId, permissionId, targetXboxUserId); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("privacy"), m_appConfig), + subpathAndQuery, + xbox_live_api::check_permission_with_target_user + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + return utils::generate_xbox_live_result( + permission_check_result::_Deserializer(response->response_body_json()), + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + + +pplx::task>> +privacy_service::check_multiple_permissions_with_multiple_target_users( + _In_ std::vector permissionIds, + _In_ std::vector targetXboxUserIds + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(permissionIds.empty(), std::vector, "Permission Ids are empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(targetXboxUserIds.empty(), std::vector, "Target Xbox User Ids are empty"); + + string_t xboxUserId = m_userContext->xbox_user_id(); + web::uri subpathAndQuery = permission_batch_validate_sub_path(xboxUserId); + + // Set request body to something like: + //{ + // "users": + // [ + // {"xuid":"12345"}, + // {"xuid":"54321"} + // ], + // "permissions": + // [ + // "ViewTargetGameHistory", + // "ViewTargetProfile" + // ] + //} + + web::json::value serializedObject; + + web::json::value privacyUsers; + for (uint32_t i = 0; i < targetXboxUserIds.size(); ++i) + { + web::json::value userJson; + userJson[_T("xuid")] = web::json::value(targetXboxUserIds[i]); + privacyUsers[i] = userJson; + } + + serializedObject[_T("users")] = privacyUsers; + serializedObject[_T("permissions")] = utils::serialize_vector(utils::json_string_serializer, permissionIds); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("privacy"), m_appConfig), + subpathAndQuery, + xbox_live_api::check_multiple_permissions_with_multiple_target_users + ); + + httpCall->set_request_body( + serializedObject.serialize() + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([permissionIds](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto results = utils::extract_json_vector(multiple_permissions_check_result::_Deserializer, response->response_body_json(), _T("responses"), errc, true); + + for (auto& result : results) + { + auto permissionResults = result.items(); + + if (permissionResults.size() != permissionIds.size()) return xbox_live_result>(xbox_live_error_code::runtime_error, "The resulting number of items did not match the number of items requested!"); + + for (uint32_t i = 0; i < permissionResults.size(); i++) + { + result.initialize(i, permissionIds[i]); + } + } + + xbox_live_result> multiplePermissionResults( + results, + errc, + "" + ); + + return utils::generate_xbox_live_result>( + multiplePermissionResults, + response + ); + }); + + return utils::create_exception_free_task< std::vector >( + task + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRIVACY_CPP_END diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivityConnectionState_WinRT.h b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityConnectionState_WinRT.h new file mode 100644 index 00000000..7f8b3441 --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityConnectionState_WinRT.h @@ -0,0 +1,36 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +/// +/// Enumeration for the possible connection states of the connection +/// to the real-time activity service. +/// +public enum class RealTimeActivityConnectionState +{ + /// + /// Currently connected to the real-time activity service. + /// + Connected = xbox::services::real_time_activity::real_time_activity_connection_state::connected, + + /// + /// Currently connecting to the real-time activity service. + /// + Connecting = xbox::services::real_time_activity::real_time_activity_connection_state::connecting, + + /// + /// Currently disconnected from the real-time activity service . + /// + Disconnected = xbox::services::real_time_activity::real_time_activity_connection_state::disconnected +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.cpp b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.cpp new file mode 100644 index 00000000..5ee190ec --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.cpp @@ -0,0 +1,19 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "RealTimeActivityResyncEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +RealTimeActivityResyncEventArgs::RealTimeActivityResyncEventArgs() +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.h b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.h new file mode 100644 index 00000000..331f188d --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityResyncEventArgs_WinRT.h @@ -0,0 +1,20 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +public ref class RealTimeActivityResyncEventArgs sealed +{ +internal: + RealTimeActivityResyncEventArgs(); +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.cpp b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.cpp new file mode 100644 index 00000000..6cb9c82a --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.cpp @@ -0,0 +1,273 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "RealTimeActivityService_WinRT.h" +#include "Macros_WinRT.h" +#include "XboxLiveContextSettings_WinRT.h" + +using namespace Windows::Foundation; +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +RealTimeActivityService::RealTimeActivityService( + _In_ std::shared_ptr cppObj + ) : m_cppObj(cppObj) +{ + m_connectionStateChangeEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + m_subscriptionErrorEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + m_resyncEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + + m_connectionStateChangeEventBind->AddConnectionStateChangeEvent(); + m_subscriptionErrorEventBind->AddSubscriptionErrorEvent(); + m_resyncEventBind->AddResyncEvent(); +} + +RealTimeActivityService::~RealTimeActivityService() +{ + m_connectionStateChangeEventBind->RemoveConnectionStateChangeEvent(); + m_subscriptionErrorEventBind->RemoveSubscriptionErrorEvent(); + m_resyncEventBind->RemoveResyncEvent(); +} + +void +RealTimeActivityService::Activate() +{ + m_connectionStateChangeEventBind->AddConnectionStateChangeEvent(); + m_subscriptionErrorEventBind->AddSubscriptionErrorEvent(); + m_resyncEventBind->AddResyncEvent(); + + CONVERT_STD_EXCEPTION( + m_cppObj->activate(); + ); +} + +void +RealTimeActivityService::Deactivate() +{ + m_connectionStateChangeEventBind->RemoveConnectionStateChangeEvent(); + m_subscriptionErrorEventBind->RemoveSubscriptionErrorEvent(); + m_resyncEventBind->RemoveResyncEvent(); + + CONVERT_STD_EXCEPTION( + m_cppObj->deactivate(); + ); +} + +std::shared_ptr +RealTimeActivityService::GetCppObj() const +{ + return m_cppObj; +} + +void +RealTimeActivityService::RaiseRealTimeActivityConnectedStateChange( +_In_ RealTimeActivityConnectionState args +) +{ + RealTimeActivityConnectionStateChange(this, args); +} + +void +RealTimeActivityService::RaiseRealTimeActivitySubscriptionError( +_In_ RealTimeActivitySubscriptionErrorEventArgs^ args +) +{ + RealTimeActivitySubscriptionError(this, args); +} + +void +RealTimeActivityService::RaiseRealTimeActivityResync( + _In_ RealTimeActivityResyncEventArgs^ args + ) +{ + RealTimeActivityResync(this, args); +} + +ConnectionStateChangeEventBind::ConnectionStateChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ std::shared_ptr cppObj + ) : + m_setting(setting), + m_rtaCppObj(std::move(cppObj)), + m_functionContext(0) +{ +} + +void +ConnectionStateChangeEventBind::AddConnectionStateChangeEvent() +{ + if (m_functionContext == 0) + { + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_rtaCppObj->add_connection_state_change_handler([thisWeakPtr](_In_ xbox::services::real_time_activity::real_time_activity_connection_state state) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->RealTimeActivityConnectionStateChangeRouter(state); + } + }); + } +} + +void +ConnectionStateChangeEventBind::RemoveConnectionStateChangeEvent() +{ + if (m_functionContext != 0) + { + m_rtaCppObj->remove_connection_state_change_handler(m_functionContext); + m_functionContext = 0; + } +} + +void +ConnectionStateChangeEventBind::RealTimeActivityConnectionStateChangeRouter( + _In_ xbox::services::real_time_activity::real_time_activity_connection_state state + ) +{ + RealTimeActivityService^ rtaService = m_setting.Resolve(); + if (rtaService != nullptr) + { + if (m_rtaCppObj->_Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([rtaService, state]() + { + rtaService->RaiseRealTimeActivityConnectedStateChange(static_cast(state)); + })); + } + else + { + rtaService->RaiseRealTimeActivityConnectedStateChange(static_cast(state)); + } + } +} + +SubscriptionErrorEventBind::SubscriptionErrorEventBind( + _In_ Platform::WeakReference setting, + _In_ std::shared_ptr cppObj + ) : + m_setting(setting), + m_rtaCppObj(std::move(cppObj)), + m_functionContext(0) +{ +} + +void +SubscriptionErrorEventBind::AddSubscriptionErrorEvent() +{ + if (m_functionContext == 0) + { + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_rtaCppObj->add_subscription_error_handler([thisWeakPtr](_In_ const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->RealTimeActivitySubscriptionErrorRouter(args); + } + }); + } +} + +void +SubscriptionErrorEventBind::RemoveSubscriptionErrorEvent() +{ + if (m_functionContext != 0) + { + m_rtaCppObj->remove_subscription_error_handler(m_functionContext); + m_functionContext = 0; + } +} + +void +SubscriptionErrorEventBind::RealTimeActivitySubscriptionErrorRouter( + _In_ const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& args + ) +{ + RealTimeActivityService^ rtaService = m_setting.Resolve(); + if (rtaService != nullptr) + { + if (m_rtaCppObj->_Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([rtaService, args]() + { + rtaService->RaiseRealTimeActivitySubscriptionError(ref new RealTimeActivitySubscriptionErrorEventArgs(args)); + })); + } + else + { + rtaService->RaiseRealTimeActivitySubscriptionError(ref new RealTimeActivitySubscriptionErrorEventArgs(args)); + } + } +} + +ResyncEventBind::ResyncEventBind( + _In_ Platform::WeakReference setting, + _In_ std::shared_ptr cppObj + ) : + m_setting(setting), + m_rtaCppObj(std::move(cppObj)), + m_functionContext(0) +{ +} + +void +ResyncEventBind::AddResyncEvent() +{ + if (m_functionContext == 0) + { + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_rtaCppObj->add_resync_handler([thisWeakPtr](void) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->RealTimeActivityResyncRouter(); + } + }); + } +} + +void +ResyncEventBind::RemoveResyncEvent() +{ + if (m_functionContext != 0) + { + m_rtaCppObj->remove_resync_handler(m_functionContext); + m_functionContext = 0; + } +} + +void +ResyncEventBind::RealTimeActivityResyncRouter() +{ + RealTimeActivityService^ rtaService = m_setting.Resolve(); + if (rtaService != nullptr) + { + if (m_rtaCppObj->_Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([rtaService]() + { + rtaService->RaiseRealTimeActivityResync(ref new RealTimeActivityResyncEventArgs()); + })); + } + else + { + rtaService->RaiseRealTimeActivityResync(ref new RealTimeActivityResyncEventArgs()); + } + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.h b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.h new file mode 100644 index 00000000..2192276a --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivityService_WinRT.h @@ -0,0 +1,141 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/real_time_activity.h" +#include "xsapi/xbox_live_context_settings.h" +#include "RealTimeActivityConnectionState_WinRT.h" +#include "RealTimeActivitySubscriptionErrorEventArgs_WinRT.h" +#include "RealTimeActivityResyncEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +class ConnectionStateChangeEventBind : public std::enable_shared_from_this +{ +public: + ConnectionStateChangeEventBind( + _In_ Platform::WeakReference setting, + _In_ std::shared_ptr cppObj + ); + + void AddConnectionStateChangeEvent(); + + void RemoveConnectionStateChangeEvent(); + + void RealTimeActivityConnectionStateChangeRouter(_In_ xbox::services::real_time_activity::real_time_activity_connection_state state); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + std::shared_ptr m_rtaCppObj; +}; + +class SubscriptionErrorEventBind : public std::enable_shared_from_this +{ +public: + SubscriptionErrorEventBind( + _In_ Platform::WeakReference setting, + _In_ std::shared_ptr cppObj + ); + + void AddSubscriptionErrorEvent(); + + void RemoveSubscriptionErrorEvent(); + + void RealTimeActivitySubscriptionErrorRouter(_In_ const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& args); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + std::shared_ptr m_rtaCppObj; +}; + +class ResyncEventBind : public std::enable_shared_from_this +{ +public: + ResyncEventBind( + _In_ Platform::WeakReference setting, + _In_ std::shared_ptr cppObj + ); + + void AddResyncEvent(); + + void RemoveResyncEvent(); + + void RealTimeActivityResyncRouter(); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + std::shared_ptr m_rtaCppObj; +}; + +/// +/// Represents a client side service that handles connections and communications with +/// the Xbox Live real-time activity service. +/// +public ref class RealTimeActivityService sealed +{ +public: + /// + /// Starts a background task that creates and initializes a websocket connection to the + /// Xbox Live real-time activity service. + /// + void Activate(); + + /// + /// Cancels all existing subscriptions to the Xbox Live real-time activity service, + /// unhooks from the websocket connection, and stops the background task. + /// + void Deactivate(); + + /// + /// A notification that is sent when the client service loses or gains connectivity to the + /// Xbox Live service. + /// Event handlers receive a RealTimeActivitySubscriptionState^ object. + /// + event Windows::Foundation::EventHandler^ RealTimeActivityConnectionStateChange; + + /// + /// Registers a handler function to recieve a notification that is sent when there is an + /// error in the real time activity service. + /// Event handlers recieve a real_time_activity_subscription_error_event_args& object. + /// + event Windows::Foundation::EventHandler^ RealTimeActivitySubscriptionError; + + /// + /// Registers a handler function to recieve a notification that is sent when there is a + /// resync message from the real time activity serivce. + /// This message indicates that data may have been lost and to resync all data by calling + /// corresponding REST API's + /// + event Windows::Foundation::EventHandler^ RealTimeActivityResync; + +internal: + RealTimeActivityService( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + + void RaiseRealTimeActivityConnectedStateChange(_In_ RealTimeActivityConnectionState state); + + void RaiseRealTimeActivitySubscriptionError(_In_ RealTimeActivitySubscriptionErrorEventArgs^ args); + + void RaiseRealTimeActivityResync(_In_ RealTimeActivityResyncEventArgs^ args); + +private: + ~RealTimeActivityService(); + std::shared_ptr m_cppObj; + std::shared_ptr m_connectionStateChangeEventBind; + std::shared_ptr m_subscriptionErrorEventBind; + std::shared_ptr m_resyncEventBind; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.cpp b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.cpp new file mode 100644 index 00000000..06ab062d --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.cpp @@ -0,0 +1,57 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "RealTimeActivitySubscriptionErrorEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +RealTimeActivitySubscriptionErrorEventArgs::RealTimeActivitySubscriptionErrorEventArgs( + _In_ xbox::services::real_time_activity::real_time_activity_subscription_error_event_args args + ) : + m_cppObj(std::move(args)), + m_errorMessage(ref new Platform::String(utility::conversions::utf8_to_utf16(m_cppObj.err_message()).c_str())), + m_subscriptionError(static_cast(args.err().value())), + m_subscriptionId(args.subscription().subscription_id()), + m_resourceUri(ref new Platform::String(args.subscription().resource_uri().c_str())), + m_state(static_cast(args.subscription().state())) +{ +} + +Platform::String^ +RealTimeActivitySubscriptionErrorEventArgs::ErrorMessage::get() +{ + return m_errorMessage; +} + +RealTimeActivitySubscriptionState +RealTimeActivitySubscriptionErrorEventArgs::State::get() +{ + return m_state; +} + +uint32_t +RealTimeActivitySubscriptionErrorEventArgs::SubscriptionId::get() +{ + return m_subscriptionId; +} + +Platform::String^ +RealTimeActivitySubscriptionErrorEventArgs::ResourceUri::get() +{ + return m_resourceUri; +} + +RealTimeActivitySubscriptionError +RealTimeActivitySubscriptionErrorEventArgs::SubscriptionError::get() +{ + return m_subscriptionError; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.h b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.h new file mode 100644 index 00000000..d0314972 --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionErrorEventArgs_WinRT.h @@ -0,0 +1,57 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/real_time_activity.h" +#include "RealTimeActivitySubscriptionError_WinRT.h" +#include "RealTimeActivitySubscriptionState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +public ref class RealTimeActivitySubscriptionErrorEventArgs sealed +{ +public: + property RealTimeActivitySubscriptionState State + { + RealTimeActivitySubscriptionState get(); + }; + + property uint32_t SubscriptionId + { + uint32_t get(); + }; + + property Platform::String^ ResourceUri + { + Platform::String^ get(); + }; + + property RealTimeActivitySubscriptionError SubscriptionError + { + RealTimeActivitySubscriptionError get(); + }; + + property Platform::String^ ErrorMessage + { + Platform::String^ get(); + }; + +internal: + RealTimeActivitySubscriptionErrorEventArgs(_In_ xbox::services::real_time_activity::real_time_activity_subscription_error_event_args args); + +private: + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args m_cppObj; + RealTimeActivitySubscriptionError m_subscriptionError; + Platform::String^ m_resourceUri; + RealTimeActivitySubscriptionState m_state; + uint32_t m_subscriptionId; + Platform::String^ m_errorMessage; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionError_WinRT.h b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionError_WinRT.h new file mode 100644 index 00000000..6eeb4bb4 --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionError_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +public enum class RealTimeActivitySubscriptionError +{ + NoError = xbox::services::xbox_live_error_code::no_error, + + JsonError = xbox::services::xbox_live_error_code::json_error, + + RTAGenericError = xbox::services::xbox_live_error_code::rta_generic_error, + + RTASubscriptionLimit = xbox::services::xbox_live_error_code::rta_subscription_limit_reached, + + RTAAccessDenied = xbox::services::xbox_live_error_code::rta_access_denied +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionState_WinRT.h b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionState_WinRT.h new file mode 100644 index 00000000..10283d54 --- /dev/null +++ b/Source/Services/RealTimeActivity/WinRT/RealTimeActivitySubscriptionState_WinRT.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_BEGIN + +/// +/// Enumeration for the possible states of a statistic subscription request +/// to the real-time activity service. +/// +public enum class RealTimeActivitySubscriptionState +{ + /// + /// The subscription state is unknown. + /// + Unknown = xbox::services::real_time_activity::real_time_activity_subscription_state::unknown, + + /// + /// Waiting for the server to respond to the subscription request. + /// + PendingSubscribe = xbox::services::real_time_activity::real_time_activity_subscription_state::pending_subscribe, + + /// + /// Subscription confirmed. + /// + Subscribed = xbox::services::real_time_activity::real_time_activity_subscription_state::subscribed, + + /// + /// Waiting for the server to respond to the unsubscribe request. + /// + PendingUnsubscribe = xbox::services::real_time_activity::real_time_activity_subscription_state::pending_unsubscribe, + + /// + /// Unsubscribe confirmed. + /// + Closed = xbox::services::real_time_activity::real_time_activity_subscription_state::closed +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/real_time_activity_internal.h b/Source/Services/RealTimeActivity/real_time_activity_internal.h new file mode 100644 index 00000000..5150de65 --- /dev/null +++ b/Source/Services/RealTimeActivity/real_time_activity_internal.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +namespace xbox { namespace services { namespace real_time_activity { + +struct real_time_activity_service_factory_counter +{ + real_time_activity_service_factory_counter() : counter(1) {} + + uint32_t counter; + std::shared_ptr rtaService; +}; + +class real_time_activity_service_factory +{ +public: + real_time_activity_service_factory(); + + static std::shared_ptr get_singleton_instance(); + + const std::shared_ptr& get_rta_instance( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ); + + void remove_user_from_rta_map( + _In_ std::shared_ptr userContext + ); + +private: + std::unordered_map m_xuidToRTAMap; +}; + +}}} \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/real_time_activity_service.cpp b/Source/Services/RealTimeActivity/real_time_activity_service.cpp new file mode 100644 index 00000000..23e017d7 --- /dev/null +++ b/Source/Services/RealTimeActivity/real_time_activity_service.cpp @@ -0,0 +1,806 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Utils.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "xsapi/real_time_activity.h" +#include "web_socket_connection.h" +#include "web_socket_connection_state.h" +#include "web_socket_client.h" +#include "utils.h" +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_BEGIN + +real_time_activity_service::real_time_activity_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_sequenceNumber(0), + m_subscriptionErrorHandlerCounter(0), + m_connectionStateChangeHandlerCounter(0), + m_resyncHandlerCounter(0), + m_connectionState(real_time_activity_connection_state::disconnected) +{ +} + +real_time_activity_service::~real_time_activity_service() +{ + if (m_userContext->caller_context_type() == caller_context_type::title) + { + deactivate(); + } +} + +void +real_time_activity_service::activate() +{ + std::lock_guard lock(m_lock); + int activationCount = 0; + { + std::lock_guard guard(get_xsapi_singleton()->s_rtaActivationCounterLock); + if (m_webSocketConnection == nullptr) + { + activationCount = ++get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[m_userContext->xbox_user_id()]; + + LOGS_DEBUG << "websocket count is at " << get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[m_userContext->xbox_user_id()] << " for user " << m_userContext->xbox_user_id(); + } + + if (m_userContext->caller_context_type() == caller_context_type::multiplayer_manager || + m_userContext->caller_context_type() == caller_context_type::social_manager) + { + ++get_xsapi_singleton()->s_rtaActiveManagersByUser[m_userContext->xbox_user_id()]; + LOGS_DEBUG << "websocket manager count is at " << get_xsapi_singleton()->s_rtaActiveManagersByUser[m_userContext->xbox_user_id()] << " for user " << m_userContext->xbox_user_id(); + } + } + + if (activationCount > MAXIMUM_WEBSOCKETS_ACTIVATIONS_ALLOWED_PER_USER) + { + std::shared_ptr appConfig = xbox::services::xbox_live_app_config::get_app_config_singleton(); + if (utils::str_icmp(appConfig->sandbox(), _T("RETAIL")) != 0) + { + bool disableAsserts = m_xboxLiveContextSettings->_Is_disable_asserts_for_max_number_of_websockets_activated(); + if (!disableAsserts) + { +#if UNIT_TEST_SERVICES + std::lock_guard guard(get_xsapi_singleton()->s_rtaActivationCounterLock); + --get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[m_userContext->xbox_user_id()]; +#endif + std::stringstream msg; + LOGS_ERROR << "You've currently activated " << activationCount << " websockets."; + LOGS_ERROR << "We recommend you don't activate more than " << MAXIMUM_WEBSOCKETS_ACTIVATIONS_ALLOWED_PER_USER << " websockets"; + LOGS_ERROR << "You can temporarily disable the assert by calling"; + LOGS_ERROR << "xboxLiveContext->settings()->disable_asserts_for_maximum_number_of_websockets_activated()"; + LOGS_ERROR << "however the issue must be addressed before certification."; + + XSAPI_ASSERT(false); + } + } + } + + if (m_webSocketConnection == nullptr) + { + std::weak_ptr thisWeakPtr = shared_from_this(); + +#if TV_API + m_rtaShutdownToken = + Windows::ApplicationModel::Core::CoreApplication::Suspending += ref new Windows::Foundation::EventHandler + ([thisWeakPtr](_In_opt_ Platform::Object^ sender, _In_ Windows::ApplicationModel::SuspendingEventArgs^ eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->deactivate(); + } + }); +#elif UWP_API + m_rtaShutdownToken = + Windows::ApplicationModel::Core::CoreApplication::Exiting += ref new Windows::Foundation::EventHandler + ([thisWeakPtr](_In_opt_ Platform::Object^ sender, _In_ Platform::Object^ eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->deactivate(); + } + }); +#endif + + stringstream_t endpoint; + endpoint << utils::create_xboxlive_endpoint(_T("rta"), m_appConfig, _T("wss")); + endpoint << _T("/connect"); + + m_webSocketConnection = std::make_shared( + m_userContext, + endpoint.str(), + _T("rta.xboxlive.com.V2"), + m_xboxLiveContextSettings + ); + + // We will reset these event handler on destructor, so it's safe to pass in 'this' here. + m_webSocketConnection->set_connection_state_change_handler([thisWeakPtr](web_socket_connection_state oldState, web_socket_connection_state newState) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_socket_connection_state_change(oldState, newState); + } + }); + + m_webSocketConnection->set_received_handler([thisWeakPtr](string_t message) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->on_socket_message_received(message); + } + }); + + m_webSocketConnection->ensure_connected(); + } +} + +void +real_time_activity_service::deactivate() +{ + if (get_xsapi_singleton(false) != nullptr) // skip this if process is shutting down + { + std::lock_guard guard(get_xsapi_singleton()->s_rtaActivationCounterLock); + auto& xuid = m_userContext->xbox_user_id(); + if (m_userContext->caller_context_type() == caller_context_type::title) + { + if (m_webSocketConnection != nullptr && get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[xuid] > 0) + { + --get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[xuid]; + } + } + else if(get_xsapi_singleton()->s_rtaActiveManagersByUser[xuid] != 0) + { + auto counter = --get_xsapi_singleton()->s_rtaActiveManagersByUser[xuid]; + if (counter > 0 ) + { + // Since the Managers share the RTA service, only close the socket on the last deactivate() call for that user. + return; + } + --get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[xuid]; + LOGS_DEBUG << "websocket count is at " << get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[xuid] << " for user " << xuid; + get_xsapi_singleton()->s_rtaActiveManagersByUser.erase(xuid); + } + + if (get_xsapi_singleton()->s_rtaActiveSocketCountPerUser[xuid] == 0) + { + get_xsapi_singleton()->s_rtaActiveSocketCountPerUser.erase(xuid); + } + } + + try + { +#if TV_API + Windows::ApplicationModel::Core::CoreApplication::Suspending -= m_rtaShutdownToken; +#elif UWP_API + Windows::ApplicationModel::Core::CoreApplication::Exiting -= m_rtaShutdownToken; +#endif + } + catch (...) + { + LOG_ERROR("Exception on unregistering CoreApplication events!"); + } + + _Close_websocket(); + + // _Close_websocket has it's own locking inside, don't include in the next lock + { + std::lock_guard lock(m_lock); + m_connectionStateChangeHandler.clear(); + m_connectionStateChangeHandlerCounter = 0; + m_subscriptionErrorHandler.clear(); + m_subscriptionErrorHandlerCounter = 0; + } + +} + +function_context +real_time_activity_service::add_connection_state_change_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_lock); + function_context context = -1; + if (handler != nullptr) + { + context = ++m_connectionStateChangeHandlerCounter; + m_connectionStateChangeHandler[m_connectionStateChangeHandlerCounter] = std::move(handler); + + // Since you could have activated the service already for this context, trigger a state changed event. + if (m_connectionState != disconnected) + { + trigger_connection_state_changed_event(m_connectionState); + } + } + + return context; +} + +void +real_time_activity_service::remove_connection_state_change_handler( + _In_ function_context remove + ) +{ + std::lock_guard lock(m_lock); + m_connectionStateChangeHandler.erase(remove); +} + +function_context +real_time_activity_service::add_subscription_error_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_lock); + function_context context = -1; + if (handler != nullptr) + { + context = ++m_subscriptionErrorHandlerCounter; + m_subscriptionErrorHandler[m_subscriptionErrorHandlerCounter] = std::move(handler); + } + + return context; +} + +void +real_time_activity_service::remove_subscription_error_handler( + _In_ function_context remove + ) +{ + std::lock_guard lock(m_lock); + m_subscriptionErrorHandler.erase(remove); +} + +void +real_time_activity_service::trigger_resync_event() +{ + std::unordered_map> resyncHandlerCopy; + { + std::lock_guard lock(m_lock); + resyncHandlerCopy = m_resyncHandler; + } + + for (auto& resyncHandler : resyncHandlerCopy) + { + XSAPI_ASSERT(resyncHandler.second != nullptr); + if (resyncHandler.second != nullptr) + { + try + { + resyncHandler.second(); + } + catch (...) + { + } + } + } +} + +function_context +real_time_activity_service::add_resync_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_lock); + function_context context = -1; + if (handler != nullptr) + { + context = ++m_resyncHandlerCounter; + m_resyncHandler[m_resyncHandlerCounter] = std::move(handler); + } + + return context; +} + +void +real_time_activity_service::remove_resync_handler( + _In_ function_context remove + ) +{ + std::lock_guard lock(m_lock); + m_resyncHandler.erase(remove); +} + +void +real_time_activity_service::_Trigger_subscription_error( + real_time_activity_subscription_error_event_args args + ) +{ + std::unordered_map> subscriptionErrorHandlerCopy; + LOGS_DEBUG << "RTA subscription error occurred"; + { + std::lock_guard lock(m_lock); + subscriptionErrorHandlerCopy = m_subscriptionErrorHandler; + } + + for (auto& subHandler : subscriptionErrorHandlerCopy) + { + XSAPI_ASSERT(subHandler.second != nullptr); + if (subHandler.second != nullptr) + { + try + { + subHandler.second(args); + } + catch (...) + { + } + } + } +} + +void real_time_activity_service::clear_all_subscriptions() +{ + for (auto& subscriptionPair : m_pendingResponseSubscriptions) + { + auto subscription = subscriptionPair.second; + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + m_pendingResponseSubscriptions.clear(); + + for (auto& subscriptionPair : m_subscriptions) + { + auto subscription = subscriptionPair.second; + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + m_subscriptions.clear(); + + for (auto& subscriptionPair : m_pendingUnsubscriptions) + { + auto subscription = subscriptionPair.second; + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + m_pendingUnsubscriptions.clear(); + + for (auto& subscription : m_pendingSubmission) + { + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + m_pendingSubmission.clear(); +} + +void +real_time_activity_service::on_socket_connection_state_change( + _In_ web_socket_connection_state oldState, + _In_ web_socket_connection_state newState + ) +{ + if (oldState == newState) return; + + if (web_socket_connection_state::activated == newState) return; + + std::lock_guard lock(m_lock); + { + if (newState == web_socket_connection_state::disconnected) + { + m_connectionState = real_time_activity_connection_state::disconnected; + + clear_all_subscriptions(); + trigger_connection_state_changed_event(real_time_activity_connection_state::disconnected); + } + + // On connecting, set subscriptions state accordingly. + if (newState == web_socket_connection_state::connecting) + { + m_connectionState = real_time_activity_connection_state::connecting; + for (auto& subscriptionPair : m_subscriptions) + { + auto subscription = subscriptionPair.second; + subscription->_Set_state(real_time_activity_subscription_state::pending_subscribe); + m_pendingSubmission.push_back(subscription); + } + m_subscriptions.clear(); + + for (auto& subscriptionPair : m_pendingResponseSubscriptions) + { + auto subscription = subscriptionPair.second; + subscription->_Set_state(real_time_activity_subscription_state::pending_subscribe); + m_pendingSubmission.push_back(subscription); + } + m_pendingResponseSubscriptions.clear(); + + // clear out pending unsubscriptions, as it will be reset by service. + for (auto& subscriptionPair : m_pendingUnsubscriptions) + { + auto subscription = subscriptionPair.second; + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + m_pendingUnsubscriptions.clear(); + + trigger_connection_state_changed_event(real_time_activity_connection_state::connecting); + } + + // socket reconnected, re-subscribe everything + if (newState == web_socket_connection_state::connected) + { + m_connectionState = real_time_activity_connection_state::connected; + submit_subscriptions(); + trigger_connection_state_changed_event(real_time_activity_connection_state::connected); + } + } +} + +void +real_time_activity_service::trigger_connection_state_changed_event( + _In_ real_time_activity_connection_state connectionState + ) +{ + std::unordered_map> connectionStateChangeHandlers; + { + std::lock_guard lock(m_lock); + connectionStateChangeHandlers = m_connectionStateChangeHandler; + } + + for (auto& connectionHandler : connectionStateChangeHandlers) + { + XSAPI_ASSERT(connectionHandler.second != nullptr); + if (connectionHandler.second != nullptr) + { + try + { + connectionHandler.second(connectionState); + } + catch (...) + { + } + } + } +} + +void +real_time_activity_service::on_socket_message_received( + _In_ const string_t& message + ) +{ + auto msgJson = web::json::value::parse(message); + real_time_activity_message_type messageType = static_cast(msgJson[0].as_integer()); + + switch (messageType) + { + case real_time_activity_message_type::subscribe: + complete_subscribe(msgJson); + break; + case real_time_activity_message_type::unsubscribe: + complete_unsubscribe(msgJson); + break; + case real_time_activity_message_type::change_event: + handle_change_event(msgJson); + break; + case real_time_activity_message_type::resync: + trigger_resync_event(); + break; + default: + throw std::runtime_error("Unexpected websocket message"); + break; + } +} + +void +real_time_activity_service::handle_change_event( + _In_ web::json::value& message + ) +{ + // response format: + //[, , ] + int subscriptionId = message[1].as_integer(); + const auto& data = message[2]; + + std::shared_ptr subscription; + { + std::lock_guard lock(m_lock); + auto iter = m_subscriptions.find(subscriptionId); + if (iter != m_subscriptions.end()) + { + subscription = iter->second; + } + } + + if (subscription != nullptr) + { + subscription->on_event_received(data); + } +} + +void +real_time_activity_service::complete_subscribe( + _In_ web::json::value& message + ) +{ + // subscribe response format: + // [, , , , ] + int32_t sequenceNum = message[1].as_integer(); + int32_t code = message[2].as_integer(); + std::shared_ptr subscription; + { + std::lock_guard guard(m_lock); + auto iter = m_pendingResponseSubscriptions.find(sequenceNum); + if (iter != m_pendingResponseSubscriptions.end()) + { + subscription = iter->second; + m_pendingResponseSubscriptions.erase(iter); + + } + } + + if (subscription != nullptr) + { + if (code == 0) + { + int subscriptionId = message[3].as_integer(); + const auto& data = message[4]; + + { + std::lock_guard guard(m_lock); + m_subscriptions[subscriptionId] = subscription; + } + + subscription->on_subscription_created(subscriptionId, data); + } + else + { + auto xboxLiveErrCode = convert_rta_error_code_to_xbox_live_error_code(code); + subscription->_Set_state(real_time_activity_subscription_state::closed); + + std::string errorStr = utility::conversions::to_utf8string(message[3].as_string()); + _Trigger_subscription_error( + real_time_activity_subscription_error_event_args( + *subscription, + xboxLiveErrCode, + errorStr + ) + ); + } + } + else + { + LOG_ERROR("No subscription found that matches recieved message"); + } +} + +void +real_time_activity_service::complete_unsubscribe( + _In_ web::json::value& message + ) +{ + // response format: + // [, , ] + int sequenceNum = message[1].as_integer(); + + std::shared_ptr subscription; + { + std::lock_guard guard(m_lock); + auto iter = m_pendingUnsubscriptions.find(sequenceNum); + if (iter != m_pendingUnsubscriptions.end()) + { + subscription = iter->second; + m_pendingUnsubscriptions.erase(iter); + + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + } +} + +xbox_live_result +real_time_activity_service::_Add_subscription( + _In_ std::shared_ptr subscription + ) +{ + if (subscription == nullptr) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "subscription is null"); + } + + std::lock_guard guard(m_lock); + if ((m_webSocketConnection == nullptr || (m_webSocketConnection != nullptr && m_webSocketConnection->state() == web_socket_connection_state::disconnected)) && + m_connectionState == real_time_activity_connection_state::disconnected) + { + return xbox_live_result( + xbox_live_error_code::invalid_argument, + "The webscoket has been deactivated. Call activate to reconnect." + ); + } + + subscription->_Set_state(real_time_activity_subscription_state::pending_subscribe); + m_pendingSubmission.push_back(subscription); + if (m_connectionState == real_time_activity_connection_state::connected) + { + submit_subscriptions(); + } + + return xbox_live_result(); +} + +void +real_time_activity_service::submit_subscriptions() +{ + while (m_webSocketConnection != nullptr && !m_pendingSubmission.empty()) + { + auto subscription = m_pendingSubmission.back(); + m_pendingSubmission.pop_back(); + int sequenceNumber = utils::interlocked_increment(m_sequenceNumber); + m_pendingResponseSubscriptions[sequenceNumber] = subscription; + + web::json::value request; + request[0] = static_cast(real_time_activity_message_type::subscribe); + request[1] = sequenceNumber; + request[2] = web::json::value(subscription->resource_uri()); + + m_webSocketConnection->send(request.serialize()) + .then([](task t) + { + try + { + t.get(); + } + catch (...) + { + // Throws this exception on failure to send, our retry logic once the websocket comes back online will resend + } + }); + } +} + +xbox_live_result +real_time_activity_service::_Remove_subscription( + _In_ std::shared_ptr subscription + ) +{ + if (subscription == nullptr) + { + return xbox_live_result( + xbox_live_error_code::invalid_argument, + "subscription is null" + ); + } + + std::lock_guard guard(m_lock); + auto subscriptionId = subscription->subscription_id(); + + if (subscription->state() == real_time_activity_subscription_state::subscribed) + { + auto iter = m_subscriptions.find(subscriptionId); + if (iter != m_subscriptions.end()) + { + auto subscriptionIter = iter->second; + m_subscriptions.erase(iter); + + int sequenceNumber = utils::interlocked_increment(m_sequenceNumber); + subscriptionIter->_Set_state(real_time_activity_subscription_state::pending_unsubscribe); + m_pendingUnsubscriptions[sequenceNumber] = subscriptionIter; + + web::json::value request; + request[0] = static_cast(real_time_activity_message_type::unsubscribe); + request[1] = sequenceNumber; + request[2] = subscriptionId; + + auto asyncOp = m_webSocketConnection->send(request.serialize()) + .then([subscriptionIter](task t) + { + try + { + t.get(); + } + catch (const web::websockets::client::websocket_exception&) + { + } + }); + } + } + else if(subscription->state() == real_time_activity_subscription_state::pending_subscribe) + { + std::vector>::iterator it = m_pendingSubmission.begin(); + bool found = false; + for (it; it != m_pendingSubmission.end(); ++it) + { + auto pendingSubmission = *it; + if (pendingSubmission->m_guid == subscription->m_guid) + { + found = true; + m_pendingSubmission.erase(it); + break; + } + } + + if (!found) + { + std::map>::iterator responseIt = m_pendingResponseSubscriptions.begin(); + for (responseIt; responseIt != m_pendingResponseSubscriptions.end(); ++responseIt) + { + auto pendingResponse = *responseIt; + if (pendingResponse.second->m_guid == subscription->m_guid) + { + m_pendingResponseSubscriptions.erase(responseIt); + break; + } + } + } + + subscription->_Set_state(real_time_activity_subscription_state::closed); + } + return xbox_live_result(); +} + +void +real_time_activity_service::_Close_websocket() +{ + std::shared_ptr socketToClean; + { + std::lock_guard lock(m_lock); + // RTA service will cleanup subscription on websocket close, no need + // to send unsubscribe msg on websocket closing. Just to clear all local + // stored subscriptions + clear_all_subscriptions(); + + socketToClean = m_webSocketConnection; + m_webSocketConnection = nullptr; + m_connectionState = real_time_activity_connection_state::disconnected; + } + + if (socketToClean != nullptr) + { + socketToClean->set_received_handler(nullptr); + + socketToClean->close().then([socketToClean](task t) + { + try + { + // Hold the reference to the shared point, so it won't deconsturct + auto socketConnectionSharedCopy = socketToClean; + t.get(); + socketConnectionSharedCopy = nullptr; + } + catch (...) + { + } + }); + + socketToClean->set_connection_state_change_handler(nullptr); + } +} + +std::error_code +real_time_activity_service::convert_rta_error_code_to_xbox_live_error_code( + _In_ int32_t rtaErrorCode + ) +{ + switch (rtaErrorCode) + { + case 0: return xbox_live_error_code::no_error; + case 1: return xbox_live_error_code::rta_subscription_limit_reached; + case 2: return xbox_live_error_code::rta_access_denied; + default: return xbox_live_error_code::rta_generic_error; + } +} + +std::unordered_map +real_time_activity_service::_Rta_activation_map() +{ + std::lock_guard guard(get_xsapi_singleton()->s_rtaActivationCounterLock); + return get_xsapi_singleton(true)->s_rtaActiveSocketCountPerUser; +} + +std::unordered_map +real_time_activity_service::_Rta_manager_activation_map() +{ + std::lock_guard guard(get_xsapi_singleton()->s_rtaActivationCounterLock); + return get_xsapi_singleton(true)->s_rtaActiveManagersByUser; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/real_time_activity_service_factory.cpp b/Source/Services/RealTimeActivity/real_time_activity_service_factory.cpp new file mode 100644 index 00000000..c9ea0768 --- /dev/null +++ b/Source/Services/RealTimeActivity/real_time_activity_service_factory.cpp @@ -0,0 +1,93 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "user_context.h" +#include "xsapi/real_time_activity.h" +#include "real_time_activity_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_BEGIN +static std::mutex s_singletonLock; + +std::shared_ptr +real_time_activity_service_factory::get_singleton_instance() +{ + std::lock_guard guard(s_singletonLock); + static std::shared_ptr instance; + if (instance == nullptr) + { + instance = std::make_shared(); + } + + return instance; +} + +real_time_activity_service_factory::real_time_activity_service_factory() +{ +} + +const std::shared_ptr& +real_time_activity_service_factory::get_rta_instance( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) +{ + std::lock_guard guard(s_singletonLock); + XSAPI_ASSERT(userContext != nullptr); + + auto xboxUserId = userContext->xbox_user_id(); + auto iter = m_xuidToRTAMap.find(xboxUserId); + if (iter == m_xuidToRTAMap.end()) + { + auto rtaService = std::shared_ptr( + new real_time_activity_service( + userContext, + xboxLiveContextSettings, + appConfig + )); + + real_time_activity_service_factory_counter rtaImplCounter; + rtaImplCounter.rtaService = rtaService; + m_xuidToRTAMap[xboxUserId] = rtaImplCounter; + iter = m_xuidToRTAMap.find(xboxUserId); + } + else + { + ++iter->second.counter; + } + + return iter->second.rtaService; +} + +void +real_time_activity_service_factory::remove_user_from_rta_map( + _In_ std::shared_ptr userContext + ) +{ + std::lock_guard guard(s_singletonLock); + XSAPI_ASSERT(userContext != nullptr); + auto& xuid = userContext->xbox_user_id(); + if (!xuid.empty()) + { + auto iter = m_xuidToRTAMap.find(xuid); + if (iter == m_xuidToRTAMap.end()) + { + return; + } + + --iter->second.counter; + if (iter->second.counter == 0) + { + m_xuidToRTAMap.erase(xuid); + } + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/real_time_activity_subscription.cpp b/Source/Services/RealTimeActivity/real_time_activity_subscription.cpp new file mode 100644 index 00000000..8ec8f373 --- /dev/null +++ b/Source/Services/RealTimeActivity/real_time_activity_subscription.cpp @@ -0,0 +1,104 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "xsapi/real_time_activity.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_BEGIN + +real_time_activity_subscription::real_time_activity_subscription( + _In_ std::function subscriptionErrorHandler + ) : + m_subscriptionErrorHandler(std::move(subscriptionErrorHandler)), + m_state(real_time_activity_subscription_state::unknown), + m_guid(xbox::services::utils::create_guid(true)) +{ + XSAPI_ASSERT(m_subscriptionErrorHandler != nullptr); +} + +real_time_activity_subscription_state +real_time_activity_subscription::state() const +{ + return m_state; +} + +void +real_time_activity_subscription::_Set_state( + _In_ real_time_activity_subscription_state newState + ) +{ + // if state is change from subscribed, reset subscription id + if (m_state == subscribed && newState != real_time_activity_subscription_state::subscribed) + { + m_subscriptionId = 0; + } + m_state = newState; + on_state_changed(m_state); +} + +const string_t& +real_time_activity_subscription::resource_uri() const +{ + return m_resourceUri; +} + +void +real_time_activity_subscription::set_resource_uri( + _In_ string_t uri + ) +{ + m_resourceUri = std::move(uri); +} + +uint32_t +real_time_activity_subscription::subscription_id() const +{ + return m_subscriptionId; +} + +void +real_time_activity_subscription::set_subscription_id( + _In_ uint32_t id + ) +{ + m_subscriptionId = id; +} + +void +real_time_activity_subscription::on_event_received( + _In_ const web::json::value& data + ) +{ + // Nothing need to do on the base class. + UNREFERENCED_PARAMETER(data); +} + +void +real_time_activity_subscription::on_subscription_created( + _In_ uint32_t id, + _In_ const web::json::value& data + ) +{ + UNREFERENCED_PARAMETER(data); + m_subscriptionId = id; + _Set_state(real_time_activity_subscription_state::subscribed); +} + +void +real_time_activity_subscription::on_state_changed( + _In_ real_time_activity_subscription_state state + ) +{ + // Nothing need to do on the base class. + UNREFERENCED_PARAMETER(state); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_END \ No newline at end of file diff --git a/Source/Services/RealTimeActivity/real_time_activity_subscription_error_event_args.cpp b/Source/Services/RealTimeActivity/real_time_activity_subscription_error_event_args.cpp new file mode 100644 index 00000000..cadcf35d --- /dev/null +++ b/Source/Services/RealTimeActivity/real_time_activity_subscription_error_event_args.cpp @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/real_time_activity.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_BEGIN + +real_time_activity_subscription_error_event_args::real_time_activity_subscription_error_event_args( + real_time_activity_subscription subscription, + std::error_code errc, + std::string errMessage + ) : + m_subscription(std::move(subscription)), + m_err(std::move(errc)), + m_errorMessage(std::move(errMessage)) +{ +} + +const real_time_activity_subscription& +real_time_activity_subscription_error_event_args::subscription() +{ + return m_subscription; +} + +const std::error_code& +real_time_activity_subscription_error_event_args::err() +{ + return m_err; +} + +const std::string& +real_time_activity_subscription_error_event_args::err_message() +{ + return m_errorMessage; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_RTA_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.cpp b/Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.cpp new file mode 100644 index 00000000..3cca2d40 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.cpp @@ -0,0 +1,22 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "PreferredColor_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +PreferredColor::PreferredColor( + _In_ xbox::services::social::manager::preferred_color cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.h b/Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.h new file mode 100644 index 00000000..ab267ce7 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/PreferredColor_WinRT.h @@ -0,0 +1,45 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// The users preferred color scheme +/// +public ref class PreferredColor sealed +{ +public: + /// + /// The user's primary preferred color + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(PrimaryColor, primary_color); + + /// + /// The user's secondary preferred color + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(SecondaryColor, secondary_color); + + /// + /// The user's tertiary preferred color + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(TertiaryColor, tertiary_color); + +internal: + PreferredColor( + _In_ xbox::services::social::manager::preferred_color cppObj + ); + +private: + xbox::services::social::manager::preferred_color m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialEventArgs_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialEventArgs_WinRT.h new file mode 100644 index 00000000..1dfca1d4 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialEventArgs_WinRT.h @@ -0,0 +1,19 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public interface class SocialEventArgs +{ +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialEventType_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialEventType_WinRT.h new file mode 100644 index 00000000..965f1b08 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialEventType_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public enum class SocialEventType +{ + /// Users added to social graph + UsersAddedToSocialGraph = xbox::services::social::manager::social_event_type::users_added_to_social_graph, + + /// Users removed from + UsersRemovedFromSocialGraph = xbox::services::social::manager::social_event_type::users_removed_from_social_graph, + + /// Users presence record has changed + PresenceChanged = xbox::services::social::manager::social_event_type::presence_changed, + + /// Users profile information has changed + ProfilesChanged = xbox::services::social::manager::social_event_type::profiles_changed, + + /// Relationship to users has changed + SocialRelationshipsChanged = xbox::services::social::manager::social_event_type::social_relationships_changed, + + /// Social graph load complete from adding a local user + LocalUserAdded = xbox::services::social::manager::social_event_type::local_user_added, + + /// Social graph removal complete + LocalUserRemoved = xbox::services::social::manager::social_event_type::local_user_removed, + + /// Xbox Social User Group load complete (will only trigger for views that take a list of users) + SocialUserGroupLoaded = xbox::services::social::manager::social_event_type::social_user_group_loaded, + + /// Social user group updated + SocialUserGroupUpdated = xbox::services::social::manager::social_event_type::social_user_group_updated +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.cpp b/Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.cpp new file mode 100644 index 00000000..1ba7c414 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.cpp @@ -0,0 +1,85 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialEvent_WinRT.h" +#include "Utils_WinRT.h" +#include "SocialUserGroupLoadedEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN +using namespace xbox::services; +using namespace xbox::services::social::manager; +using namespace Microsoft::Xbox::Services::System; + +SocialEvent::SocialEvent( + _In_ xbox::services::social::manager::social_event cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_user = user_context::user_convert(m_cppObj.user()); + auto trackedUsers = m_cppObj.users_affected(); + auto vector = ref new Platform::Collections::Vector(); + for (auto& user : trackedUsers) + { + vector->Append(ref new Platform::String(user.xbox_user_id())); + } + + m_usersAffected = vector->GetView(); + + if (m_cppObj.err()) + { + m_errorCode = ref new Platform::Exception(xbox::services::utils::convert_xbox_live_error_code_to_hresult(m_cppObj.err())); + } + + m_errorMessage = ref new Platform::String(utility::conversions::utf8_to_utf16(m_cppObj.err_message()).c_str()); +} + +XboxLiveUser_t +SocialEvent::User::get() +{ + return m_user; +} + + +Windows::Foundation::Collections::IVectorView^ +SocialEvent::UsersAffected::get() +{ + return m_usersAffected; +} + +int +SocialEvent::ErrorCode::get() +{ + if (m_errorCode == nullptr) + { + return 0; + } + + return m_errorCode->HResult; +} + +Platform::String^ +SocialEvent::ErrorMessage::get() +{ + return m_errorMessage; +} + +SocialEventArgs^ SocialEvent::EventArgs::get() +{ + switch (m_cppObj.event_type()) + { + case social_event_type::social_user_group_loaded: + return ref new SocialUserGroupLoadedEventArgs(std::dynamic_pointer_cast(m_cppObj.event_args())); + default: + return nullptr; + + } +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.h new file mode 100644 index 00000000..aa33d8bc --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialEvent_WinRT.h @@ -0,0 +1,76 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "SocialEventType_WinRT.h" +#include "XboxSocialUser_WinRT.h" +#include "user_context.h" +#include "SocialEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// An event that something in the social graph has changed +/// +public ref class SocialEvent sealed +{ +public: + /// + /// The Xbox Live user this event is for + /// + property XboxLiveUser_t User { XboxLiveUser_t get(); } + + /// + /// The type of event this is + /// Tells the caller what to cast the event_args to + /// + DEFINE_PROP_GET_ENUM_OBJ(EventType, event_type, SocialEventType); + + /// + /// List of users this event affects + /// + property Windows::Foundation::Collections::IVectorView^ UsersAffected { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The error code indicating the result of the operation. + /// + property int ErrorCode + { + int get(); + }; + + /// + /// Returns call specific debug information if join fails + /// It is not localized, so only use for debugging purposes. + /// + property Platform::String^ ErrorMessage + { + Platform::String^ get(); + }; + + property SocialEventArgs^ EventArgs + { + Microsoft::Xbox::Services::Social::Manager::SocialEventArgs^ get(); + }; + +internal: + SocialEvent( + _In_ xbox::services::social::manager::social_event cppObj + ); + +private: + XboxLiveUser_t m_user; + Windows::Foundation::Collections::IVectorView^ m_usersAffected; + xbox::services::social::manager::social_event m_cppObj; + Platform::Exception^ m_errorCode; + Platform::String^ m_errorMessage; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialManagerExtraDetailLevel_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialManagerExtraDetailLevel_WinRT.h new file mode 100644 index 00000000..98d62df4 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManagerExtraDetailLevel_WinRT.h @@ -0,0 +1,32 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// Detail level controls how much information is exposed in each xbox_live_social_graph_user +/// Detail level can only be set on construction of social_manager +/// +[Platform::Metadata::Flags] +public enum class SocialManagerExtraDetailLevel : unsigned int +{ + /// Only get default PeopleHub information (presence, profile) + NoExtraDetail = xbox::services::social::manager::social_manager_extra_detail_level::no_extra_detail, + + /// Add extra detail for the title history for the users + TitleHistoryLevel = xbox::services::social::manager::social_manager_extra_detail_level::title_history_level, + + /// Add extra detail for the preferred color for the users + PreferredColorLevel = xbox::services::social::manager::social_manager_extra_detail_level::preferred_color_level, +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END diff --git a/Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.cpp b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.cpp new file mode 100644 index 00000000..e7d99909 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.cpp @@ -0,0 +1,44 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "Utils_WinRT.h" +#include "SocialManagerPresenceRecord_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +SocialManagerPresenceRecord::SocialManagerPresenceRecord( + _In_ xbox::services::social::manager::social_manager_presence_record cppObj + ) : m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::Collections::IVectorView^ +SocialManagerPresenceRecord::PresenceTitleRecords::get() +{ + auto socialManagerPresenceTitleRecordVec = ref new Platform::Collections::Vector(); + for (auto& presenceTitleRecord : m_cppObj.presence_title_records()) + { + if (!presenceTitleRecord._Is_null()) + { + socialManagerPresenceTitleRecordVec->Append(ref new SocialManagerPresenceTitleRecord(presenceTitleRecord)); + } + } + return socialManagerPresenceTitleRecordVec->GetView(); +} + +bool +SocialManagerPresenceRecord::IsUserPlayingTitle(_In_ uint32_t titleId) +{ + return m_cppObj.is_user_playing_title(titleId); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.h new file mode 100644 index 00000000..d484751c --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceRecord_WinRT.h @@ -0,0 +1,47 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "UserPresenceState_WinRT.h" +#include "SocialManagerPresenceTitleRecord_WinRT.h" +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public ref class SocialManagerPresenceRecord sealed +{ +public: + /// + /// The user's presence state. + /// + DEFINE_PROP_GET_ENUM_OBJ(UserState, user_state, Microsoft::Xbox::Services::Presence::UserPresenceState); + + /// + /// Collection of presence title record objects returned by a request. + /// + property Windows::Foundation::Collections::IVectorView^ PresenceTitleRecords + { + Windows::Foundation::Collections::IVectorView^ get(); + }; + + /// + /// Returns whether the user is playing this title id + /// + bool IsUserPlayingTitle(_In_ uint32_t titleId); + +internal: + SocialManagerPresenceRecord( + _In_ xbox::services::social::manager::social_manager_presence_record cppObj + ); + +private: + xbox::services::social::manager::social_manager_presence_record m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.cpp b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.cpp new file mode 100644 index 00000000..03bc93c4 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.cpp @@ -0,0 +1,22 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "SocialManagerPresenceTitleRecord_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +SocialManagerPresenceTitleRecord::SocialManagerPresenceTitleRecord( + _In_ xbox::services::social::manager::social_manager_presence_title_record cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.h new file mode 100644 index 00000000..82df1e11 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManagerPresenceTitleRecord_WinRT.h @@ -0,0 +1,50 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "PresenceDeviceType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public ref class SocialManagerPresenceTitleRecord sealed +{ +public: + /// + /// The title ID. + /// + DEFINE_PROP_GET_OBJ(IsTitleActive, is_title_active, bool); + + /// + /// The active state for the title. + /// + DEFINE_PROP_GET_OBJ(TitleId, title_id, uint32_t); + + /// + /// The formatted and localized presence string. + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(PresenceText, presence_text); + + /// + /// The active state for the title. + /// + DEFINE_PROP_GET_OBJ(IsBroadcasting, is_broadcasting, bool); + + DEFINE_PROP_GET_ENUM_OBJ(DeviceType, device_type, Microsoft::Xbox::Services::Presence::PresenceDeviceType); + +internal: + SocialManagerPresenceTitleRecord( + _In_ xbox::services::social::manager::social_manager_presence_title_record cppObj + ); + +private: + xbox::services::social::manager::social_manager_presence_title_record m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialManager_WinRT.cpp b/Source/Services/Social/Manager/WinRT/SocialManager_WinRT.cpp new file mode 100644 index 00000000..8322c6ed --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManager_WinRT.cpp @@ -0,0 +1,175 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialManager_WinRT.h" +#include "user_context.h" +#if UNIT_TEST_SERVICES +#include "MockSocialManager.h" +#endif + +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::social::manager; +using namespace xbox::services; +using namespace Windows::Foundation::Collections; +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +SocialManager^ +SocialManager::SingletonInstance::get() +{ + static SocialManager^ manager = ref new SocialManager(); + return manager; +} + +SocialManager::SocialManager() : +#if UNIT_TEST_SERVICES + m_cppObj(xbox::services::social::manager::MockSocialManager::get_mock_singleton_instance()), +#else + m_cppObj(xbox::services::social::manager::social_manager::get_singleton_instance()), +#endif + m_localUserChanged(false), + m_previousSize(0) +{ +} + +XboxSocialUserGroup^ +SocialManager::CreateSocialUserGroupFromFilters( + _In_ XboxLiveUser_t user, + _In_ PresenceFilter presenceFilter, + _In_ RelationshipFilter relationshipFilter + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + auto xboxSocialUserGroup = m_cppObj->create_social_user_group_from_filters( + user_context::user_convert(user), + static_cast(presenceFilter), + static_cast(relationshipFilter) + ); + + THROW_IF_ERR(xboxSocialUserGroup); + return ref new XboxSocialUserGroup(xboxSocialUserGroup.payload()); +} + +XboxSocialUserGroup^ +SocialManager::CreateSocialUserGroupFromList( + _In_ XboxLiveUser_t user, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIdList + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + auto viewResult = m_cppObj->create_social_user_group_from_list( + user_context::user_convert(user), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(xboxUserIdList) + ); + + THROW_IF_ERR(viewResult); + return ref new XboxSocialUserGroup(viewResult.payload()); +} + +void +SocialManager::DestroySocialUserGroup( + _In_ XboxSocialUserGroup^ xboxSocialUserGroup + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(xboxSocialUserGroup); + auto viewResult = m_cppObj->destroy_social_user_group( + xboxSocialUserGroup->GetCppObj() + ); + + THROW_IF_ERR(viewResult); +} + +void +SocialManager::AddLocalUser( + _In_ XboxLiveUser_t user, + _In_ SocialManagerExtraDetailLevel extraDetailLevel + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + auto userResult = m_cppObj->add_local_user( + user_context::user_convert(user), + static_cast(extraDetailLevel) + ); + + THROW_IF_ERR(userResult); + + m_localUserChanged = true; +} + +void SocialManager::RemoveLocalUser( + _In_ XboxLiveUser_t user + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(user); + auto userResult = m_cppObj->remove_local_user( + user_context::user_convert(user) + ); + + THROW_IF_ERR(userResult); + + m_localUserChanged = true; +} + +Windows::Foundation::Collections::IVectorView^ +SocialManager::DoWork() +{ + auto workResult = m_cppObj->do_work(); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(workResult)->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +SocialManager::LocalUsers::get() +{ + auto localUsers = m_cppObj->local_users(); + auto localUserSize = localUsers.size(); + if (m_localUserChanged || localUserSize != m_previousSize) + { + auto platformVec = ref new Platform::Collections::Vector(); + for (auto& localUser : localUsers) + { + auto newUser = xbox::services::user_context::user_convert(localUser); + platformVec->Append(newUser); + } + + m_localUserVector = platformVec->GetView(); + m_localUserChanged = false; + m_previousSize = localUserSize; + } + + return m_localUserVector; +} + +void SocialManager::UpdateSocialUserGroup( + _In_ XboxSocialUserGroup^ socialGroup, + _In_ Windows::Foundation::Collections::IVectorView^ users + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(socialGroup); + + auto result = m_cppObj->update_social_user_group( + socialGroup->GetCppObj(), + UtilsWinRT::CreateStdVectorStringFromPlatformVectorObj(users) + ); + + THROW_IF_ERR(result); +} + + +void SocialManager::LogState() +{ + m_cppObj->_Log_state(); +} + +std::shared_ptr +SocialManager::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialManager_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialManager_WinRT.h new file mode 100644 index 00000000..5625bc13 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialManager_WinRT.h @@ -0,0 +1,122 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "XboxSocialUserGroup_WinRT.h" +#if !TV_API +#include "User_WinRT.h" +#endif +#include "RelationshipFilter_WinRT.h" +#include "SocialManagerExtraDetailLevel_WinRT.h" +#include "PresenceFilter_WinRT.h" +#include "SocialEvent_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public ref class SocialManager sealed +{ +public: + /// + /// Gets the social_manager singleton instance + /// + static property SocialManager^ SingletonInstance + { + SocialManager^ get(); + } + + /// + /// Create a social graph for the specified local user + /// + /// Xbox Live User + /// A bitmask of extra detail to include in the xbox_social_user + void AddLocalUser( + _In_ XboxLiveUser_t user, + _In_ SocialManagerExtraDetailLevel extraDetailLevel + ); + + /// + /// Removes a social graph for the specified local user + /// + /// Xbox Live User + void RemoveLocalUser( + _In_ XboxLiveUser_t user + ); + + /// + /// Called whenever the title wants to update the social graph and get list of change events + /// Events that are returned will only be for the page that is is currently selected + /// Must be called every frame for data to be up to date + /// + /// The list of what has changed in between social graph updates + Windows::Foundation::Collections::IVectorView^ DoWork(); + + /// + /// Constructs a social social user group, which is a collection of users with social information + /// + /// Xbox Live User + /// The restriction of users based on their presence and title activity + /// The restriction of users based on their relationship to the calling user + /// The created view + XboxSocialUserGroup^ CreateSocialUserGroupFromFilters( + _In_ XboxLiveUser_t user, + _In_ PresenceFilter presenceFilter, + _In_ RelationshipFilter relationshipFilter + ); + + /// + /// Constructs a social social user group, which is a collection of users with social information + /// + /// Xbox Live User + /// List of users to populate the view with + /// The created view + XboxSocialUserGroup^ CreateSocialUserGroupFromList( + _In_ XboxLiveUser_t user, + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIdList + ); + + /// + /// Destroys a created social social user group + /// This will stop updating the social user group and remove tracking for any users the social user group holds + /// + /// The social social user group to destroy and stop tracking + void DestroySocialUserGroup(_In_ XboxSocialUserGroup^ xboxSocialUserGroup); + + /// + /// Returns all local users who have been added to the social manager + /// + property Windows::Foundation::Collections::IVectorView^ LocalUsers + { + Windows::Foundation::Collections::IVectorView^ get(); + }; + + /// + /// Updates specified social user group to new group of users + /// Does a diff to see which users have been added or removed from + /// + /// The xbox social user group to add users to + /// List of users to add to the xbox social user group + void UpdateSocialUserGroup( + _In_ XboxSocialUserGroup^ socialGroup, + _In_ Windows::Foundation::Collections::IVectorView^ users + ); + +internal: + SocialManager(); + std::shared_ptr GetCppObj() const; + void LogState(); + +private: + Windows::Foundation::Collections::IVectorView^ m_localUserVector; + size_t m_previousSize; + std::shared_ptr m_cppObj; + bool m_localUserChanged; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.cpp b/Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.cpp new file mode 100644 index 00000000..5732fb00 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialUserGroupLoadedEventArgs_WinRT.h" + +using namespace xbox::services::social::manager; +using namespace xbox::services; +using namespace Windows::Foundation::Collections; +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +SocialUserGroupLoadedEventArgs::SocialUserGroupLoadedEventArgs( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(std::move(cppObj)), + m_xboxSocialUserGroup( + ref new XboxSocialUserGroup(m_cppObj->social_user_group()) + ) +{ +} + +XboxSocialUserGroup^ SocialUserGroupLoadedEventArgs::SocialUserGroup::get() +{ + return m_xboxSocialUserGroup; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.h new file mode 100644 index 00000000..f059b2b3 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialUserGroupLoadedEventArgs_WinRT.h @@ -0,0 +1,38 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "XboxSocialUserGroup_WinRT.h" +#include "SocialEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public ref class SocialUserGroupLoadedEventArgs sealed : SocialEventArgs +{ +public: + /// + /// The loaded social user group + /// + property XboxSocialUserGroup^ SocialUserGroup + { + XboxSocialUserGroup^ get(); + }; + +internal: + SocialUserGroupLoadedEventArgs( + _In_ std::shared_ptr cppObj + ); + +private: + std::shared_ptr m_cppObj; + XboxSocialUserGroup^ m_xboxSocialUserGroup; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/SocialUserGroupType_WinRT.h b/Source/Services/Social/Manager/WinRT/SocialUserGroupType_WinRT.h new file mode 100644 index 00000000..c6540f1c --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/SocialUserGroupType_WinRT.h @@ -0,0 +1,24 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +public enum class SocialUserGroupType +{ + /// Social user group based off of filters + FilterType, + + /// Social user group based off of list of users + UserListType +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.cpp b/Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.cpp new file mode 100644 index 00000000..23a46846 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.cpp @@ -0,0 +1,22 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "TitleHistory_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +TitleHistory::TitleHistory( + _In_ xbox::services::social::manager::title_history cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.h b/Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.h new file mode 100644 index 00000000..816952b1 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/TitleHistory_WinRT.h @@ -0,0 +1,38 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// Data about whether the user has played the title +/// +public ref class TitleHistory sealed +{ +public: + /// + /// Whether the user has played this title + /// + DEFINE_PROP_GET_OBJ(HasUserPlayed, has_user_played, bool); + + /// + /// The last time the user had played + /// + DEFINE_PROP_GET_DATETIME_OBJ(LastTimeUserPlayed, last_time_user_played); + +internal: + TitleHistory(_In_ xbox::services::social::manager::title_history cppObj); + +private: + xbox::services::social::manager::title_history m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.cpp b/Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.cpp new file mode 100644 index 00000000..c8c20225 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.cpp @@ -0,0 +1,77 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "user_context.h" +#include "XboxSocialUserGroup_WinRT.h" +#include "Utils_WinRT.h" +#include "user_context.h" + +using namespace xbox::services::social::manager; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +XboxSocialUserGroup::XboxSocialUserGroup( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_user = xbox::services::user_context::user_convert(m_cppObj->local_user()); +} + +std::shared_ptr +XboxSocialUserGroup::GetCppObj() const +{ + return m_cppObj; +} + +Windows::Foundation::Collections::IVectorView^ +XboxSocialUserGroup::Users::get() +{ + auto currentPageResult = m_cppObj->users(); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(currentPageResult)->GetView(); +} + +XboxLiveUser_t +XboxSocialUserGroup::LocalUser::get() +{ + return m_user; +}; + +Windows::Foundation::Collections::IVectorView^ +XboxSocialUserGroup::UsersTrackedBySocialUserGroup::get() +{ + auto trackedUsers = m_cppObj->users_tracked_by_social_user_group(); + auto vector = ref new Platform::Collections::Vector(); + for (auto& user : trackedUsers) + { + vector->Append(ref new Platform::String(user.xbox_user_id())); + } + + return vector->GetView(); +}; + +Windows::Foundation::Collections::IVectorView^ +XboxSocialUserGroup::GetUsersFromXboxUserIds( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ) +{ + std::vector xboxUserIdContainerVec; + xboxUserIdContainerVec.reserve(xboxUserIds->Size); + for (auto str : xboxUserIds) + { + xboxUserIdContainerVec.push_back(str->Data()); + } + + auto users = m_cppObj->get_users_from_xbox_user_ids(xboxUserIdContainerVec); + return UtilsWinRT::CreatePlatformVectorFromStdVectorObj(users)->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.h b/Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.h new file mode 100644 index 00000000..f86825ba --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/XboxSocialUserGroup_WinRT.h @@ -0,0 +1,86 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "XboxSocialUser_WinRT.h" +#include "SocialUserGroupType_WinRT.h" +#include "PresenceFilter_WinRT.h" +#include "RelationshipFilter_WinRT.h" +#include "user_context.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// A subset snapshot of the users social graph +/// +public ref class XboxSocialUserGroup sealed +{ +public: + /// + /// Gets an up to date list of users from the social graph + /// + ///Returns a list of users + property Windows::Foundation::Collections::IVectorView^ Users + { + Windows::Foundation::Collections::IVectorView^ get(); + }; + + /// + /// The type of social user group + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(SocialUserGroupType, social_user_group_type, Microsoft::Xbox::Services::Social::Manager::SocialUserGroupType) + + /// + /// Users who are contained in this user group currently + /// For list this is static, for filter this is dynamic and will change on do_work + /// + property Windows::Foundation::Collections::IVectorView^ UsersTrackedBySocialUserGroup + { + Windows::Foundation::Collections::IVectorView^ get(); + }; + + /// + /// The local user who the user group is related to + /// + property XboxLiveUser_t LocalUser + { + XboxLiveUser_t get(); + }; + + /// + /// Returns the presence filter used if group type is filter type + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(PresenceFilterOfGroup, presence_filter_of_group, PresenceFilter); + + /// + /// Returns the relationship filter used if group type is filter type + /// + DEFINE_PTR_PROP_GET_ENUM_OBJ(RelationshipFilterOfGroup, relationship_filter_of_group, RelationshipFilter); + + /// + /// Returns users from xuids + /// + _XSAPIIMP Windows::Foundation::Collections::IVectorView^ GetUsersFromXboxUserIds( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ); + +internal: + XboxSocialUserGroup( + _In_ std::shared_ptr cppObj + ); + + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + XboxLiveUser_t m_user; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.cpp b/Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.cpp new file mode 100644 index 00000000..58e3cab5 --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.cpp @@ -0,0 +1,48 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "XboxSocialUser_WinRT.h" +#include "TitleHistory_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +XboxSocialUser::XboxSocialUser( + _In_ xbox::services::social::manager::xbox_social_user* cppObj + ) +{ + if (cppObj != nullptr) + { + m_cppObj = *cppObj; + m_presenceRecord = ref new SocialManagerPresenceRecord(m_cppObj.presence_record()); + m_titleHistory = ref new Microsoft::Xbox::Services::Social::Manager::TitleHistory(m_cppObj.title_history()); + m_preferredColor = ref new Microsoft::Xbox::Services::Social::Manager::PreferredColor(m_cppObj.preferred_color()); + } +} + +Microsoft::Xbox::Services::Social::Manager::SocialManagerPresenceRecord^ +XboxSocialUser::PresenceRecord::get() +{ + return m_presenceRecord; +} + +Microsoft::Xbox::Services::Social::Manager::TitleHistory^ +XboxSocialUser::TitleHistory::get() +{ + return m_titleHistory; +} + +Microsoft::Xbox::Services::Social::Manager::PreferredColor^ +XboxSocialUser::PreferredColor::get() +{ + return m_preferredColor; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.h b/Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.h new file mode 100644 index 00000000..1c76aebe --- /dev/null +++ b/Source/Services/Social/Manager/WinRT/XboxSocialUser_WinRT.h @@ -0,0 +1,101 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "SocialManagerPresenceRecord_WinRT.h" +#include "TitleHistory_WinRT.h" +#include "PreferredColor_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// Represents a xbox social user containing social information +/// +public ref class XboxSocialUser sealed +{ +public: + /// + /// The Xbox user id + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(XboxUserId, xbox_user_id); + + /// + /// Whether they are a favorite + /// + DEFINE_PROP_GET_OBJ(IsFavorite, is_favorite, bool); + + /// + /// Whether the calling user is following them + /// + DEFINE_PROP_GET_OBJ(IsFollowingUser, is_following_user, bool); + + /// + /// Whether they calling user is followed by this person + /// + DEFINE_PROP_GET_OBJ(IsFollowedByCaller, is_followed_by_caller, bool); + + /// + /// The display name + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(DisplayName, display_name); + + /// + /// The real name + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(RealName, real_name); + + /// + /// The display picture uri + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(DisplayPicUrlRaw, display_pic_url_raw); + + /// + /// Whether to use the players avatar + /// + DEFINE_PROP_GET_OBJ(UseAvatar, use_avatar, bool); + + /// + /// The player's gamertag + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(Gamertag, gamertag); + + /// + /// The player's gamerscore + /// + DEFINE_PROP_GET_STR_OBJ_FROM_WCHAR_PTR(Gamerscore, gamerscore); + + /// + /// The user's presence record + /// + property Microsoft::Xbox::Services::Social::Manager::SocialManagerPresenceRecord^ PresenceRecord { Microsoft::Xbox::Services::Social::Manager::SocialManagerPresenceRecord^ get(); } + + /// + /// Title history for the user + /// + property Microsoft::Xbox::Services::Social::Manager::TitleHistory^ TitleHistory { Microsoft::Xbox::Services::Social::Manager::TitleHistory^ get(); } + + /// + /// Preferred color for the user + /// + property Microsoft::Xbox::Services::Social::Manager::PreferredColor^ PreferredColor { Microsoft::Xbox::Services::Social::Manager::PreferredColor^ get(); } + +internal: + XboxSocialUser( + _In_ xbox::services::social::manager::xbox_social_user* cppObj + ); + +private: + Microsoft::Xbox::Services::Social::Manager::SocialManagerPresenceRecord^ m_presenceRecord; + Microsoft::Xbox::Services::Social::Manager::PreferredColor^ m_preferredColor; + Microsoft::Xbox::Services::Social::Manager::TitleHistory^ m_titleHistory; + xbox::services::social::manager::xbox_social_user m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/internal_social_event.cpp b/Source/Services/Social/Manager/internal_social_event.cpp new file mode 100644 index 00000000..1118dc35 --- /dev/null +++ b/Source/Services/Social/Manager/internal_social_event.cpp @@ -0,0 +1,185 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "social_manager_internal.h" +#include "xsapi/presence.h" + +using namespace xbox::services::presence; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(xbox_social_user) usersAffected + ) : + m_socialEventType(eventType), + m_usersAffected(std::move(usersAffected)) +{ + for (auto& user : m_usersAffected) + { + m_usersAffectedAsStringVec.push_back(user.xbox_user_id()); + } +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(social_manager_presence_record) presenceRecords + ) : + m_socialEventType(eventType), + m_presenceRecords(std::move(presenceRecords)) +{ + for (auto& record : m_presenceRecords) + { + stringstream_t str; + str << record._Xbox_user_id(); + auto strStr = str.str(); + xsapi_internal_string xuid(strStr.c_str()); + m_usersAffectedAsStringVec.push_back(xuid); + } +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ device_presence_change_event_args devicePresenceArgs + ) : + m_socialEventType(eventType), + m_devicePresenceArgs(std::move(devicePresenceArgs)) +{ + xsapi_internal_string xuidStr(m_devicePresenceArgs.xbox_user_id().c_str()); + m_usersAffectedAsStringVec.push_back(xuidStr); +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xbox::services::presence::title_presence_change_event_args titlePresenceArgs + ) : + m_socialEventType(eventType), + m_titlePresenceArgs(std::move(titlePresenceArgs)) +{ + m_usersAffectedAsStringVec.push_back(m_titlePresenceArgs.xbox_user_id().c_str()); +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(uint64_t) userList + ) : + m_socialEventType(eventType), + m_userList(std::move(userList)) +{ + for (auto& user : m_userList) + { + stringstream_t str; + str << user; + auto strStr = str.str(); + xsapi_internal_string xuid(strStr.c_str()); + m_usersAffectedAsStringVec.push_back(xuid); + } +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(xsapi_internal_string) userAddList, + _In_ pplx::task_completion_event> tce + ) : + m_socialEventType(eventType), + m_usersAffectedAsStringVec(std::move(userAddList)), + m_tce(std::move(tce)) +{ +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type socialEventType, + _In_ xbox_live_result errorInfo, + _In_ xsapi_internal_vector(xsapi_internal_string) userList + ) : + m_socialEventType(socialEventType), + m_error(std::move(errorInfo)), + m_usersAffectedAsStringVec(std::move(userList)) +{ +} + +internal_social_event::internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(xsapi_internal_string) userAddList + ) : + m_socialEventType(eventType), + m_usersAffectedAsStringVec(std::move(userAddList)) +{ +} + +internal_social_event_type +internal_social_event::event_type() const +{ + return m_socialEventType; +} + +const xsapi_internal_vector(xbox_social_user)& +internal_social_event::users_affected() const +{ + return m_usersAffected; +} + +const xsapi_internal_vector(uint64_t)& +internal_social_event::users_to_remove() const +{ + return m_userList; +} + +const xsapi_internal_vector(social_manager_presence_record)& +internal_social_event::presence_records() const +{ + return m_presenceRecords; +} + +const device_presence_change_event_args& +internal_social_event::device_presence_args() const +{ + return m_devicePresenceArgs; +} + +const title_presence_change_event_args& +internal_social_event::title_presence_args() const +{ + return m_titlePresenceArgs; +} + +const xsapi_internal_vector(xsapi_internal_string)& +internal_social_event::users_affected_as_string_vec() const +{ + return m_usersAffectedAsStringVec; +} + +const pplx::task_completion_event>& +internal_social_event::tce() const +{ + return m_tce; +} + +const xbox_live_result& +internal_social_event::error() const +{ + return m_error; +} + +const fire_timer_completion_context& +internal_social_event::completion_context() const +{ + return m_completionContext; +} + +void +internal_social_event::set_completion_context( + _In_ const fire_timer_completion_context& compleitionContext + ) +{ + m_completionContext = compleitionContext; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/peoplehub_service.cpp b/Source/Services/Social/Manager/peoplehub_service.cpp new file mode 100644 index 00000000..78edf1c2 --- /dev/null +++ b/Source/Services/Social/Manager/peoplehub_service.cpp @@ -0,0 +1,201 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "social_manager_internal.h" +#include "http_call_impl.h" +#include "xbox_system_factory.h" + +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +peoplehub_service::peoplehub_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr httpCallSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_httpCallSettings(std::move(httpCallSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task>> +peoplehub_service::get_social_graph( + _In_ const string_t& callerXboxUserId, + _In_ social_manager_extra_detail_level decorations + ) +{ + return get_social_graph( + callerXboxUserId, + decorations, + _T("social"), + std::vector(), + false + ); +} + +pplx::task>> +peoplehub_service::get_social_graph( + _In_ const string_t& callerXboxUserId, + _In_ social_manager_extra_detail_level decorations, + _In_ const std::vector xboxLiveUsers + ) +{ + return get_social_graph( + callerXboxUserId, + decorations, + _T(""), + xboxLiveUsers, + true + ); +} + +pplx::task>> +peoplehub_service::get_social_graph( + _In_ const string_t& callerXboxUserId, + _In_ social_manager_extra_detail_level decorations, + _In_ const string_t& relationshipType, + _In_ const std::vector xboxLiveUsers, + _In_ bool isBatch + ) +{ + string_t pathAndQuery = social_graph_subpath( + callerXboxUserId, + decorations, + relationshipType, + xboxLiveUsers, + isBatch + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_httpCallSettings, + isBatch ? _T("POST") : _T("GET"), + utils::create_xboxlive_endpoint(_T("peoplehub"), m_appConfig), + pathAndQuery, + xbox_live_api::get_social_graph + ); + + if (isBatch) + { + web::json::value postJSON; + web::json::value xuidJSON = web::json::value::array(); + for (uint32_t i = 0; i < xboxLiveUsers.size(); ++i) + { + xuidJSON[i] = web::json::value::string(xboxLiveUsers[i]); + } + + postJSON[_T("xuids")] = xuidJSON; + httpCall->set_request_body(postJSON); + } + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc; + web::json::value peopleArray = utils::extract_json_field( + response->response_body_json(), + _T("people"), + errc, + false + ); + + if (errc) + { + return xbox_live_result>( + response->err_code(), + response->err_message() + ); + } + + std::vector socialUserVec = utils::extract_json_vector( + xbox_social_user::_Deserialize, + peopleArray, + errc, + false + ); + + std::vector socialUser; + socialUser.reserve(socialUserVec.size()); + for (auto& user : socialUserVec) + { + socialUser.push_back(user); + } + + auto socialUserResult = xbox_live_result>(socialUser, errc); + + return utils::generate_xbox_live_result>( + socialUserResult, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +string_t peoplehub_service::social_graph_subpath( + _In_ const string_t& xboxUserId, + _In_ social_manager_extra_detail_level decorations, + _In_ const string_t& relationshipType, + _In_ const std::vector xboxLiveUsers, + _In_ bool isBatch + ) const +{ + stringstream_t source; + source << _T("/users/xuid("); + source << xboxUserId; + source << _T(")/people"); + if (!relationshipType.empty()) + { + source << _T("/") << relationshipType; + } + + if (isBatch) + { + source << _T("/batch"); + } + + if ((decorations | social_manager_extra_detail_level::no_extra_detail) != social_manager_extra_detail_level::no_extra_detail) + { + source << _T("/decoration/"); + std::vector decorationList; + if ((decorations & social_manager_extra_detail_level::title_history_level) == social_manager_extra_detail_level::title_history_level) + { + stringstream_t titleStream; + titleStream << _T("titlehistory("); + titleStream << m_appConfig->title_id(); + titleStream << _T(")"); + string_t decorationString = titleStream.str(); + decorationList.push_back(decorationString); + } + if ((decorations & social_manager_extra_detail_level::preferred_color_level) == social_manager_extra_detail_level::preferred_color_level) + { + decorationList.push_back(_T("preferredcolor")); + } + + decorationList.push_back(_T("presenceDetail")); + uint32_t i = 0; + for (const auto& str : decorationList) + { + if (i != 0) + { + source << _T(","); + } + source << str; + ++i; + } + } + + return source.str(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/preferred_color.cpp b/Source/Services/Social/Manager/preferred_color.cpp new file mode 100644 index 00000000..72d2d8c3 --- /dev/null +++ b/Source/Services/Social/Manager/preferred_color.cpp @@ -0,0 +1,76 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" + +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +preferred_color::preferred_color() +{ + initialize_char_arr(m_primaryColor); + initialize_char_arr(m_secondaryColor); + initialize_char_arr(m_tertiaryColor); +} + +const char_t* +preferred_color::primary_color() const +{ + return m_primaryColor; +} + +const char_t* +preferred_color::secondary_color() const +{ + return m_secondaryColor; +} + +const char_t* +preferred_color::tertiary_color() const +{ + return m_tertiaryColor; +} + +bool +preferred_color::operator!=(const preferred_color& rhs) const +{ + return ( + utils::str_icmp(m_primaryColor, rhs.m_primaryColor) != 0 || + utils::str_icmp(m_secondaryColor, rhs.m_secondaryColor) != 0 || + utils::str_icmp(m_tertiaryColor, rhs.m_tertiaryColor) != 0 + ); +} + +xbox_live_result +preferred_color::_Deserialize( + _In_ const web::json::value& json, + _In_ std::error_code& errcOut + ) +{ + preferred_color returnObject; + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + utils::extract_json_string_to_char_t_array(json, _T("primaryColor"), errc, returnObject.m_primaryColor, ARRAYSIZE(returnObject.m_primaryColor)); + utils::extract_json_string_to_char_t_array(json, _T("secondaryColor"), errc, returnObject.m_secondaryColor, ARRAYSIZE(returnObject.m_secondaryColor)); + utils::extract_json_string_to_char_t_array(json, _T("tertiaryColor"), errc, returnObject.m_tertiaryColor, ARRAYSIZE(returnObject.m_tertiaryColor)); + + if (errcOut) + { + errcOut = errc; + } + return xbox_live_result( + returnObject, + errc + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/social_event.cpp b/Source/Services/Social/Manager/social_event.cpp new file mode 100644 index 00000000..d1d0182b --- /dev/null +++ b/Source/Services/Social/Manager/social_event.cpp @@ -0,0 +1,76 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" +#include "user_context.h" + +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +social_event::social_event() : + m_eventType(social_event_type::unknown) +{ +} + +social_event::social_event( + _In_ xbox_live_user_t user, + _In_ social_event_type eventType, + _In_ std::vector usersAffected, + _In_ std::shared_ptr socialEventArgs, + _In_ std::error_code errCode, + _In_ std::string errMessage + ) : + m_user(std::move(user)), + m_eventType(eventType), + m_usersAffected(std::move(usersAffected)), + m_eventArgs(std::move(socialEventArgs)), + m_errCode(std::move(errCode)), + m_errMessage(std::move(errMessage)) +{ +} + +xbox_live_user_t +social_event::user() const +{ + return m_user; +} + +social_event_type +social_event::event_type() const +{ + return m_eventType; +} + +const std::vector& +social_event::users_affected() const +{ + return m_usersAffected; +} + +const std::error_code& +social_event::err() const +{ + return m_errCode; +} + +const std::string& +social_event::err_message() const +{ + return m_errMessage; +} + +const std::shared_ptr& +social_event::event_args() const +{ + return m_eventArgs; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/social_graph.cpp b/Source/Services/Social/Manager/social_graph.cpp new file mode 100644 index 00000000..ea5096c4 --- /dev/null +++ b/Source/Services/Social/Manager/social_graph.cpp @@ -0,0 +1,1803 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "social_manager_internal.h" +#include "xsapi/services.h" +#include "xsapi/system.h" +#include "xsapi/presence.h" +#include "xbox_live_context_impl.h" +#include "system_internal.h" +#if !XSAPI_U +#include "ppltasks_extra.h" +#endif +#include "xbox_system_factory.h" + +using namespace xbox::services; +using namespace xbox::services::system; +using namespace xbox::services::presence; +using namespace xbox::services::social; +using namespace xbox::services::real_time_activity; +using namespace Concurrency::extras; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +const std::chrono::milliseconds rta_trigger_timer::TIME_PER_CALL_MS = +#if UNIT_TEST_SERVICES +std::chrono::milliseconds(0); +#else +std::chrono::milliseconds(30 * 1000); +#endif + +const std::chrono::minutes social_graph::REFRESH_TIME_MIN = std::chrono::minutes(20); +const uint32_t social_graph::NUM_EVENTS_PER_FRAME = 5; + +social_graph::social_graph( + _In_ xbox_live_user_t user, + _In_ social_manager_extra_detail_level socialManagerExtraDetailLevel, + _In_ std::function graphDestructionCompleteCallback + ) : + m_detailLevel(socialManagerExtraDetailLevel), + m_xboxLiveContextImpl(new xbox_live_context_impl(m_user)), + m_user(std::move(user)), + m_graphDestructionCompleteCallback(std::move(graphDestructionCompleteCallback)), + m_isInitialized(false), + m_socialGraphState(social_graph_state::normal), + m_stateRTAFunction(nullptr), + m_perfTester(_T("social_graph")), + m_wasDisconnected(false), + m_numEventsThisFrame(0), + m_userAddedContext(0) +{ + m_xboxLiveContextImpl->user_context()->set_caller_context_type(caller_context_type::social_manager); + m_xboxLiveContextImpl->init(); + m_peoplehubService = peoplehub_service( + m_xboxLiveContextImpl->user_context(), + m_xboxLiveContextImpl->settings(), + m_xboxLiveContextImpl->application_config() + ); + + LOG_DEBUG("social_graph created"); +} + +social_graph::~social_graph() +{ + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("~social_graph")); + m_xboxLiveContextImpl->real_time_activity_service()->deactivate(); + try + { + if (m_graphDestructionCompleteCallback != nullptr) + { + m_graphDestructionCompleteCallback(); + } + } + catch (...) + { + LOG_ERROR("Exception happened during graph destruction complete callback"); + } + + LOG_DEBUG("social_graph destroyed"); + + + m_perfTester.stop_timer(_T("~social_graph")); +} + +pplx::task> +social_graph::initialize() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + setup_rta(); + + m_presenceRefreshTimer = std::make_shared( + [thisWeakPtr](std::vector eventArgs, const fire_timer_completion_context&) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->presence_timer_callback( + eventArgs + ); + } + }); + + m_socialGraphRefreshTimer = std::make_shared( + [thisWeakPtr](std::vector eventArgs, const fire_timer_completion_context& completionContext) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->social_graph_timer_callback( + eventArgs, + completionContext + ); + } + }); + + m_resyncRefreshTimer = std::make_shared( + [thisWeakPtr](std::vector eventArgs, const fire_timer_completion_context&) + { + UNREFERENCED_PARAMETER(eventArgs); + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->refresh_graph(); + } + }); + + create_delayed_task( + REFRESH_TIME_MIN, + [thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->social_graph_refresh_callback(); + } + }); + + pplx::create_task([thisWeakPtr]() + { + try + { + while (true) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->do_event_work(); + } + else + { + LOG_DEBUG("exiting event processing loop"); + return; + } + } + } + catch (const std::exception& e) + { + LOGS_DEBUG << "Exception in event processing " << e.what(); + } + catch (...) + { + LOG_DEBUG("Unknown std::exception in event processing"); + } + }); + + return m_peoplehubService.get_social_graph( +#if TV_API || UNIT_TEST_SERVICES || !XSAPI_CPP + m_xboxLiveContextImpl->user()->XboxUserId->Data(), +#else + m_xboxLiveContextImpl->user()->xbox_user_id(), +#endif + m_detailLevel + ).then([thisWeakPtr](xbox_live_result> socialUsersResult) + { + try + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + if (socialUsersResult.err()) + { + return xbox_live_result(socialUsersResult.err(), socialUsersResult.err_message()); + } + + pThis->initialize_social_buffers(socialUsersResult.payload()); + auto& inactiveBufferSocialGraph = pThis->m_userBuffer.inactive_buffer()->socialUserGraph; + for (auto& user : inactiveBufferSocialGraph) + { + auto devicePresenceSubResult = pThis->m_xboxLiveContextImpl->presence_service().subscribe_to_device_presence_change(user.second.socialUser->xbox_user_id()); + auto titlePresenceSubResult = pThis->m_xboxLiveContextImpl->presence_service().subscribe_to_title_presence_change( + user.second.socialUser->xbox_user_id(), + pThis->m_xboxLiveContextImpl->application_config()->title_id() + ); + + if (devicePresenceSubResult.err() || titlePresenceSubResult.err()) + { + return xbox_live_result(xbox_live_error_code::runtime_error, "subscription initialization failed"); + } + + std::lock_guard lock(pThis->m_socialGraphMutex); + std::lock_guard priorityLock(pThis->m_socialGraphPriorityMutex); + pThis->m_perfTester.start_timer(_T("sub")); + pThis->m_socialUserSubscriptions[user.first].devicePresenceChangeSubscription = devicePresenceSubResult.payload(); + pThis->m_socialUserSubscriptions[user.first].titlePresenceChangeSubscription = titlePresenceSubResult.payload(); + pThis->m_perfTester.stop_timer(_T("sub")); + } + + + std::lock_guard lock(pThis->m_socialGraphMutex); + std::lock_guard priorityLock(pThis->m_socialGraphPriorityMutex); + pThis->m_perfTester.start_timer(_T("m_isInitialized")); + pThis->m_isInitialized = true; + pThis->m_perfTester.stop_timer(_T("m_isInitialized")); + } + else + { + return xbox_live_result(xbox_live_error_code::runtime_error); + } + } + catch (const std::exception& e) + { + LOGS_DEBUG << "Exception in get_social_graph " << e.what(); + } + catch (...) + { + LOG_DEBUG("Unknown std::exception in initialization"); + } + return xbox_live_result(); + }); +} + +const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)* +social_graph::active_buffer_social_graph() +{ + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + return &m_userBuffer.active_buffer()->socialUserGraph; +} + +void +social_graph::do_event_work() +{ + static const std::chrono::milliseconds sleepTime(30); + bool hasRemainingEvent = false; + bool hasCachedEvents = false; + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + set_state(social_graph_state::event_processing); + + m_perfTester.start_timer(_T("do_event_work: event_processing")); + m_perfTester.start_timer(_T("do_event_work: has_cached_events")); + hasCachedEvents = m_isInitialized && m_userBuffer.inactive_buffer() && !m_userBuffer.inactive_buffer()->socialUserEventQueue.empty(true); + m_perfTester.stop_timer(_T("do_event_work: has_cached_events")); + if (hasCachedEvents) + { + m_perfTester.start_timer(_T("do_event_work: set_state")); + LOG_INFO("set state: event_processing"); + m_perfTester.stop_timer(_T("do_event_work: set_state")); + } + m_perfTester.stop_timer(_T("do_event_work: event_processing")); + } + if (hasCachedEvents) + { + process_cached_events(); + hasRemainingEvent = true; + } + else if(m_isInitialized) + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("do_event_work: process_events")); + set_state(social_graph_state::normal); + hasRemainingEvent = process_events(); //effectively a coroutine here so that each event yields when it is done processing + m_perfTester.stop_timer(_T("do_event_work: process_events")); + } + else + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + + m_perfTester.start_timer(_T("set_state: normal")); + set_state(social_graph_state::normal); + m_perfTester.stop_timer(_T("set_state: normal")); + } + + if (!hasRemainingEvent) + { + std::this_thread::sleep_for(sleepTime); + } +} + +void social_graph::initialize_social_buffers( + _In_ const std::vector& socialUsers + ) +{ + m_userBuffer.initialize(socialUsers); +} + +bool +social_graph::is_initialized() +{ + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + return m_isInitialized; +} + +void +social_graph::process_cached_events() +{ + if (m_userBuffer.inactive_buffer() != nullptr) + { + auto inactiveBuffer = m_userBuffer.inactive_buffer(); + auto& eventQueue = inactiveBuffer->socialUserEventQueue; + while (!eventQueue.empty()) + { + auto evt = eventQueue.pop(); + apply_event(evt, false); + } + + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + set_state(social_graph_state::normal); + } +} + +bool +social_graph::process_events() +{ + bool shouldApplyEvent = !m_internalEventQueue.empty() && m_numEventsThisFrame < NUM_EVENTS_PER_FRAME; + if(shouldApplyEvent) + { + ++m_numEventsThisFrame; + auto evt = m_internalEventQueue.pop(); + apply_event(evt, true); + m_userBuffer.add_event(evt); + } + + return shouldApplyEvent; +} + +void +social_graph::apply_event( + _In_ const internal_social_event& evt, + _In_ bool isFreshEvent + ) +{ + const auto& inactiveBuffer = m_userBuffer.inactive_buffer(); + social_event_type eventType = social_event_type::unknown; + switch (evt.event_type()) + { + case internal_social_event_type::users_added: + { + LOG_INFO("Appling internal events: users_added"); + apply_users_added_event(evt, inactiveBuffer, isFreshEvent); + break; + } + case internal_social_event_type::users_changed: + { + LOG_INFO("Appling internal events: users_changed"); + apply_users_change_event(evt, inactiveBuffer, isFreshEvent); + break; + } + case internal_social_event_type::users_removed: + { + LOG_INFO("Appling internal events: users_removed"); + apply_users_removed_event(evt, inactiveBuffer, eventType, isFreshEvent); + break; + } + case internal_social_event_type::device_presence_changed: + { + LOG_INFO("Appling internal events: device_presence_changed"); + + apply_device_presence_changed_event(evt, inactiveBuffer, isFreshEvent, eventType); + break; + } + case internal_social_event_type::title_presence_changed: + { + LOG_INFO("Appling internal events: title_presence_changed"); + auto& titlePresenceChanged = evt.title_presence_args(); + auto xuid = utils::string_t_to_uint64(titlePresenceChanged.xbox_user_id()); + auto xuidIter = inactiveBuffer->socialUserGraph.find(xuid); + if (xuidIter == inactiveBuffer->socialUserGraph.end() || (xuidIter != inactiveBuffer->socialUserGraph.end() && xuidIter->second.socialUser == nullptr)) + { + LOG_ERROR("social graph: social user not found in title presence change"); + break; + } + auto& userPresenceRecord = inactiveBuffer->socialUserGraph.at(xuid).socialUser->m_presenceRecord; + if (titlePresenceChanged.title_state() == xbox::services::presence::title_presence_state::ended) + { + userPresenceRecord._Remove_title( + titlePresenceChanged.title_id() + ); + } + + eventType = social_event_type::presence_changed; + break; + } + case internal_social_event_type::presence_changed: + { + LOG_INFO("Appling internal events: presence_changed"); + apply_presence_changed_event(evt, inactiveBuffer, isFreshEvent); + break; + } + case internal_social_event_type::social_relationships_changed: + case internal_social_event_type::profiles_changed: + { + LOG_INFO("Appling internal events: social_relationships_changed or profiles_changed"); + m_perfTester.start_timer(_T("profiles_changed")); + for (auto& user : evt.users_affected()) + { + *inactiveBuffer->socialUserGraph[user._Xbox_user_id_as_integer()].socialUser = user; + } + + eventType = social_event_type::profiles_changed; + m_perfTester.stop_timer(_T("profiles_changed")); + break; + } + case internal_social_event_type::unknown: + default: + { + LOG_ERROR("unknown event in process_events"); + } + } + + if (isFreshEvent) + { + m_socialEventQueue.push(evt, m_user, eventType); + } +} + +void social_graph::apply_users_added_event( + _In_ const internal_social_event& evt, + _In_ user_buffer* inactiveBuffer, + _In_ bool isFreshEvent + ) +{ + m_perfTester.start_timer(_T("apply_users_added_event")); + std::vector usersToAdd; + for (auto& user : evt.users_affected_as_string_vec()) + { + string_t addUser(user.c_str()); + auto userIter = inactiveBuffer->socialUserGraph.find(utils::string_t_to_uint64(addUser)); + if (userIter != inactiveBuffer->socialUserGraph.end()) + { + ++userIter->second.refCount; + } + else + { + usersToAdd.push_back(addUser); + } + } + + if (usersToAdd.empty()) + { + evt.tce().set(xbox_live_result()); + } + else + { + fire_timer_completion_context usersAddedStruct; + + usersAddedStruct.isNull = false; + usersAddedStruct.context = ++m_userAddedContext; + usersAddedStruct.numObjects = usersToAdd.size(); + usersAddedStruct.tce = std::move(evt.tce()); + + if (isFreshEvent) + { + m_socialGraphRefreshTimer->fire(usersToAdd, usersAddedStruct); + } + + for (auto& user : usersToAdd) + { + auto userAsInt = utils::string_t_to_uint64(user); + inactiveBuffer->socialUserGraph[userAsInt].socialUser = nullptr; + inactiveBuffer->socialUserGraph[userAsInt].refCount = 1; + } + } + m_perfTester.stop_timer(_T("apply_users_added_event")); +} + +void +social_graph::apply_users_removed_event( + _In_ const internal_social_event& evt, + _In_ user_buffer* inactiveBuffer, + _Inout_ social_event_type& eventType, + _In_ bool isFreshEvent + ) +{ + m_perfTester.start_timer(_T("removing_users")); + auto usersAffected = evt.users_to_remove(); + std::vector removeUsers; + for (auto& user : usersAffected) + { + --inactiveBuffer->socialUserGraph[user].refCount; + if (inactiveBuffer->socialUserGraph[user].refCount == 0) + { + if (inactiveBuffer->socialUserGraph[user].socialUser != nullptr) + { + removeUsers.push_back(user); + } + else + { + inactiveBuffer->socialUserGraph.erase(user); + } + + eventType = social_event_type::users_removed_from_social_graph; + } + } + + m_userBuffer.remove_users_from_buffer(removeUsers, *inactiveBuffer); + if (isFreshEvent) + { + unsubscribe_users(removeUsers); + } + m_perfTester.stop_timer(_T("removing_users")); +} + +void +social_graph::apply_users_change_event( + _In_ const internal_social_event& evt, + _In_ user_buffer* inactiveBuffer, + _In_ bool isFreshEvent + ) +{ + m_perfTester.start_timer(_T("apply_users_change_event")); + std::vector usersToAdd; + std::vector usersChanged; + if (!evt.completion_context().isNull) + { + evt.completion_context().tce.set(evt.error()); + } + + auto result = evt.error(); + if (result.err() != xbox_live_error_code::no_error) + { + m_socialEventQueue.push(evt, m_user, social_event_type::users_added_to_social_graph, evt.error()); + return; + } + + for (auto user : evt.users_affected()) + { + auto userIter = inactiveBuffer->socialUserGraph.find(user._Xbox_user_id_as_integer()); + if (userIter != inactiveBuffer->socialUserGraph.end()) // if not found then it was deleted while the lookup was happening + { + if (userIter->second.socialUser == nullptr) + { + usersToAdd.push_back(user); + } + else + { + *userIter->second.socialUser = user; + usersChanged.push_back(user); + } + } + } + + if (!usersToAdd.empty()) + { + m_userBuffer.add_users_to_buffer(usersToAdd, *inactiveBuffer, evt.completion_context().numObjects); + + std::vector usersList; + for (auto& user : usersToAdd) + { + usersList.push_back(user._Xbox_user_id_as_integer()); + } + if (isFreshEvent) + { + setup_device_and_presence_subscriptions(usersList); + internal_social_event internalSocialUsersAddedEvent(internal_social_event_type::users_added, utils::std_vector_to_xsapi_vector(usersToAdd)); + m_socialEventQueue.push(internalSocialUsersAddedEvent, m_user, social_event_type::users_added_to_social_graph); + } + } + + if (!usersChanged.empty() && isFreshEvent) + { + internal_social_event internalSocialProfileChangedEvent(internal_social_event_type::profiles_changed, utils::std_vector_to_xsapi_vector(usersChanged)); + m_socialEventQueue.push(internalSocialProfileChangedEvent, m_user, social_event_type::profiles_changed); + } + + m_perfTester.stop_timer(_T("apply_users_change_event")); +} + +void social_graph::apply_device_presence_changed_event( + _In_ const internal_social_event& evt, + _In_ user_buffer* inactiveBuffer, + _In_ bool isFreshEvent, + _Inout_ social_event_type& eventType + ) +{ + m_perfTester.start_timer(_T("apply_device_presence_changed_event")); + auto& devicePresenceChangedArgs = evt.device_presence_args(); + auto xuid = utils::string_t_to_uint64(devicePresenceChangedArgs.xbox_user_id()); + + bool fireCallbackTimer = false; + auto mapIter = m_userBuffer.inactive_buffer()->socialUserGraph.find(xuid); + if (mapIter != m_userBuffer.inactive_buffer()->socialUserGraph.end()) + { + if (mapIter->second.socialUser == nullptr) + { + LOG_ERROR("social graph: social user null in apply_device_presence_changed_event"); + return; + } + auto& userPresenceRecord = mapIter->second.socialUser->presence_record(); + auto deviceRecordSize = userPresenceRecord.presence_title_records().size(); + fireCallbackTimer = deviceRecordSize > 1 || devicePresenceChangedArgs.is_user_logged_on_device(); + } + else + { + LOG_ERROR("device presence record recieved for user not in graph"); + return; + } + + if (fireCallbackTimer && isFreshEvent) + { + std::vector entryVec(1); + entryVec[0] = devicePresenceChangedArgs.xbox_user_id(); + m_presenceRefreshTimer->fire(entryVec); + } + else if (!fireCallbackTimer) + { + auto xuidIter = inactiveBuffer->socialUserGraph.find(xuid); + if (xuidIter == inactiveBuffer->socialUserGraph.end() || (xuidIter != inactiveBuffer->socialUserGraph.end() && xuidIter->second.socialUser == nullptr)) + { + LOG_ERROR("social graph: social user null in inactiveBuffer"); + return; + } + auto& userPresenceRecord = xuidIter->second.socialUser->m_presenceRecord; + userPresenceRecord._Update_device( + devicePresenceChangedArgs.device_type(), + devicePresenceChangedArgs.is_user_logged_on_device() + ); + + eventType = social_event_type::presence_changed; + } + m_perfTester.stop_timer(_T("apply_device_presence_changed_event")); +} + +void social_graph::apply_presence_changed_event( + _In_ const internal_social_event& evt, + _In_ user_buffer* inactiveBuffer, + _In_ bool isFreshEvent + ) +{ + m_perfTester.start_timer(_T("apply_presence_changed_event")); + xsapi_internal_vector(uint64_t) userAddedVec; + auto& presenceRecords = evt.presence_records(); + for (auto& presenceRecord : presenceRecords) + { + uint64_t index = presenceRecord._Xbox_user_id(); + if (index == 0) + { + LOG_ERROR("social_graph: Invalid user in apply_presence_changed_event"); + continue; + } + + auto userPresenceRecordIter = inactiveBuffer->socialUserGraph.find(index); + if (userPresenceRecordIter != inactiveBuffer->socialUserGraph.end()) + { + auto socialUser = userPresenceRecordIter->second.socialUser; + if (socialUser == nullptr) + { + LOG_ERROR("social_graph: User not found in updating presence"); + continue; + } + auto userPresenceRecord = socialUser->presence_record(); + if (userPresenceRecord._Compare(presenceRecord)) // TODO: potential optimization, limits the number of compares that can happen in a single event (i.e. if presence result has 100 record split it up into 10 events) + { + auto socialUserGraphUser = inactiveBuffer->socialUserGraph.at(presenceRecord._Xbox_user_id()).socialUser; + if (socialUserGraphUser == nullptr) + { + LOG_ERROR("social_graph: User not found in social user graph"); + continue; + } + socialUserGraphUser->_Set_presence_record(presenceRecord); + userAddedVec.push_back(presenceRecord._Xbox_user_id()); + } + } + } + + if (isFreshEvent) + { + internal_social_event internalPresenceChangedEvent(internal_social_event_type::presence_changed, userAddedVec); + m_socialEventQueue.push(internalPresenceChangedEvent, m_user, social_event_type::presence_changed); + } + + m_perfTester.stop_timer(_T("apply_presence_changed_event")); +} + +void +social_graph::set_state( + _In_ social_graph_state socialGraphState + ) +{ + m_socialGraphState = socialGraphState; +} + +void +social_graph::setup_rta() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + + setup_rta_subscriptions(); + + m_devicePresenceContext = m_xboxLiveContextImpl->presence_service().add_device_presence_changed_handler( + [thisWeakPtr](device_presence_change_event_args eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->handle_device_presence_change( + eventArgs + ); + } + }); + + m_titlePresenceContext = m_xboxLiveContextImpl->presence_service().add_title_presence_changed_handler( + [thisWeakPtr](title_presence_change_event_args eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->handle_title_presence_change( + eventArgs + ); + } + }); + + m_socialRelationshipContext = m_xboxLiveContextImpl->social_service().add_social_relationship_changed_handler( + [thisWeakPtr](social_relationship_change_event_args eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->handle_social_relationship_change( + eventArgs + ); + } + }); +} + +void +social_graph::setup_rta_subscriptions( + _In_ bool shouldReinitialize + ) +{ + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("setup_rta_subscriptions")); + m_xboxLiveContextImpl->real_time_activity_service()->activate(); + auto socialRelationshipChangeResult = m_xboxLiveContextImpl->social_service().subscribe_to_social_relationship_change( + m_xboxLiveContextImpl->xbox_live_user_id() + ); + + if (socialRelationshipChangeResult.err()) + { + LOGS_ERROR << "Social relationship change error " << socialRelationshipChangeResult.err().message() << " message: " << socialRelationshipChangeResult.err_message(); + } + else + { + m_socialRelationshipChangeSubscription = socialRelationshipChangeResult.payload(); + } + + if (shouldReinitialize) + { + std::vector users; + for (auto& userPair : m_userBuffer.inactive_buffer()->socialUserGraph) + { + auto user = userPair.second.socialUser; + if (user == nullptr) + { + LOG_ERROR("social_graph: setup_rta_subscriptions get users"); + continue; + } + + users.push_back(user->_Xbox_user_id_as_integer()); + } + + setup_device_and_presence_subscriptions(users); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + m_resyncContext = m_xboxLiveContextImpl->real_time_activity_service()->add_resync_handler( + [thisWeakPtr]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->m_resyncRefreshTimer->fire(); + } + }); + + m_subscriptionErrorContext = m_xboxLiveContextImpl->real_time_activity_service()->add_subscription_error_handler( + [thisWeakPtr](real_time_activity_subscription_error_event_args args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->handle_rta_subscription_error(args); + } + }); + + m_rtaStateChangeContext = m_xboxLiveContextImpl->real_time_activity_service()->add_connection_state_change_handler( + [thisWeakPtr](real_time_activity_connection_state args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->handle_rta_connection_state_change(args); + } + }); + + m_perfTester.stop_timer(_T("setup_rta_subscriptions")); +} + +void +social_graph::setup_device_and_presence_subscriptions_helper( + _In_ const std::vector& users + ) +{ + for (auto xuid : users) + { + stringstream_t str; + str << xuid; + auto xuidStr = str.str(); + + auto devicePresenceSubResult = m_xboxLiveContextImpl->presence_service().subscribe_to_device_presence_change(xuidStr); + auto titlePresenceSubResult = m_xboxLiveContextImpl->presence_service().subscribe_to_title_presence_change( + xuidStr, + m_xboxLiveContextImpl->application_config()->title_id() + ); + + if (devicePresenceSubResult.err() || titlePresenceSubResult.err()) + { + LOG_ERROR("presence subscription failed in social manager"); + } + + + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + + m_perfTester.start_timer(_T("setup_device_and_presence_subscriptions")); + m_socialUserSubscriptions[xuid].devicePresenceChangeSubscription = devicePresenceSubResult.payload(); + m_socialUserSubscriptions[xuid].titlePresenceChangeSubscription = titlePresenceSubResult.payload(); + m_perfTester.stop_timer(_T("setup_device_and_presence_subscriptions")); + } +} + +void +social_graph::setup_device_and_presence_subscriptions( + _In_ const std::vector& users + ) +{ + std::weak_ptr thisWeak = shared_from_this(); + pplx::create_task([users, thisWeak]() + { + std::shared_ptr pThis(thisWeak.lock()); + if (pThis == nullptr) + { + return; + } + + pThis->setup_device_and_presence_subscriptions_helper(users); + }); +} + +void +social_graph::unsubscribe_users( + _In_ const std::vector& users + ) +{ + std::weak_ptr thisWeakPtr; + pplx::create_task([thisWeakPtr, users]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis == nullptr) + { + return; + } + for (auto& user : users) + { + std::lock_guard lock(pThis->m_socialGraphMutex); + std::lock_guard priorityLock(pThis->m_socialGraphPriorityMutex); + pThis->m_perfTester.start_timer(_T("unsubscribe_users")); + auto subscriptions = pThis->m_socialUserSubscriptions[user]; + pThis->m_xboxLiveContextImpl->presence_service().unsubscribe_from_device_presence_change(subscriptions.devicePresenceChangeSubscription); + pThis->m_xboxLiveContextImpl->presence_service().unsubscribe_from_title_presence_change(subscriptions.titlePresenceChangeSubscription); + pThis->m_socialUserSubscriptions.erase(user); + pThis->m_perfTester.stop_timer(_T("unsubscribe_users")); + } + }); +} + +void social_graph::refresh_graph_helper(std::vector& userRefreshList) +{ + auto inactiveBuffer = m_userBuffer.inactive_buffer(); + if (inactiveBuffer == nullptr) + { + return; + } + for (auto& user : inactiveBuffer->socialUserGraph) + { + auto socialUser = user.second.socialUser; + if (socialUser == nullptr) + { + LOG_ERROR("social graph: no user found in refresh_graph_helper"); + continue; + } + if (!socialUser->is_followed_by_caller()) + { + userRefreshList.push_back(user.first); + } + } +} + +void +social_graph::refresh_graph() +{ + std::vector userRefreshList; + { + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + + m_perfTester.start_timer(_T("refresh_graph")); + set_state(social_graph_state::refresh); + m_perfTester.stop_timer(_T("refresh_graph")); + } + refresh_graph_helper(userRefreshList); + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + + m_perfTester.start_timer(_T("refresh_graph stop")); + set_state(social_graph_state::normal); + m_perfTester.stop_timer(_T("rrefresh_graph stop")); + } + } + + std::vector userRefreshListStr; + for (auto& user : userRefreshList) + { + stringstream_t str; + str << user; + userRefreshListStr.push_back(str.str()); + } + + m_socialGraphRefreshTimer->fire(userRefreshListStr); + + std::weak_ptr thisWeakPtr = shared_from_this(); + m_peoplehubService.get_social_graph( +#if TV_API || UNIT_TEST_SERVICES || !XSAPI_CPP + m_xboxLiveContextImpl->user()->XboxUserId->Data(), +#else + m_xboxLiveContextImpl->user()->xbox_user_id(), +#endif + m_detailLevel + ) + .then([thisWeakPtr](xbox_live_result> socialListResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + if (!socialListResult.err()) + { + auto& socialList = socialListResult.payload(); + xsapi_internal_unordered_map(uint64_t, xbox_social_user) socialMap; + for (auto& user : socialList) + { + socialMap[user._Xbox_user_id_as_integer()] = user; + } + + pThis->perform_diff(socialMap); + } + else + { + LOGS_ERROR << "social_graph: refresh_graph call failed with error: " << socialListResult.err() << " " << socialListResult.err_message(); + } + } + }); +} + +void +social_graph::perform_diff( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user)& xboxSocialUsers + ) +{ + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("set_state")); + set_state(social_graph_state::diff); + m_perfTester.stop_timer(_T("set_state")); + } + + xsapi_internal_vector(xbox_social_user) usersAddedList; + xsapi_internal_vector(uint64_t) usersRemovedList; + xsapi_internal_vector(social_manager_presence_record) presenceChangeList; + xsapi_internal_vector(xbox_social_user) socialRelationshipChangeList; + xsapi_internal_vector(xbox_social_user) profileChangeList; + + for (auto& currentUserPair : xboxSocialUsers) + { + m_perfTester.start_timer(_T("perform_diff: start")); + auto inactiveBufferUserGraph = m_userBuffer.inactive_buffer()->socialUserGraph; + if (inactiveBufferUserGraph.find(currentUserPair.first) == inactiveBufferUserGraph.end()) + { + usersAddedList.push_back(currentUserPair.second); + continue; + } + + auto previousUser = inactiveBufferUserGraph.at(currentUserPair.first).socialUser; + change_list_enum didChange = xbox_social_user::_Compare(*previousUser, currentUserPair.second); + + if ((didChange & change_list_enum::presence_change) == change_list_enum::presence_change) + { + presenceChangeList.push_back(currentUserPair.second.presence_record()); + } + if ((didChange & change_list_enum::profile_change) == change_list_enum::profile_change) + { + profileChangeList.push_back(currentUserPair.second); + } + if ((didChange & change_list_enum::social_relationship_change) == change_list_enum::social_relationship_change) + { + socialRelationshipChangeList.push_back(currentUserPair.second); + } + } + + auto inactiveBufferUserGraph = m_userBuffer.inactive_buffer()->socialUserGraph; + for (auto& previousUserPair : inactiveBufferUserGraph) + { + if (xboxSocialUsers.find(previousUserPair.first) == xboxSocialUsers.end() && + (previousUserPair.second.socialUser != nullptr && previousUserPair.second.socialUser->is_following_user())) + { + usersRemovedList.push_back(previousUserPair.first); + } + } + + if (usersAddedList.size() > 0) + { + m_internalEventQueue.push(internal_social_event_type::users_changed, usersAddedList); + } + if (usersRemovedList.size() > 0) + { + m_internalEventQueue.push(internal_social_event_type::users_removed, usersRemovedList); + } + if (presenceChangeList.size() > 0) + { + m_internalEventQueue.push(internal_social_event_type::presence_changed, presenceChangeList); + } + if (profileChangeList.size() > 0) + { + m_internalEventQueue.push(internal_social_event_type::profiles_changed, profileChangeList); + } + if (socialRelationshipChangeList.size() > 0) + { + m_internalEventQueue.push(internal_social_event_type::social_relationships_changed, socialRelationshipChangeList); + } + + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("set_state normal")); + set_state(social_graph_state::normal); + m_perfTester.stop_timer(_T("set_state normal")); + } +} + +uint32_t +social_graph::title_id() +{ + return m_xboxLiveContextImpl->application_config()->title_id(); +} + +change_struct +social_graph::do_work( + _Inout_ std::vector& socialEvents + ) +{ + m_perfTester.start_timer(_T("do_work")); + m_perfTester.start_timer(_T("do_work locktime")); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.stop_timer(_T("do_work locktime")); + m_numEventsThisFrame = 0; + change_struct changeStruct; + changeStruct.socialUsers = nullptr; + m_perfTester.start_timer(_T("social_graph_state_check")); + if (m_socialGraphState == social_graph_state::normal && m_userBuffer.inactive_buffer() != nullptr && m_userBuffer.inactive_buffer()->socialUserEventQueue.empty()) + { + m_perfTester.start_timer(_T("user buffer swap")); + m_userBuffer.swap(); + m_perfTester.stop_timer(_T("user buffer swap")); + } + m_perfTester.stop_timer(_T("social_graph_state_check")); + m_perfTester.start_timer(_T("assgin active buffer")); + if (m_userBuffer.active_buffer() != nullptr) + { + changeStruct.socialUsers = &m_userBuffer.active_buffer()->socialUserGraph; + } + m_perfTester.stop_timer(_T("assgin active buffer")); + m_perfTester.start_timer(_T("!m_socialEventQueue.empty()")); + if (!m_socialEventQueue.empty() && m_socialGraphState == social_graph_state::normal) + { + m_perfTester.start_timer(_T("do_work: social event push_back")); + socialEvents.reserve(socialEvents.size() + m_socialEventQueue.social_event_list().size()); + for (auto& evt : m_socialEventQueue.social_event_list()) + { + socialEvents.push_back(evt); + } + m_socialEventQueue.clear(); + m_perfTester.stop_timer(_T("do_work: social event push_back")); + } + m_perfTester.stop_timer(_T("!m_socialEventQueue.empty()")); + m_perfTester.stop_timer(_T("do_work")); + m_perfTester.clear(); + return changeStruct; +} + +pplx::task>> +social_graph::social_graph_timer_callback( + _In_ const std::vector& users, + _In_ const fire_timer_completion_context& completionContext + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + return m_peoplehubService.get_social_graph( + m_xboxLiveContextImpl->xbox_live_user_id(), + m_detailLevel, + users + ) + .then([thisWeakPtr, users, completionContext](xbox_live_result> socialListResult) + { + try + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + if (!socialListResult.err()) + { + pThis->m_internalEventQueue.push(internal_social_event_type::users_changed, utils::std_vector_to_xsapi_vector(socialListResult.payload()), completionContext); + } + else + { + xsapi_internal_vector(xsapi_internal_string) xsapiStrVec; + for (auto user : users) + { + xsapiStrVec.push_back(user.c_str()); + } + internal_social_event evt(internal_social_event_type::users_changed, xbox_live_result(socialListResult.err(), socialListResult.err_message()), xsapiStrVec); + evt.set_completion_context(completionContext); + pThis->m_internalEventQueue.push(evt); + } + } + } + catch (const std::exception& e) + { + LOGS_DEBUG << "Exception in social_graph_timer_callback " << e.what(); + } + catch (...) + { + LOG_DEBUG("Unknown std::exception in initialization"); + } + + return socialListResult; + }); +} + +void social_graph::social_graph_refresh_callback() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + + auto task = create_delayed_task( + REFRESH_TIME_MIN, + [thisWeakPtr]() + { + try + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + pThis->social_graph_refresh_callback(); + } + } + catch (const std::exception& e) + { + LOGS_DEBUG << "Exception in social_graph_refresh_callback " << e.what(); + } + catch (...) + { + LOG_DEBUG("Unknown std::exception in initialization"); + } + }); + + refresh_graph(); +} + +void +social_graph::handle_device_presence_change( + _In_ xbox::services::presence::device_presence_change_event_args devicePresenceChanged + ) +{ + uint64_t id = utils::string_t_to_uint64(devicePresenceChanged.xbox_user_id().c_str()); + if (id == 0) + { + LOG_ERROR("Invalid user"); + return; + } + + m_internalEventQueue.push(internal_social_event(internal_social_event_type::device_presence_changed, devicePresenceChanged)); +} + +void +social_graph::handle_title_presence_change( + _In_ xbox::services::presence::title_presence_change_event_args titlePresenceChanged + ) +{ + if (titlePresenceChanged.title_state() == title_presence_state::started) + { + std::vector presenceVec(1); + presenceVec[0] = titlePresenceChanged.xbox_user_id(); + m_presenceRefreshTimer->fire(presenceVec); + } + else + { + internal_social_event titlePresenceChangeEvent(internal_social_event_type::title_presence_changed, titlePresenceChanged); + m_internalEventQueue.push(titlePresenceChangeEvent); + } +} + +void +social_graph::handle_social_relationship_change( + _In_ xbox::services::social::social_relationship_change_event_args socialRelationshipChanged + ) +{ + auto socialNotification = socialRelationshipChanged.social_notification(); + if (socialNotification == social_notification_type::added) + { + xsapi_internal_vector(xsapi_internal_string) xsapiStrVec; + for (auto user : socialRelationshipChanged.xbox_user_ids()) + { + xsapiStrVec.push_back(user.c_str()); + } + + m_internalEventQueue.push(internal_social_event_type::users_added, xsapiStrVec); + } + else if (socialNotification == social_notification_type::changed) + { + m_socialGraphRefreshTimer->fire(socialRelationshipChanged.xbox_user_ids()); + } + else if (socialRelationshipChanged.social_notification() == social_notification_type::removed) + { + std::vector xboxUserIdsAsInt; + xboxUserIdsAsInt.reserve(socialRelationshipChanged.xbox_user_ids().size()); + + for (auto& xuid : socialRelationshipChanged.xbox_user_ids()) + { + uint64_t id = utils::string_t_to_uint64(xuid.c_str()); + if (id == 0) + { + LOG_ERROR("Invalid user"); + continue; + } + xboxUserIdsAsInt.push_back(id); + } + + remove_users(xboxUserIdsAsInt); + } +} + +void +social_graph::handle_rta_subscription_error( + _In_ xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& rtaErrorEventArgs + ) +{ + LOGS_ERROR << "RTA subscription error occurred in social manager: " << rtaErrorEventArgs.err().message() << " " << rtaErrorEventArgs.err_message(); +} + +void +social_graph::handle_rta_connection_state_change( + _In_ real_time_activity_connection_state rtaState + ) +{ + bool wasDisconnected = false; + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("handle_rta_connection_state_change:disconnected_check")); + wasDisconnected = m_wasDisconnected; + m_perfTester.stop_timer(_T("handle_rta_connection_state_change:disconnected_check")); + } + if(rtaState == real_time_activity_connection_state::disconnected) + { + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("handle_rta_connection_state_change: disconnected recieved")); + m_wasDisconnected = true; + m_perfTester.stop_timer(_T("handle_rta_connection_state_change: disconnected recieved")); + } + } + else if (wasDisconnected) + { + { + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("handle_rta_connection_state_change: disconnected check false")); + m_wasDisconnected = false; + m_perfTester.stop_timer(_T("handle_rta_connection_state_change: disconnected check false")); + } + setup_rta_subscriptions(true); + } + + _Trigger_rta_connection_state_change_event(rtaState); +} + +void +social_graph::_Trigger_rta_connection_state_change_event( + _In_ xbox::services::real_time_activity::real_time_activity_connection_state state + ) +{ + if (m_stateRTAFunction != nullptr) + { + m_stateRTAFunction(state); + } +} + +void +social_graph::presence_timer_callback( + _In_ const std::vector& users + ) +{ + if (users.empty()) + { + return; + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + m_xboxLiveContextImpl->presence_service().get_presence_for_multiple_users( + users, + std::vector(), + std::vector(), + presence_detail_level::all, + false, + false + ) + .then([thisWeakPtr](xbox_live_result> presenceRecordsResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + if (!presenceRecordsResult.err()) + { + auto presenceRecordReturnVec = presenceRecordsResult.payload(); + xsapi_internal_vector(social_manager_presence_record) socialManagerPresenceVec; + socialManagerPresenceVec.reserve(presenceRecordReturnVec.size()); + for (auto& presenceRecord : presenceRecordReturnVec) + { + socialManagerPresenceVec.push_back(social_manager_presence_record(presenceRecord)); + } + + pThis->m_internalEventQueue.push( + internal_social_event_type::presence_changed, + socialManagerPresenceVec + ); + } + else + { + LOG_ERROR("social_graph: presence record update failed"); + } + } + }); +} + + +bool +social_graph::are_events_empty() +{ + std::lock_guard lock(m_socialGraphMutex); + std::lock_guard priorityLock(m_socialGraphPriorityMutex); + m_perfTester.start_timer(_T("are_events_empty")); + auto result = m_userBuffer.user_buffer_a().socialUserEventQueue.empty() && m_userBuffer.user_buffer_b().socialUserEventQueue.empty(); + m_perfTester.stop_timer(_T("are_events_empty")); + return result; +} + +void +social_graph::add_users( + _In_ const std::vector& users, + _In_ const pplx::task_completion_event>& tce + ) +{ + m_internalEventQueue.push(internal_social_event(internal_social_event_type::users_added, utils::std_vector_string_to_xsapi_vector_internal_string(users), tce)); // this is fine to be n-sized because it will generate 0 events +} + +void +social_graph::remove_users( + _In_ const std::vector& users + ) +{ + m_internalEventQueue.push(internal_social_event_type::users_removed, utils::std_vector_to_xsapi_vector(users)); +} + +void social_graph::clear_debug_counters() +{ +} + +void social_graph::print_debug_info() +{ +} + +// RTA Trigger Timer +rta_trigger_timer::rta_trigger_timer( + std::function&, const fire_timer_completion_context&)> callback + ) : + m_fCallback(std::move(callback)), + m_previousTime(std::chrono::steady_clock::duration::zero()), + m_isTaskInProgress(false), + m_queuedTask(false) +{ +} + +void +rta_trigger_timer::fire() +{ + fire_helper(); +} + +void +rta_trigger_timer::fire( + _In_ const std::vector& xboxUserIds, + _In_ const fire_timer_completion_context& usersAddedStruct + ) +{ + if (xboxUserIds.empty()) + { + return; + } + + std::lock_guard lock(m_timerLock.get()); + + for (auto& xboxUserId : xboxUserIds) + { + if (std::find(m_usersToCall.begin(), m_usersToCall.end(), xboxUserId) == m_usersToCall.end()) + { + m_usersToCall.push_back(xboxUserId); + } + } + + fire_helper(usersAddedStruct); +} + +void +rta_trigger_timer::fire_helper( + _In_ const fire_timer_completion_context& usersAddedStruct + ) +{ + if (!m_isTaskInProgress) + { + std::chrono::milliseconds timeDiff = TIME_PER_CALL_MS - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_previousTime); + std::chrono::milliseconds timeRemaining = std::max(std::chrono::milliseconds::zero(), timeDiff); + auto usersToCall = m_usersToCall; + m_usersToCall.clear(); + + std::weak_ptr thisWeakPtr = shared_from_this(); + m_isTaskInProgress = true; + m_previousTime = std::chrono::high_resolution_clock::now(); + create_delayed_task( + timeRemaining, + [thisWeakPtr, usersToCall, usersAddedStruct]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + std::lock_guard lock(pThis->m_timerLock.get()); + pThis->m_isTaskInProgress = false; + pThis->m_fCallback(usersToCall, usersAddedStruct); + + if (pThis->m_queuedTask) + { + pThis->m_queuedTask = false; + pThis->fire_helper(); + } + } + }); + } + else + { + m_queuedTask = true; + } +} + +const uint32_t user_buffers_holder::EXTRA_USER_FREE_SPACE = 5; + +user_buffers_holder::user_buffers_holder() : m_activeBuffer(nullptr), m_inactiveBuffer(nullptr) +{ +} + +user_buffers_holder::~user_buffers_holder() +{ + LOG_DEBUG("destroying user buffer holder"); + + if (m_userBufferA.buffer != nullptr) + { + xsapi_memory::mem_free(m_userBufferA.buffer); + } + + if (m_userBufferB.buffer != nullptr) + { + xsapi_memory::mem_free(m_userBufferB.buffer); + } +} + +void +user_buffers_holder::initialize( + _In_ const std::vector& users + ) +{ + initialize_buffer(m_userBufferA, users); + initialize_buffer(m_userBufferB, users); + m_activeBuffer = &m_userBufferA; + m_inactiveBuffer = &m_userBufferB; +} + +user_buffer& +user_buffers_holder::user_buffer_a() +{ + return m_userBufferA; +} + +user_buffer& user_buffers_holder::user_buffer_b() +{ + return m_userBufferB; +} + +void +user_buffers_holder::initialize_buffer( + _Inout_ user_buffer& userBuffer, + _In_ const std::vector& users, + _In_ size_t freeSpaceRequired + ) +{ + auto usersSize = users.size(); + buffer_init(userBuffer, users, freeSpaceRequired); + initialize_users_in_map(userBuffer, usersSize, 0); +} + +void user_buffers_holder::buffer_init( + _Inout_ user_buffer& userBuffer, + _In_ const std::vector& users, + _In_ size_t freeSpaceRequired + ) +{ + userBuffer.freeData = std::queue(); + size_t allocatedSize; + auto buffer = buffer_alloc(users.size(), allocatedSize, freeSpaceRequired); + if (buffer == nullptr) + { + return; // return with error + } + + userBuffer.buffer = buffer; + + auto usersSize = users.size(); + auto socialUserSize = sizeof(xbox_social_user); + + for (uint32_t i = 0; i < usersSize; ++i) + { + auto xboxSocialUser = reinterpret_cast(userBuffer.buffer + (i * socialUserSize)); + new (xboxSocialUser) xbox_social_user(); + + *xboxSocialUser = users[i]; + } + + auto totalFreeSpace = EXTRA_USER_FREE_SPACE + freeSpaceRequired; + auto startOffset = userBuffer.buffer + users.size() * socialUserSize; + for (uint32_t i = 0; i < totalFreeSpace; ++i) + { + userBuffer.freeData.push(startOffset + i * socialUserSize); + } +} + +byte* +user_buffers_holder::buffer_alloc( + _In_ size_t numUsers, + _Inout_ size_t& allocatedSize, + _In_ size_t freeSpaceRequired + ) +{ + if (numUsers == 0) + { + return nullptr; + } + + auto totalFreeSpace = EXTRA_USER_FREE_SPACE + freeSpaceRequired; // gives some wiggle room with the alloc, 5 extra users can be added to graph before realloc + + size_t size = (numUsers + totalFreeSpace) * sizeof(xbox_social_user); + auto buffer = static_cast(xsapi_memory::mem_alloc(size)); + allocatedSize = size; + return buffer; +} + +void +user_buffers_holder::initialize_users_in_map( + _Inout_ user_buffer& userBuffer, + _In_ size_t numUsers, + _In_ size_t bufferOffset + ) +{ + xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& socialUserGraph = userBuffer.socialUserGraph; + auto buffer = userBuffer.buffer + bufferOffset; + for (uint32_t i = 0; i < numUsers; ++i) + { + auto userPtr = (buffer + i * sizeof(xbox_social_user)); + xbox_social_user* socialUser = reinterpret_cast(userPtr); + + auto userIter = socialUserGraph.find(socialUser->_Xbox_user_id_as_integer()); + if (userIter == socialUserGraph.end()) + { + xbox_social_user_context userContext; + userContext.refCount = 1; + userContext.socialUser = socialUser; + + socialUserGraph[socialUser->_Xbox_user_id_as_integer()] = userContext; + } + else + { + userIter->second.socialUser = socialUser; + } + } +} + +void +user_buffers_holder::add_users_to_buffer( + _In_ const std::vector& users, + _Inout_ user_buffer& userBufferInactive, + _In_ size_t finalSize + ) +{ + auto totalSizeNeeded = __max(finalSize, users.size()); + if (totalSizeNeeded > userBufferInactive.freeData.size()) + { + uint32_t size = 0; + for (auto& user : userBufferInactive.socialUserGraph) + { + if (user.second.socialUser != nullptr) + { + ++size; + } + } + std::vector socialVec(size); +#if _WIN32 + memcpy_s(&socialVec[0], socialVec.size() * sizeof(xbox_social_user), &userBufferInactive.buffer[0], size * sizeof(xbox_social_user)); +#else + memcpy(&socialVec[0], &userBufferInactive.buffer[0], size * sizeof(xbox_social_user)); +#endif + xsapi_memory::mem_free(userBufferInactive.buffer); + initialize_buffer(userBufferInactive, socialVec, totalSizeNeeded); + } + + for (auto& user : users) + { + auto freeData = userBufferInactive.freeData.front(); + xbox_social_user* xboxSocialUser = reinterpret_cast(freeData); + userBufferInactive.freeData.pop(); + new (freeData) xbox_social_user(); + + *xboxSocialUser = user; + initialize_users_in_map(userBufferInactive, 1, freeData - userBufferInactive.buffer); + } +} + +void +user_buffers_holder::remove_users_from_buffer( + _In_ const std::vector& users, + _Inout_ user_buffer& userBufferInactive + ) +{ + for (auto user : users) + { + auto xboxSocialUserContextIter = userBufferInactive.socialUserGraph.find(user); + if (xboxSocialUserContextIter != userBufferInactive.socialUserGraph.end()) + { + auto userPtr = userBufferInactive.socialUserGraph[user].socialUser; + userBufferInactive.freeData.push(reinterpret_cast(userPtr)); + userBufferInactive.socialUserGraph.erase(xboxSocialUserContextIter); + } + else + { + LOG_ERROR("user_buffers_holder: user not found in buffer"); + } + } +} + +void +user_buffers_holder::swap() +{ + if (m_activeBuffer == &m_userBufferA) + { + m_activeBuffer = &m_userBufferB; + m_inactiveBuffer = &m_userBufferA; + } + else + { + m_activeBuffer = &m_userBufferA; + m_inactiveBuffer = &m_userBufferB; + } +} + +user_buffer* user_buffers_holder::active_buffer() +{ + return m_activeBuffer; +} + +user_buffer* +user_buffers_holder::inactive_buffer() +{ + return m_inactiveBuffer; +} + +void +user_buffers_holder::add_event( + _In_ const internal_social_event& internalSocialEvent + ) +{ + m_activeBuffer->socialUserEventQueue.push(internalSocialEvent); +} + +event_queue::event_queue() : + m_lastKnownSize(0), + m_eventState(event_state::clear) +{ +} + +event_queue::event_queue( + _In_ const xbox_live_user_t& user_t + ) : + m_user(std::move(user_t)), + m_lastKnownSize(0), + m_eventState(event_state::clear) +{ +} + +const std::vector& +event_queue::social_event_list() +{ + std::lock_guard lock(m_eventGraphMutex.get()); + m_eventState = event_state::read; + return m_socialEventList; +} + +void +event_queue::push( + _In_ const internal_social_event& socialEvent, + _In_ xbox_live_user_t user, + _In_ social_event_type socialEventType, + _In_ xbox_live_result error + ) +{ + if (socialEventType == social_event_type::unknown) + { + return; + } + + std::vector usersAffected; + usersAffected.reserve(socialEvent.users_affected_as_string_vec().size()); + for (auto& affectedUser : socialEvent.users_affected_as_string_vec()) + { + usersAffected.push_back(affectedUser.c_str()); + } + + std::lock_guard lock(m_eventGraphMutex.get()); + social_event selectedEvt; + + selectedEvt = social_event(user, socialEventType, usersAffected, nullptr, error.err(), error.err_message()); + m_socialEventList.push_back(selectedEvt); + + m_eventState = event_state::ready_to_read; +} + +void +event_queue::clear() +{ + std::lock_guard lock(m_eventGraphMutex.get()); + m_socialEventList.clear(); + m_eventState = event_state::clear; +} + +bool +event_queue::empty() +{ + std::lock_guard lock(m_eventGraphMutex.get()); + return m_socialEventList.empty(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/social_manager.cpp b/Source/Services/Social/Manager/social_manager.cpp new file mode 100644 index 00000000..fc24a3ec --- /dev/null +++ b/Source/Services/Social/Manager/social_manager.cpp @@ -0,0 +1,509 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" +#include "social_manager_internal.h" +#if UNIT_TEST_SERVICES +#include "MockSocialManager.h" +#endif + +#include "perf_tester.h" + +static xbox::services::perf_tester m_perfTester; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +std::shared_ptr social_manager::m_socialManager; + +std::shared_ptr +social_manager::get_singleton_instance() +{ + static std::mutex socialManagerInitLock; + std::lock_guard lock(socialManagerInitLock); + if (m_socialManager == nullptr) + { + m_socialManager = std::shared_ptr(new social_manager()); + } + return m_socialManager; +} + +social_manager::social_manager() +{ + m_perfTester = perf_tester(_T("social_manager")); +} + +xbox_live_result> +social_manager::create_social_user_group_from_filters( + _In_ xbox_live_user_t user, + _In_ presence_filter presenceFilterLevel, + _In_ relationship_filter relationshipFilter + ) +{ + std::lock_guard lock(m_socialMangerLock); + if (user == nullptr) return xbox_live_result>(xbox_live_error_code::invalid_argument, "user is null"); + + string_t ownerUserId = user_context::get_user_id(user); + + if (m_localGraphs.find(ownerUserId) == m_localGraphs.end()) + { + return xbox_live_result>( + xbox_live_error_code::logic_error, + "Add local user to graph before creating a social user group for them" + ); + } + + auto viewHash = utils::create_guid(true); + + uint32_t titleId = m_localGraphs[ownerUserId]->title_id(); + auto socialGroup = std::make_shared( + viewHash, + presenceFilterLevel, + relationshipFilter, + titleId, + user + ); + + m_userToViewMap[ownerUserId].push_back(viewHash); + m_xboxSocialUserGroups[viewHash] = socialGroup; + + if (m_localGraphs[ownerUserId]->is_initialized()) + { + + m_xboxSocialUserGroups[viewHash]->initialize_filter_list( + *m_localGraphs[ownerUserId]->active_buffer_social_graph() + ); + + std::lock_guard eventLock(m_socialManagerEventLock); + m_eventQueue.push_back( + social_event( + user, + social_event_type::social_user_group_loaded, + std::vector(), + std::make_shared(socialGroup) + ) + ); + } + return socialGroup; +} + +xbox_live_result> +social_manager::create_social_user_group_from_list( + _In_ xbox_live_user_t user, + _In_ std::vector xboxUserIdList + ) +{ + if (xboxUserIdList.empty()) + { + return xbox_live_result>(xbox_live_error_code::invalid_argument, "xboxUserIdList cannot be empty"); + } + else if (xboxUserIdList.size() > MAX_USERS_FROM_LIST) + { + return xbox_live_result>(xbox_live_error_code::invalid_argument, "xboxUserIdList has a limit of 100 users"); + } + + std::lock_guard lock(m_socialMangerLock); + string_t ownerUserId = user_context::get_user_id(user); + + auto userGraph = m_localGraphs.find(ownerUserId); + if (userGraph == m_localGraphs.end()) + { + return xbox_live_result>( + xbox_live_error_code::logic_error, + "Add local user to graph before creating a social user group for them" + ); + } + + auto viewHash = utils::create_guid(true); + auto socialGroup = std::make_shared( + viewHash, + xboxUserIdList, + user + ); + + auto hash = socialGroup->hash(); + + std::weak_ptr thisWeakPtr = shared_from_this(); + + pplx::task_completion_event> tce; + userGraph->second->add_users(xboxUserIdList, tce); + + create_task(tce).then([thisWeakPtr, user, socialGroup, hash, ownerUserId](xbox_live_result users) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + std::lock_guard eventLock(pThis->m_socialManagerEventLock); + + if (users.err()) + { + pThis->m_eventQueue.push_back( + social_event( + user, + social_event_type::social_user_group_loaded, + std::vector(), + std::make_shared(socialGroup), + users.err(), + users.err_message() + ) + ); + } + else + { + std::vector usersAffected; + for (auto& trackedUser : socialGroup->users_tracked_by_social_user_group()) + { + usersAffected.push_back(trackedUser); + } + + pThis->m_eventQueue.push_back( + social_event( + user, + social_event_type::social_user_group_loaded, + usersAffected, + std::make_shared(socialGroup) + ) + ); + + } + } + }); + + m_userToViewMap[ownerUserId].push_back(viewHash); + m_xboxSocialUserGroups[viewHash] = socialGroup; + return socialGroup; +} + +xbox_live_result +social_manager::destroy_social_user_group( + _In_ std::shared_ptr socialGroup + ) +{ + std::lock_guard lock(m_socialMangerLock); + + if (m_xboxSocialUserGroups.find(socialGroup->hash()) == m_xboxSocialUserGroups.end()) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Social user group not found"); + } + + // Remove the entry from user to view map + string_t user; + bool isFound = false; + for (auto& map : m_userToViewMap) + { + for (auto itr = map.second.begin(); itr < map.second.end(); ++itr) + { + auto viewGuid = *itr; + if (socialGroup->hash() == viewGuid) + { + user = map.first; + map.second.erase(itr); + isFound = true; + break; + } + } + if (isFound) + { + break; + } + } + + auto& viewToDestroy = m_xboxSocialUserGroups[socialGroup->hash()]; + std::vector trackingList = viewToDestroy->tracking_users(); + if (socialGroup->social_user_group_type() != social_user_group_type::filter_type) + { + m_localGraphs[user]->remove_users(trackingList); + } + viewToDestroy->destroy(); + + m_xboxSocialUserGroups.erase(socialGroup->hash()); + + + return xbox_live_result(); +} + +xbox_live_result +social_manager::add_local_user( + _In_ xbox_live_user_t user, + _In_ social_manager_extra_detail_level extraDetailLevel + ) +{ + if (user == nullptr) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "user object is null"); + } + + auto userString = user_context::get_user_id(user); + + { + std::lock_guard lock(m_socialMangerLock); + + if (m_localGraphs.find(userString) != m_localGraphs.end()) + { + return xbox_live_result(xbox_live_error_code::logic_error, "user already exists in graph"); + } + + std::weak_ptr thisWeakPtr = shared_from_this(); + +#if UNIT_TEST_SERVICES + auto newGraph = std::shared_ptr( + new MockSocialGraph( +#else + auto newGraph = std::shared_ptr( + new social_graph( +#endif + user, + extraDetailLevel, + [thisWeakPtr, user]() + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + std::lock_guard eventLock(pThis->m_socialManagerEventLock); + social_event userRemovedEvent( + user, + social_event_type::local_user_removed, + std::vector() + ); + pThis->m_eventQueue.push_back(userRemovedEvent); + } + } + )); + + newGraph->initialize() + .then([thisWeakPtr, user, userString](xbox_live_result result) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis) + { + if (result.err()) + { + std::lock_guard eventLock(pThis->m_socialManagerEventLock); + pThis->m_eventQueue.push_back( + social_event( + user, + social_event_type::local_user_added, + std::vector(), + std::make_shared(), + result.err(), + result.err_message() + ) + ); + } + else + { + std::lock_guard lock(pThis->m_socialMangerLock); + + auto viewList = pThis->m_userToViewMap[userString]; + if (!viewList.empty()) + { + for (auto& view : viewList) + { + if (pThis->m_xboxSocialUserGroups.find(view) != pThis->m_xboxSocialUserGroups.end()) + { + auto currentView = pThis->m_xboxSocialUserGroups[view]; + if (currentView->social_user_group_type() == social_user_group_type::filter_type) + { + std::weak_ptr socialManagerWeakPtr = pThis; + currentView->initialize_filter_list( + *pThis->m_localGraphs[userString]->active_buffer_social_graph() + ); + + std::lock_guard eventLock(pThis->m_socialManagerEventLock); + pThis->m_eventQueue.push_back( + social_event( + user, + social_event_type::social_user_group_loaded, + std::vector(), + std::make_shared(currentView) + ) + ); + } + } + + } + } + + std::lock_guard eventLock(pThis->m_socialManagerEventLock); + pThis->m_eventQueue.push_back( + social_event( + user, + social_event_type::local_user_added, + std::vector() + ) + ); + } + } + }); + + m_localGraphs[userString] = newGraph; + } + + { + std::lock_guard lock(m_socialMangerLock); + m_localUserList.push_back(user); + } + return xbox_live_result(); +} + +xbox_live_result +social_manager::remove_local_user( + _In_ xbox_live_user_t user + ) +{ + if (user == nullptr) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "User cannot be null"); + } + + std::lock_guard lock(m_socialMangerLock); + + auto xboxUserId = user_context::get_user_id(user); + + if (m_localGraphs.find(xboxUserId) == m_localGraphs.end()) + { + return xbox_live_result(xbox_live_error_code::logic_error, "User not found in graph"); + } + + m_localGraphs.erase(xboxUserId); + + auto& currentView = m_userToViewMap[xboxUserId]; + for (auto& view : currentView) + { + if (m_xboxSocialUserGroups[view]) + { + m_xboxSocialUserGroups[view]->destroy(); + m_xboxSocialUserGroups.erase(view); + } + } + + m_userToViewMap.erase(xboxUserId); + + std::vector userList; + uint32_t i; + for (i = 0; i < m_localUserList.size(); ++i) + { + auto localUser = m_localUserList[i]; + string_t userId = user_context::get_user_id(user); + string_t localUserId = user_context::get_user_id(localUser); + if (utils::str_icmp(localUserId, userId) != 0) + { + userList.push_back(localUser); + } + } + + m_localUserList = userList; + return xbox_live_result(); +} + +std::vector +social_manager::do_work() +{ + std::lock_guard lock(m_socialMangerLock); + std::lock_guard eventLock(m_socialManagerEventLock); + std::vector socialEvents(m_eventQueue); + m_perfTester.start_timer(_T("do_work")); + m_perfTester.start_timer(_T("do_work: eventqueue clear")); + m_eventQueue.clear(); + m_perfTester.stop_timer(_T("do_work: eventqueue clear")); + for (auto& graph : m_localGraphs) + { + m_perfTester.start_timer(_T("do_work: social_graph do_work")); + auto graphData = graph.second->do_work(socialEvents); + m_perfTester.stop_timer(_T("do_work: social_graph do_work")); + const auto& userViewList = m_userToViewMap[graph.first]; + for (auto& viewHash : userViewList) + { + auto& view = m_xboxSocialUserGroups[viewHash]; + if(graphData.socialUsers != nullptr) + { + m_perfTester.start_timer(_T("do_work: update_view")); + view->update_view(*graphData.socialUsers, socialEvents); + m_perfTester.stop_timer(_T("do_work: update_view")); + } + } + } + + m_perfTester.stop_timer(_T("do_work")); + m_perfTester.clear(); + return socialEvents; +} + +const std::vector& +social_manager::local_users() const +{ + return m_localUserList; +} + +xbox_live_result social_manager::update_social_user_group( + _In_ const std::shared_ptr& socialGroup, + _In_ const std::vector& users + ) +{ + std::lock_guard lock(m_socialMangerLock); + + if (m_xboxSocialUserGroups.find(socialGroup->hash()) == m_xboxSocialUserGroups.end()) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Social user group not found"); + } + + if (socialGroup->social_user_group_type() != social_user_group_type::user_list_type) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "Users can only be added to user groups of user_list_type"); + } + + if (users.size() > MAX_USERS_FROM_LIST) + { + return xbox_live_result(xbox_live_error_code::invalid_argument, "users cannot be larger than 100 users"); + } + + auto diffUsers = socialGroup->_Update_users_in_group(users); + + auto localUser = socialGroup->local_user(); + string_t xuid = user_context::get_user_id(localUser); + m_localGraphs[xuid]->remove_users(utils::xsapi_vector_to_std_vector(diffUsers.removeGroup)); + std::weak_ptr thisWeakPtr = shared_from_this(); + + auto hash = socialGroup->hash(); + pplx::task_completion_event> tce; + m_localGraphs[xuid]->add_users(utils::xsapi_vector_to_std_vector(diffUsers.addGroup), tce); + create_task(tce).then([thisWeakPtr, localUser, users, hash](xbox_live_result userResult) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if(pThis) + { + std::lock_guard eventLock(pThis->m_socialManagerEventLock); + + // send event + pThis->m_eventQueue.push_back( + social_event( + localUser, + social_event_type::social_user_group_updated, + std::vector(), + nullptr, + userResult.err(), + userResult.err_message() + ) + ); + } + }); + + return xbox_live_result(); +} + +void social_manager::_Log_state() +{ + LOGS_DEBUG << "[SM] State: m_xboxSocialUserGroups: " << m_xboxSocialUserGroups.size() + << " m_userToViewMap: " << m_userToViewMap.size() + << " m_localGraphs: " << m_localGraphs.size() + << " m_eventQueue: " << m_eventQueue.size() + << " m_localUserList: " << m_localUserList.size(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END diff --git a/Source/Services/Social/Manager/social_manager_internal.h b/Source/Services/Social/Manager/social_manager_internal.h new file mode 100644 index 00000000..652d3504 --- /dev/null +++ b/Source/Services/Social/Manager/social_manager_internal.h @@ -0,0 +1,566 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#pragma once +#include "xsapi/social_manager.h" +#include "xsapi/system.h" +#include "xsapi/social.h" +#if XSAPI_U +#include "ppltasks_extra_unix.h" +#else +#include "ppltasks_extra.h" +#endif +#include "system_internal.h" +#include "user_context.h" +#include "xsapi/mem.h" +#include "perf_tester.h" + +typedef unsigned char byte; + +namespace xbox { namespace services { namespace system { + class xbox_live_mutex; +}}} + +namespace xbox { namespace services { namespace social { namespace manager { + +/// +/// internal only +/// +enum class change_list_enum +{ + no_change = 0x0, + profile_change = 0x1, + presence_change = 0x2, + social_relationship_change = 0x4, + change = 0x8 +}; + +enum class internal_social_event_type +{ + unknown, + users_changed, + users_removed, + presence_changed, + device_presence_changed, + title_presence_changed, + profiles_changed, + social_relationships_changed, + users_added +}; + +enum class social_graph_state +{ + normal, + diff, + event_processing, + refresh +}; + +struct user_group_status_change +{ + xsapi_internal_vector(string_t) addGroup; + xsapi_internal_vector(uint64_t) removeGroup; +}; + +inline change_list_enum operator|(change_list_enum lhs, change_list_enum rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +inline change_list_enum operator&(change_list_enum lhs, change_list_enum rhs) +{ + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +struct fire_timer_completion_context +{ + fire_timer_completion_context() : isNull(true), context(0), numObjects(0) {} + bool isNull; + uint32_t context; + size_t numObjects; + pplx::task_completion_event> tce; +}; + +class internal_social_event +{ +public: + internal_social_event() : m_socialEventType(internal_social_event_type::unknown) {} + internal_social_event(_In_ internal_social_event_type eventType, _In_ xsapi_internal_vector(xbox_social_user) usersAffected); + internal_social_event(_In_ internal_social_event_type eventType, _In_ xsapi_internal_vector(social_manager_presence_record) presenceRecords); + internal_social_event(_In_ internal_social_event_type eventType, _In_ xbox::services::presence::device_presence_change_event_args devicePresenceArgs); + internal_social_event(_In_ internal_social_event_type eventType, _In_ xbox::services::presence::title_presence_change_event_args titlePresenceArgs); + internal_social_event(_In_ internal_social_event_type eventType, _In_ xsapi_internal_vector(uint64_t) userList); + internal_social_event( + _In_ internal_social_event_type socialEventType, + _In_ xbox_live_result errorInfo, + _In_ xsapi_internal_vector(xsapi_internal_string) userList + ); + + internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(xsapi_internal_string) userAddList, + _In_ pplx::task_completion_event> tce + ); + + internal_social_event( + _In_ internal_social_event_type eventType, + _In_ xsapi_internal_vector(xsapi_internal_string) userAddList + ); + + const fire_timer_completion_context& completion_context() const; + void set_completion_context(_In_ const fire_timer_completion_context& compleitionContext); + const xsapi_internal_vector(xbox_social_user)& users_affected() const; + const xsapi_internal_vector(uint64_t)& users_to_remove() const; + const xsapi_internal_vector(social_manager_presence_record)& presence_records() const; + const xbox::services::presence::device_presence_change_event_args& device_presence_args() const; + const xbox::services::presence::title_presence_change_event_args& title_presence_args() const; + const xsapi_internal_vector(xsapi_internal_string)& users_affected_as_string_vec() const; + const pplx::task_completion_event>& tce() const; + const xbox_live_result& error() const; + internal_social_event_type event_type() const; + +private: + internal_social_event_type m_socialEventType; + fire_timer_completion_context m_completionContext; + xsapi_internal_vector(social_manager_presence_record) m_presenceRecords; + xsapi_internal_vector(xbox_social_user) m_usersAffected; + xsapi_internal_vector(xsapi_internal_string) m_usersAffectedAsStringVec; + xsapi_internal_vector(uint64_t) m_userList; + pplx::task_completion_event> m_tce; + xbox::services::presence::device_presence_change_event_args m_devicePresenceArgs; + xbox::services::presence::title_presence_change_event_args m_titlePresenceArgs; + xbox_live_result m_error; +}; + +class rta_trigger_timer : public std::enable_shared_from_this +{ +public: + rta_trigger_timer() {}; + + rta_trigger_timer( + std::function&, const fire_timer_completion_context&)> callback + ); + + void fire(); + void fire(_In_ const std::vector& xboxUserIds, _In_ const fire_timer_completion_context& usersAddedStruct = fire_timer_completion_context()); + +private: + static const std::chrono::milliseconds TIME_PER_CALL_MS; + + void fire_helper(_In_ const fire_timer_completion_context& usersAddedStruct = fire_timer_completion_context()); + + bool m_isTaskInProgress; + bool m_queuedTask; +#if _MSC_VER <= 1800 && !defined XSAPI_I + std::chrono::system_clock::time_point m_previousTime; +#else + std::chrono::time_point m_previousTime; +#endif + std::vector m_usersToCall; + std::function&, const fire_timer_completion_context&)> m_fCallback; + xbox::services::system::xbox_live_mutex m_timerLock; +}; + +struct xbox_social_user_context +{ + uint32_t refCount; + xbox_social_user* socialUser; +}; + +struct xbox_social_user_subscriptions +{ + std::shared_ptr devicePresenceChangeSubscription; + std::shared_ptr titlePresenceChangeSubscription; +}; + +struct change_struct +{ + const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)* socialUsers; +}; + +class internal_event_queue +{ +public: + template + void push(_In_ internal_social_event_type socialEventType, _In_ const std::vector userList, _In_ const fire_timer_completion_context& completionContext = fire_timer_completion_context()) + { + std::lock_guard lock(m_eventMutex.get()); + std::lock_guard priorityLock(m_eventPriorityMutex.get()); + auto numGroupsofUsers = userList.size() / MAX_USERS_AFFECTED_PER_EVENT + 1; + for (uint32_t i = 0; i < numGroupsofUsers; ++i) + { + auto endLoc = __min((i + 1) * MAX_USERS_AFFECTED_PER_EVENT, userList.size()); + std::vector usersAffected(userList.begin() + i * MAX_USERS_AFFECTED_PER_EVENT, userList.begin() + endLoc); + auto evt = internal_social_event(socialEventType, usersAffected); + if (i == 0 && !completionContext.isNull) + { + evt.set_completion_context(completionContext); + } + m_eventQueue.push_back(evt); + } + } + + void push(_In_ const internal_social_event& socialEvent) + { + std::lock_guard lock(m_eventMutex.get()); + std::lock_guard priorityLock(m_eventPriorityMutex.get()); + m_eventQueue.push_back(socialEvent); + } + + internal_social_event pop() + { + std::lock_guard lock(m_eventMutex.get()); + std::lock_guard priorityLock(m_eventPriorityMutex.get()); + internal_social_event evt = m_eventQueue.front(); + m_eventQueue.pop_front(); + return evt; + } + + size_t size() + { + std::lock_guard lock(m_eventMutex.get()); + std::lock_guard priorityLock(m_eventPriorityMutex.get()); + return m_eventQueue.size(); + } + + bool empty(_In_ bool isPriority = false) + { + if (!isPriority) + { + std::lock_guard lock(m_eventMutex.get()); + } + std::lock_guard priorityLock(m_eventPriorityMutex.get()); + return m_eventQueue.empty(); + } + +private: + static const uint32_t MAX_USERS_AFFECTED_PER_EVENT = 10; + + bool m_useLock; + xsapi_internal_dequeue(internal_social_event) m_eventQueue; + xbox::services::system::xbox_live_mutex m_eventMutex; + xbox::services::system::xbox_live_mutex m_eventPriorityMutex; +}; + +struct user_buffer +{ + user_buffer() : buffer(nullptr) {} + + byte* buffer; + std::queue freeData; + xsapi_internal_unordered_map(uint64_t, xbox_social_user_context) socialUserGraph; + internal_event_queue socialUserEventQueue; +}; + +class user_buffers_holder +{ +public: + user_buffers_holder(); + ~user_buffers_holder(); + + void initialize(_In_ const std::vector& users); + void swap(); + + user_buffer& user_buffer_a(); + user_buffer& user_buffer_b(); + + user_buffer* active_buffer(); + user_buffer* inactive_buffer(); + + void add_event( + _In_ const internal_social_event& internalSocialEvent + ); + + void add_users_to_buffer(_In_ const std::vector& users, _Inout_ user_buffer& userBufferInactive, _In_ size_t finalSize = 0); + + void remove_users_from_buffer(_In_ const std::vector& users, _Inout_ user_buffer& userBufferInactive); + + static void initialize_users_in_map(_Inout_ user_buffer& userBuffer, _In_ size_t numUsers, _In_ size_t bufferOffset); + +protected: + void initialize_buffer(_Inout_ user_buffer& userBuffer, _In_ const std::vector& users, _In_ size_t freeSpaceRequired = 0); + + void buffer_init(_Inout_ user_buffer& userBuffer, _In_ const std::vector& users, _In_ size_t freeSpaceRequired); + + static void add_users_impl(_In_ const xsapi_internal_vector(xbox_social_user)& users, _Inout_ user_buffer& userBufferActive, _Inout_ user_buffer& userBufferInactive); + + static void remove_users_impl(_In_ const xsapi_internal_vector(xbox_social_user)& users, _Inout_ user_buffer& userBufferActive, _Inout_ user_buffer& userBufferInactive); + + byte* buffer_alloc( + _In_ size_t numUsers, + _Inout_ size_t& allocatedSize, + _In_ size_t freeSpaceRequired + ); + + static const uint32_t EXTRA_USER_FREE_SPACE; + + user_buffer* m_activeBuffer; + user_buffer* m_inactiveBuffer; + user_buffer m_userBufferA; + user_buffer m_userBufferB; +}; + +enum class event_state +{ + read, + ready_to_read, + clear +}; + +class event_queue +{ +public: + event_queue(); + event_queue(_In_ const xbox_live_user_t& user_t); + void push( + _In_ const internal_social_event& socialEvent, + _In_ xbox_live_user_t user, + _In_ social_event_type type, + _In_ xbox_live_result error = xbox_live_result() + ); + + bool empty(); + void clear(); + size_t size() + { + return m_socialEventList.size(); + } + const std::vector& social_event_list(); + +private: + event_state m_eventState; + uint32_t m_lastKnownSize; + xbox_live_user_t m_user; + std::vector m_socialEventList; + xbox::services::system::xbox_live_mutex m_eventGraphMutex; + + static social_event_type convert_internal_social_event_type_to_social_event_type(_In_ internal_social_event_type socialEventType); +}; + +class peoplehub_service +{ +public: + peoplehub_service() {}; + + peoplehub_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr httpCallSettings, + _In_ std::shared_ptr appConfig + ); + + pplx::task>> get_social_graph( + _In_ const string_t& callerXboxUserId, + _In_ social_manager_extra_detail_level decorations + ); + + pplx::task>> get_social_graph( + _In_ const string_t& callerXboxUserId, + _In_ social_manager_extra_detail_level decorations, + _In_ const std::vector xboxLiveUsers + ); + + pplx::task>> get_suggested_friends( + _In_ const string_t& xboxUserId, + _In_ social_manager_extra_detail_level decorations + ); + +private: + pplx::task>> get_social_graph( + _In_ const string_t& callerXboxUserId, + _In_ social_manager_extra_detail_level decorations, + _In_ const string_t& relationshipType, + _In_ const std::vector xboxLiveUsers, + _In_ bool isBatch + ); + + string_t social_graph_subpath( + _In_ const string_t& xboxUserId, + _In_ social_manager_extra_detail_level decorations, + _In_ const string_t& relationshipType, + _In_ const std::vector xboxLiveUsers, + _In_ bool isBatch + ) const; + + std::shared_ptr m_userContext; + std::shared_ptr m_httpCallSettings; + std::shared_ptr m_appConfig; +}; + +class social_graph_snapshot +{ +public: + social_graph_snapshot( + _In_ xsapi_internal_unordered_map(string_t, xbox_social_user_context) snapshot + ); + + const xsapi_internal_unordered_map(string_t, xbox_social_user_context)& snapshot(); +private: + xsapi_internal_unordered_map(string_t, xbox_social_user_context) m_socialUsers; +}; + + +class social_graph : public std::enable_shared_from_this +{ +public: + social_graph( + _In_ xbox_live_user_t user, + _In_ social_manager_extra_detail_level socialManagerExtraDetailLevel, + _In_ std::function graphDestructionCompleteCallback + ); + + virtual ~social_graph(); + + pplx::task> virtual initialize(); + + uint32_t title_id(); + + change_struct do_work(_Inout_ std::vector& socialEvents); + + void add_users(_In_ const std::vector& users, _In_ const pplx::task_completion_event>& tce); + + void remove_users(_In_ const std::vector& users); + + bool is_initialized(); + + bool are_events_empty(); + + void clear_debug_counters(); + + void print_debug_info(); + + const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)* active_buffer_social_graph(); + +protected: + static const std::chrono::minutes REFRESH_TIME_MIN; + + static const uint32_t NUM_EVENTS_PER_FRAME; + + void setup_rta(); + + void setup_rta_subscriptions( + _In_ bool shouldReinitialize = false + ); + + void refresh_graph(); + + bool process_events(); + + void initialize_social_buffers(_In_ const std::vector& socialUsers); + + void social_graph_refresh_callback(); + + void do_event_work(); + + void presence_timer_callback( + _In_ const std::vector& users + ); + + pplx::task>> social_graph_timer_callback( + _In_ const std::vector& users, + _In_ const fire_timer_completion_context& completionContext + ); + + void update_graph( + _In_ std::vector> userList + ); + + void handle_title_presence_change( + _In_ xbox::services::presence::title_presence_change_event_args titlePresenceChanged + ); + + void handle_device_presence_change( + _In_ xbox::services::presence::device_presence_change_event_args devicePresenceChanged + ); + + void handle_social_relationship_change( + _In_ xbox::services::social::social_relationship_change_event_args socialRelationshipChanged + ); + + void handle_rta_subscription_error( + _In_ xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& rtaErrorEventArgs + ); + + void handle_rta_connection_state_change( + _In_ xbox::services::real_time_activity::real_time_activity_connection_state rtaState + ); + + void perform_diff(_In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user)& xboxSocialUsers); + + void set_state(_In_ social_graph_state socialGraphState); + + void process_cached_events(); + + void apply_event( + _In_ const internal_social_event& evt, + _In_ bool applyToEventQueue + ); + + void setup_device_and_presence_subscriptions( + _In_ const std::vector& users + ); + + void setup_device_and_presence_subscriptions_helper( + _In_ const std::vector& users + ); + + void unsubscribe_users( + _In_ const std::vector& users + ); + + void _Trigger_rta_connection_state_change_event(_In_ xbox::services::real_time_activity::real_time_activity_connection_state state); + + void apply_users_change_event(_In_ const internal_social_event& socialEvent, _In_ user_buffer* inactiveBuffer, _In_ bool isFreshEvent); + + void apply_users_removed_event(_In_ const internal_social_event& socialEvent, _In_ user_buffer* inactiveBuffer, _Inout_ social_event_type& eventType, _In_ bool isFreshEvent); + + void apply_users_added_event(_In_ const internal_social_event& socialEvent, _In_ user_buffer* inactiveBuffer, _In_ bool isFreshEvent); + + void apply_device_presence_changed_event(_In_ const internal_social_event& socialEvent, _In_ user_buffer* inactiveBuffer, _In_ bool isFreshEvent, _Inout_ social_event_type& eventType); + + void apply_presence_changed_event(_In_ const internal_social_event& socialEvent, _In_ user_buffer* inactiveBuffer, _In_ bool isFreshEvent); + + void refresh_graph_helper(std::vector& userRefreshList); + + + bool m_isInitialized; + bool m_wasDisconnected; + + //rta function contexts + function_context m_devicePresenceContext; + function_context m_titlePresenceContext; + function_context m_socialRelationshipContext; + function_context m_resyncContext; + function_context m_subscriptionErrorContext; + function_context m_rtaStateChangeContext; + + uint32_t m_numEventsThisFrame; + uint32_t m_userAddedContext; + + social_manager_extra_detail_level m_detailLevel; + social_graph_state m_socialGraphState; + + xbox_live_user_t m_user; + std::shared_ptr m_xboxLiveContextImpl; + std::shared_ptr m_presenceRefreshTimer; + std::shared_ptr m_socialGraphRefreshTimer; + std::shared_ptr m_resyncRefreshTimer; + std::shared_ptr m_socialRelationshipChangeSubscription; + peoplehub_service m_peoplehubService; + std::function m_graphDestructionCompleteCallback; + std::function m_stateRTAFunction; + xsapi_internal_unordered_map(uint64_t, xbox_social_user_subscriptions) m_socialUserSubscriptions; + std::recursive_mutex m_socialGraphMutex; + std::recursive_mutex m_socialGraphPriorityMutex; + xbox::services::perf_tester m_perfTester; + event_queue m_socialEventQueue; + internal_event_queue m_internalEventQueue; + user_buffers_holder m_userBuffer; +}; + +}}}} diff --git a/Source/Services/Social/Manager/social_manager_presence_record.cpp b/Source/Services/Social/Manager/social_manager_presence_record.cpp new file mode 100644 index 00000000..ecb67194 --- /dev/null +++ b/Source/Services/Social/Manager/social_manager_presence_record.cpp @@ -0,0 +1,216 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" +#include "xsapi/presence.h" + +using namespace xbox::services::presence; +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +social_manager_presence_record::social_manager_presence_record() : + m_userState(xbox::services::presence::user_presence_state::unknown), + m_xboxUserId(0) +{ +} + +social_manager_presence_record::social_manager_presence_record( + _In_ const xbox::services::presence::presence_record& presenceRecord + ) +{ + m_userState = presenceRecord.user_state(); + m_xboxUserId = utils::string_t_to_uint64(presenceRecord.xbox_user_id()); + + uint32_t counter = 0; + for (auto& deviceRecord : presenceRecord.presence_device_records()) + { + for (auto& titleRecord : deviceRecord.presence_title_records()) + { + m_presenceVec[counter] = social_manager_presence_title_record(titleRecord, deviceRecord.device_type()); + if (counter == NUM_PRESENCE_RECORDS - 1) + { + break; + } + ++counter; + } + } +} + +xbox::services::presence::user_presence_state +social_manager_presence_record::user_state() const +{ + return m_userState; +} + +bool +social_manager_presence_record::is_user_playing_title( + _In_ uint32_t titleId + ) const +{ + for (uint32_t i = 0; i < NUM_PRESENCE_RECORDS; ++i) + { + auto& presenceRecord = m_presenceVec[i]; + if (!presenceRecord._Is_null() && presenceRecord.title_id() == titleId) + { + return true; + } + } + + return false; +} + +xbox_live_result +social_manager_presence_record::_Deserialize( + _In_ const web::json::value& json, + _Inout_ std::error_code& errc + ) +{ + if (json.is_null()) return social_manager_presence_record(); + + social_manager_presence_record returnObject; + returnObject.m_userState = user_presence_state::offline; + + auto presenceDetailsJson = utils::extract_json_field( + json, + _T("presenceDetails"), + errc, + false + ); + + auto presenceStateString = utils::extract_json_string(json, _T("presenceState"), errc); + returnObject.m_userState = presence_record::_Convert_string_to_user_presence_state(presenceStateString); + auto presenceEntries = utils::extract_json_vector( + social_manager_presence_title_record::_Deserialize, + presenceDetailsJson, + errc, + false + ); + + auto presenceSize = __min(NUM_PRESENCE_RECORDS, presenceEntries.size()); + for (uint32_t i = 0; i < presenceSize; ++i) + { + auto presenceEntry = presenceEntries[i]; + returnObject.m_presenceVec[i] = presenceEntry; + if (presenceEntry.is_title_active()) + { + returnObject.m_userState = user_presence_state::online; + } + } + + return returnObject; +} + +uint64_t social_manager_presence_record::_Xbox_user_id() const +{ + return m_xboxUserId; +} + +void +social_manager_presence_record::_Set_xbox_user_id(_In_ uint64_t xboxUserId) +{ + m_xboxUserId = xboxUserId; +} + +const std::vector +social_manager_presence_record::presence_title_records() const +{ + std::vector returnVec; + for (uint32_t i = 0; i < NUM_PRESENCE_RECORDS; ++i) + { + auto presenceRecord = m_presenceVec[i]; + if (!presenceRecord._Is_null()) + { + returnVec.push_back(presenceRecord); + } + } + + return returnVec; +} + +bool +social_manager_presence_record::_Compare( + _In_ const social_manager_presence_record& presenceRecord + ) +{ + if (presenceRecord.m_userState != m_userState) + { + return true; + } + + + for (auto& titleRecord : presenceRecord.m_presenceVec) + { + bool wasTitleFound = false; + for (auto& compareTitleRecord : m_presenceVec) + { + if (compareTitleRecord.title_id() == titleRecord.title_id() + && utils::str_icmp(compareTitleRecord.presence_text(), titleRecord.presence_text()) == 0 + && compareTitleRecord.is_title_active() == titleRecord.is_title_active() + && compareTitleRecord.is_broadcasting() == titleRecord.is_broadcasting() + ) + { + wasTitleFound = true; + } + } + + if (!wasTitleFound) + { + return true; + } + } + + return false; +} + +void +social_manager_presence_record::_Update_device( + _In_ presence_device_type deviceType, + _In_ bool isUserLoggedIn + ) +{ + bool isNull = true; + if(!isUserLoggedIn) + { + for (uint32_t i = 0; i < NUM_PRESENCE_RECORDS; ++i) + { + auto presenceTitleEntry = m_presenceVec[i]; + if (presenceTitleEntry.device_type() == deviceType) + { + m_presenceVec[i] = social_manager_presence_title_record(); + } + else + { + isNull |= presenceTitleEntry._Is_null(); + } + } + } + + if (isNull && !isUserLoggedIn) + { + m_userState = user_presence_state::offline; + } +} + +void +social_manager_presence_record::_Remove_title( + _In_ uint32_t titleId + ) +{ + for (auto i = 0; i < NUM_PRESENCE_RECORDS; ++i) + { + auto presenceEntry = m_presenceVec[i]; + if (presenceEntry.title_id() == titleId) + { + m_presenceVec[i] = social_manager_presence_title_record(); + break; + } + } +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/social_manager_presence_title_record.cpp b/Source/Services/Social/Manager/social_manager_presence_title_record.cpp new file mode 100644 index 00000000..e427243c --- /dev/null +++ b/Source/Services/Social/Manager/social_manager_presence_title_record.cpp @@ -0,0 +1,97 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" +#include "xsapi/presence.h" + +using namespace xbox::services::presence; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +social_manager_presence_title_record::social_manager_presence_title_record() : + m_titleId(0), + m_isTitleActive(false), + m_isBroadcasting(false), + m_deviceType(presence_device_type::unknown), + m_isNull(true) +{ + initialize_char_arr(m_presenceText); +} + +social_manager_presence_title_record::social_manager_presence_title_record( + _In_ const xbox::services::presence::presence_title_record& presenceTitleRecord, + _In_ presence_device_type deviceType + ) : + m_titleId(presenceTitleRecord.title_id()), + m_isBroadcasting(presenceTitleRecord.broadcast_record().start_time() != utility::datetime()), + m_isTitleActive(presenceTitleRecord.is_title_active()), + m_deviceType(deviceType), + m_isNull(false) +{ + utils::char_t_copy(m_presenceText, ARRAYSIZE(m_presenceText), presenceTitleRecord.presence().c_str()); +} + +uint32_t +social_manager_presence_title_record::title_id() const +{ + return m_titleId; +} + +bool +social_manager_presence_title_record::is_title_active() const +{ + return m_isTitleActive; +} + +const char_t* +social_manager_presence_title_record::presence_text() const +{ + return m_presenceText; +} + +bool social_manager_presence_title_record::is_broadcasting() const +{ + return m_isBroadcasting; +} + +presence_device_type +social_manager_presence_title_record::device_type() const +{ + return m_deviceType; +} + +bool +social_manager_presence_title_record::_Is_null() const +{ + return m_isNull; +} + +xbox_live_result +social_manager_presence_title_record::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return social_manager_presence_title_record(); + + social_manager_presence_title_record returnObject; + std::error_code errc; + + auto deviceString = utils::extract_json_string(json, _T("Device"), errc); + returnObject.m_deviceType = presence_device_record::_Convert_string_to_presence_device_type(deviceString); + utils::extract_json_string_to_char_t_array(json, _T("PresenceText"), errc, returnObject.m_presenceText, ARRAYSIZE(returnObject.m_presenceText)); + auto state = utils::extract_json_string(json, _T("State"), errc); + returnObject.m_isTitleActive = (!state.empty() && utils::str_icmp(state, _T("active")) == 0); + returnObject.m_titleId = utils::string_t_to_uint32(utils::extract_json_string(json, _T("TitleId"), errc)); + returnObject.m_isNull = false; + + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/social_user_group_loaded_event_args.cpp b/Source/Services/Social/Manager/social_user_group_loaded_event_args.cpp new file mode 100644 index 00000000..58716fd4 --- /dev/null +++ b/Source/Services/Social/Manager/social_user_group_loaded_event_args.cpp @@ -0,0 +1,28 @@ +///********************************************************* +/// +/// Copyright (c) Microsoft. All rights reserved. +/// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +/// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +/// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +/// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +/// +///********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +social_user_group_loaded_event_args::social_user_group_loaded_event_args( + _In_ std::shared_ptr socialUserGroup + ) : + m_socialUserGroup(socialUserGroup) +{ +} + +const std::shared_ptr& +social_user_group_loaded_event_args::social_user_group() const +{ + return m_socialUserGroup; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/title_history.cpp b/Source/Services/Social/Manager/title_history.cpp new file mode 100644 index 00000000..101557b7 --- /dev/null +++ b/Source/Services/Social/Manager/title_history.cpp @@ -0,0 +1,84 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "social_manager_internal.h" + +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +title_history::title_history() : + m_userHasPlayed(false) +{ +} + +bool +title_history::has_user_played() const +{ + return m_userHasPlayed; +} + +const utility::datetime& +title_history::last_time_user_played() const +{ + return m_lastTimeUserPlayed; +} + +bool +title_history::operator!= ( + _In_ const title_history& previousTitleHistory + ) const +{ + return ( + previousTitleHistory.m_lastTimeUserPlayed != m_lastTimeUserPlayed || + previousTitleHistory.m_titleId != m_titleId || + previousTitleHistory.m_userHasPlayed != m_userHasPlayed + ); +} + +xbox_live_result +title_history::_Deserialize( + _In_ const web::json::value& json, + _In_ std::error_code& errcOut + ) +{ + title_history returnObject; + if (json.is_null()) + { + return returnObject; + } + + std::error_code errc = xbox_live_error_code::no_error; + returnObject.m_lastTimeUserPlayed = utils::extract_json_time( + json, + _T("LastTimePlayed"), + errc + ); + if (returnObject.m_lastTimeUserPlayed.to_interval() != 0) + { + returnObject.m_userHasPlayed = true; + } + returnObject.m_titleId = utils::extract_json_int( + json, + _T("TitleId"), + errc + ); + + if (errc) + { + errcOut = errc; + } + return xbox_live_result( + returnObject, + errc + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/xbox_social_user.cpp b/Source/Services/Social/Manager/xbox_social_user.cpp new file mode 100644 index 00000000..b99d3dab --- /dev/null +++ b/Source/Services/Social/Manager/xbox_social_user.cpp @@ -0,0 +1,216 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" +#include "social_manager_internal.h" + +using namespace xbox::services; +using namespace xbox::services::presence; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +xbox_social_user::xbox_social_user() : + m_xboxUserIdAsInt(0), + m_isFavorite(false), + m_isFollowingCaller(false), + m_isFollowedByCaller(false), + m_useAvatar(false) +{ + initialize_char_arr(m_gamerscore); + initialize_char_arr(m_gamertag); + initialize_char_arr(m_xboxUserId); + initialize_char_arr(m_displayName); + initialize_char_arr(m_realName); + initialize_char_arr(m_displayPicUrlRaw); +} + +const char_t* +xbox_social_user::xbox_user_id() const +{ + return m_xboxUserId; +} + +uint64_t +xbox_social_user::_Xbox_user_id_as_integer() const +{ + return m_xboxUserIdAsInt; +} + +bool +xbox_social_user::is_favorite() const +{ + return m_isFavorite; +} + +bool +xbox_social_user::is_following_user() const +{ + return m_isFollowingCaller; +} + +bool +xbox_social_user::is_followed_by_caller() const +{ + return m_isFollowedByCaller; +} + +const char_t* +xbox_social_user::display_name() const +{ + return m_displayName; +} + +const char_t* +xbox_social_user::real_name() const +{ + return m_realName; +} + +const char_t* +xbox_social_user::display_pic_url_raw() const +{ + return m_displayPicUrlRaw; +} + +bool +xbox_social_user::use_avatar() const +{ + return m_useAvatar; +} + +const char_t* +xbox_social_user::gamerscore() const +{ + return m_gamerscore; +} + +const char_t* +xbox_social_user::gamertag() const +{ + return m_gamertag; +} + +const social_manager_presence_record& +xbox_social_user::presence_record() const +{ + return m_presenceRecord; +} + +void xbox_social_user::_Set_presence_record( + _In_ const social_manager_presence_record& presenceRecord + ) +{ + m_presenceRecord = presenceRecord; +} + +void xbox_social_user::_Set_is_followed_by_caller( + _In_ bool isFollowed + ) +{ + m_isFollowedByCaller = isFollowed; +} + +const xbox::services::social::manager::title_history& +xbox_social_user::title_history() const +{ + return m_titleHistory; +} + +const preferred_color& +xbox_social_user::preferred_color() const +{ + return m_preferredColor; +} + +change_list_enum xbox_social_user::_Compare( + _In_ const xbox_social_user& previous, + _In_ const xbox_social_user& current + ) +{ + change_list_enum changeResult = change_list_enum::no_change; + + if ( + utils::str_icmp(previous.m_gamerscore, current.m_gamerscore) != 0 || + previous.m_titleHistory != current.m_titleHistory || + utils::str_icmp(previous.m_displayPicUrlRaw, current.m_displayPicUrlRaw) != 0 || + previous.m_useAvatar != current.m_useAvatar || + utils::str_icmp(previous.m_gamertag, current.m_gamertag) != 0 || + utils::str_icmp(previous.m_displayName, current.m_displayName) != 0 || + utils::str_icmp(previous.m_realName, current.m_realName) != 0 || + previous.m_preferredColor != current.m_preferredColor + ) + { + changeResult = static_cast(changeResult | change_list_enum::profile_change); + } + + if ( + previous.m_isFollowedByCaller != current.m_isFollowedByCaller || + previous.m_isFollowingCaller != current.m_isFollowingCaller || + previous.m_isFavorite != current.m_isFavorite + ) + { + changeResult = static_cast(changeResult | change_list_enum::social_relationship_change); + } + + return changeResult; +} + +xbox_live_result +xbox_social_user::_Deserialize( + _In_ const web::json::value& json + ) +{ + xbox_social_user returnObject; + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + utils::extract_json_string_to_char_t_array(json, _T("xuid"), errc, returnObject.m_xboxUserId, ARRAYSIZE(returnObject.m_xboxUserId)); + returnObject.m_xboxUserIdAsInt = utils::string_t_to_uint64(returnObject.m_xboxUserId); + returnObject.m_isFavorite = utils::extract_json_bool(json, _T("isFavorite"), errc); + returnObject.m_isFollowedByCaller = utils::extract_json_bool(json, _T("isFollowedByCaller"), errc); + returnObject.m_isFollowingCaller = utils::extract_json_bool(json, _T("isFollowingCaller"), errc); + utils::extract_json_string_to_char_t_array(json, _T("displayName"), errc, returnObject.m_displayName, ARRAYSIZE(returnObject.m_displayName)); + utils::extract_json_string_to_char_t_array(json, _T("realName"), errc, returnObject.m_realName, ARRAYSIZE(returnObject.m_realName)); + utils::extract_json_string_to_char_t_array(json, _T("displayPicRaw"), errc, returnObject.m_displayPicUrlRaw, ARRAYSIZE(returnObject.m_displayPicUrlRaw)); + returnObject.m_useAvatar = utils::extract_json_bool(json, _T("useAvatar"), errc); + utils::extract_json_string_to_char_t_array(json, _T("gamertag"), errc, returnObject.m_gamertag, ARRAYSIZE(returnObject.m_gamertag)); + utils::extract_json_string_to_char_t_array(json, _T("gamerScore"), errc, returnObject.m_gamerscore, ARRAYSIZE(returnObject.m_gamerscore)); + + returnObject.m_presenceRecord = social_manager_presence_record::_Deserialize( + json, + errc + ).payload(); + + returnObject.m_presenceRecord._Set_xbox_user_id(returnObject.m_xboxUserIdAsInt); + + returnObject.m_preferredColor = preferred_color::_Deserialize( + utils::extract_json_field( + json, + _T("preferredColor"), + errc, + false + ), + errc + ).payload(); + + returnObject.m_titleHistory = title_history::_Deserialize( + utils::extract_json_field( + json, + _T("titleHistory"), + errc, + false + ), + errc + ).payload(); + + return returnObject; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END diff --git a/Source/Services/Social/Manager/xbox_social_user_group.cpp b/Source/Services/Social/Manager/xbox_social_user_group.cpp new file mode 100644 index 00000000..aafe889d --- /dev/null +++ b/Source/Services/Social/Manager/xbox_social_user_group.cpp @@ -0,0 +1,531 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" +#include "social_manager_internal.h" +#include "xsapi/presence.h" + +using namespace xbox::services::presence; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +xbox_social_user_group::xbox_social_user_group( + _In_ string_t viewHash, + _In_ presence_filter presenceFilter, + _In_ relationship_filter relationshipFilter, + _In_ uint32_t titleId, + _In_ xbox_live_user_t xboxLiveUser + ) : + m_viewHash(std::move(viewHash)), + m_presenceFilter(presenceFilter), + m_relationshipFilter(relationshipFilter), + m_titleId(titleId), + m_xboxLiveUser(xboxLiveUser), + m_userGroupType(social_user_group_type::filter_type), + m_detailLevel(social_manager_extra_detail_level::no_extra_detail), + m_needsUpdate(true) +{ +} + +xbox_social_user_group::xbox_social_user_group( + _In_ string_t viewHash, + _In_ std::vector userList, + _In_ xbox_live_user_t xboxLiveUser + ) : + m_viewHash(std::move(viewHash)), + m_xboxLiveUser(std::move(xboxLiveUser)), + m_userGroupType(social_user_group_type::user_list_type), + m_presenceFilter(presence_filter::unknown), + m_relationshipFilter(relationship_filter::friends), + m_detailLevel(social_manager_extra_detail_level::no_extra_detail), + m_titleId(0), + m_needsUpdate(true) +{ + for (auto& user : userList) + { + uint64_t id = utils::string_t_to_uint64(user.c_str()); + if (id == 0) + { + LOG_ERROR("Invalid user"); + continue; + } + + m_userUpdateListString.push_back(user.c_str()); + m_userUpdateListInt.push_back(id); + } +} + +social_user_group_type +xbox_social_user_group::social_user_group_type() +{ + std::lock_guard lock(m_groupMutex); + return m_userGroupType; +} + +const std::vector& +xbox_social_user_group::users_tracked_by_social_user_group() +{ + std::lock_guard lock(m_groupMutex); + return m_userUpdateListString; +} + +const xbox_live_user_t& +xbox_social_user_group::local_user() +{ + std::lock_guard lock(m_groupMutex); + return m_xboxLiveUser; +} + +void +xbox_social_user_group::destroy() +{ + m_userUpdateListInt.clear(); + m_userGroupVector.clear(); + m_userUpdateListString.clear(); +} + +const std::vector& +xbox_social_user_group::tracking_users() +{ + std::lock_guard lock(m_groupMutex); + return m_userUpdateListInt; +} + +void xbox_social_user_group::update_view( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& snapshotList, + _In_ const std::vector& socialEvents + ) +{ + std::lock_guard lock(m_groupMutex); + if (m_userGroupType == social_user_group_type::filter_type) + { + filter_list( + snapshotList, + socialEvents + ); + } + else if (m_userGroupType == social_user_group_type::user_list_type) + { + if (m_userGroupVector.empty() || m_userGroupVector.size() != m_userUpdateListInt.size() || m_needsUpdate) + { + m_userGroupVector.clear(); + for (auto userUpdateInt : m_userUpdateListInt) + { + if (snapshotList.find(userUpdateInt) != snapshotList.end()) + { + auto socialUser = snapshotList.at(userUpdateInt).socialUser; + if (socialUser != nullptr) + { + m_userGroupVector.push_back(socialUser); + } + } + } + } + else + { + for (auto i = m_userGroupVector.begin(); i < m_userGroupVector.end(); ++i) + { + if (*i == nullptr) + { + continue; + } + auto user = *i; + auto userIter = snapshotList.find(user->_Xbox_user_id_as_integer()); + if (userIter != snapshotList.end()) + { + *i = userIter->second.socialUser; + } + } + } + } + + m_needsUpdate = false; +} + +void +xbox_social_user_group::initialize_filter_list( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& users + ) +{ + std::lock_guard lock(m_groupMutex); + std::vector resultVec; + for (auto& userPairMap : users) + { + auto user = userPairMap.second.socialUser; + if (user == nullptr) + { + continue; + } + if ((m_relationshipFilter == relationship_filter::favorite && user->is_favorite()) || + (m_relationshipFilter == relationship_filter::friends && user->is_followed_by_caller()) + ) + { + bool userValid = get_presence_filter_result( + user, + m_presenceFilter + ); + + if (userValid) + { + m_userUpdateListInt.push_back(userPairMap.first); + m_userGroupVector.push_back(user); + + m_userUpdateListString.push_back(userPairMap.second.socialUser->xbox_user_id()); + } + } + } +} + +void +xbox_social_user_group::remove_users( + _In_ const std::vector& usersToRemove + ) +{ + for (auto& userRemovalStruct : usersToRemove) + { + for (auto userUpdateIter = m_userUpdateListString.begin(); userUpdateIter != m_userUpdateListString.end(); ++userUpdateIter) + { + const char_t* xuid = userUpdateIter->xbox_user_id(); + if (utils::char_t_cmp(xuid, userRemovalStruct.xuidContainer.xbox_user_id()) == 0) + { + m_userUpdateListString.erase(userUpdateIter); + break; + } + } + for (auto userUpdateIter = m_userGroupVector.begin(); userUpdateIter != m_userGroupVector.end(); ++userUpdateIter) + { + auto xuid = (*userUpdateIter)->_Xbox_user_id_as_integer(); + if (xuid == userRemovalStruct.xuidNum) + { + m_userGroupVector.erase(userUpdateIter); + break; + } + } + for (auto userUpdateIter = m_userUpdateListInt.begin(); userUpdateIter != m_userUpdateListInt.end(); ++userUpdateIter) + { + auto xuidAsInt = *userUpdateIter; + if (xuidAsInt == userRemovalStruct.xuidNum) + { + m_userUpdateListInt.erase(userUpdateIter); + break; + } + } + } +} + +void +xbox_social_user_group::filter_list( + _In_ const xsapi_internal_unordered_map(uint64_t, xbox_social_user_context)& snapshotList, + _In_ const std::vector& socialEvents + ) +{ + std::vector refilterList; + std::vector addedList; + std::vector removeList; + std::vector removalStructList; + + for (auto& evt : socialEvents) + { + switch (evt.event_type()) + { + case social_event_type::presence_changed: + case social_event_type::profiles_changed: + case social_event_type::social_relationships_changed: + refilterList.insert(refilterList.end(), evt.users_affected().begin(), evt.users_affected().end()); + break; + case social_event_type::users_added_to_social_graph: + addedList.insert(addedList.end(), evt.users_affected().begin(), evt.users_affected().end()); + break; + case social_event_type::users_removed_from_social_graph: + removeList.insert(removeList.end(), evt.users_affected().begin(), evt.users_affected().end()); + break; + } + } + for (auto& userStr : refilterList) + { + uint64_t userInt = utils::string_t_to_uint64(userStr.xbox_user_id()); + auto userPair = snapshotList.find(userInt); + if (userPair == snapshotList.end()) + { + continue; + } + + auto user = userPair->second.socialUser; + if ((m_relationshipFilter == relationship_filter::favorite && user->is_favorite()) || + (m_relationshipFilter == relationship_filter::friends && user->is_followed_by_caller()) + ) + { + bool userValid = get_presence_filter_result( + user, + m_presenceFilter + ); + + if (!userValid) + { + xbox_removal_struct xboxRemovalStruct; + xboxRemovalStruct.xuidContainer = userStr.xbox_user_id(); + xboxRemovalStruct.xuidNum = userInt; + + removalStructList.push_back(xboxRemovalStruct); + } + else + { + // check if added + bool wasFound = false; + for (auto& updateUserInt : m_userUpdateListInt) + { + if (updateUserInt == userInt) + { + wasFound = true; + break; + } + } + + if (!wasFound) + { + m_userUpdateListString.push_back(userStr.xbox_user_id()); + m_userUpdateListInt.push_back(userInt); + m_userGroupVector.push_back(user); + } + } + } + } + + for (auto& userStr : addedList) + { + uint64_t userInt = utils::string_t_to_uint64(userStr.xbox_user_id()); + auto userPair = snapshotList.find(userInt); + if (userPair == snapshotList.end()) + { + continue; + } + + auto user = userPair->second.socialUser; + if (user == nullptr) + { + continue; + } + if ((m_relationshipFilter == relationship_filter::favorite && user->is_favorite()) || + (m_relationshipFilter == relationship_filter::friends && user->is_followed_by_caller()) + ) + { + bool userValid = get_presence_filter_result( + user, + m_presenceFilter + ); + + if (userValid) + { + m_userUpdateListString.push_back(userStr.xbox_user_id()); + m_userUpdateListInt.push_back(userInt); + m_userGroupVector.push_back(user); + } + } + } + + for (auto& userStr : removeList) + { + uint64_t userInt = utils::string_t_to_uint64(userStr.xbox_user_id()); + xbox_removal_struct xboxRemovalStruct; + + xboxRemovalStruct.xuidContainer = userStr; + xboxRemovalStruct.xuidNum = userInt; + + removalStructList.push_back(xboxRemovalStruct); + } + + if (!removalStructList.empty()) + { + remove_users(removalStructList); + } + + m_userGroupVector.clear(); + for (auto& userInt : m_userUpdateListInt) + { + auto userIter = snapshotList.find(userInt); + if (userIter != snapshotList.end()) + { + auto& user = userIter->second.socialUser; + m_userGroupVector.push_back(user); + } + } +} + +const std::vector& +xbox_social_user_group::users() +{ + std::lock_guard lock(m_groupMutex); + return m_userGroupVector; +} + +user_group_status_change +xbox_social_user_group::_Update_users_in_group( + _In_ const std::vector& userList + ) +{ + xsapi_internal_unordered_map(uint64_t, uint32_t) changeMap; + xsapi_internal_vector(uint64_t) userIdList; + userIdList.reserve(userList.size()); + + user_group_status_change changeGroups; + for (auto& user : userList) + { + uint64_t id = utils::string_t_to_uint64(user.c_str()); + + if (id == 0) + { + LOG_ERROR("Invalid user"); + continue; + } + + userIdList.push_back(id); + bool userFound = false; + for (auto userInt : m_userUpdateListInt) + { + if (userInt == id) + { + userFound = true; + break; + } + } + if (userFound) + { + continue; + } + + changeGroups.addGroup.push_back(user); + m_userUpdateListInt.push_back(id); + + m_userUpdateListString.push_back(user.c_str()); + } + + std::vector userCompareList(m_userUpdateListInt); + for (auto updateUser : userCompareList) + { + bool wasFound = false; + for (auto userId : userIdList) + { + if (userId == updateUser) + { + wasFound = true; + } + } + + if (!wasFound) + { + changeGroups.removeGroup.push_back(updateUser); + + for (std::vector::iterator i = m_userUpdateListInt.begin(); i != m_userUpdateListInt.end(); ++i) + { + if (*i == updateUser) + { + m_userUpdateListInt.erase(i); + break; + } + } + + for (auto i = m_userUpdateListString.begin(); i != m_userUpdateListString.end(); ++i) + { + stringstream_t str; + str << updateUser; + if (utils::str_icmp(i->xbox_user_id(), str.str()) == 0) + { + m_userUpdateListString.erase(i); + break; + } + } + } + } + + if (!changeGroups.addGroup.empty() || !changeGroups.removeGroup.empty()) + { + m_needsUpdate = true; + } + return changeGroups; +} + +const string_t& +xbox_social_user_group::hash() const +{ + return m_viewHash; +} + +bool +xbox_social_user_group::needs_update() +{ + std::lock_guard lock(m_groupMutex); + return m_needsUpdate; +} + +xbox_live_result +xbox_social_user_group::get_copy_of_users( + _Inout_ std::vector& socialUserVector + ) +{ + std::lock_guard lock(social_manager::get_singleton_instance()->m_socialMangerLock); + std::lock_guard socialGroupLock(m_groupMutex); + + socialUserVector.clear(); + socialUserVector.reserve(m_userGroupVector.size()); + for (auto& user : m_userGroupVector) + { + socialUserVector.push_back(*user); + } + + return xbox_live_result(); +} + +bool +xbox_social_user_group::get_presence_filter_result( + _In_ const xbox_social_user* user, + _In_ presence_filter presenceFilter + ) const +{ + switch (presenceFilter) + { + case presence_filter::all: + return true; + case presence_filter::all_offline: + return user->presence_record().user_state() == user_presence_state::offline; + case presence_filter::all_online: + return user->presence_record().user_state() == user_presence_state::online; + case presence_filter::all_title: + return user->title_history().has_user_played(); + case presence_filter::title_offline: + return user->presence_record().user_state() == user_presence_state::offline && user->title_history().has_user_played(); + case presence_filter::title_online: + return user->presence_record().is_user_playing_title(m_titleId); + default: + return false; + } +} + +std::vector +xbox_social_user_group::get_users_from_xbox_user_ids( + _In_ const std::vector& xboxUserIds + ) +{ + std::vector returnVec; + std::lock_guard lock(m_groupMutex); + for (auto& user : m_userGroupVector) + { + for (auto searchUser : xboxUserIds) + { + if (utils::char_t_cmp(searchUser.xbox_user_id(), user->xbox_user_id()) == 0) + { + returnVec.push_back(user); + } + } + } + + return returnVec; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/Manager/xbox_user_id_container.cpp b/Source/Services/Social/Manager/xbox_user_id_container.cpp new file mode 100644 index 00000000..ae54f2ba --- /dev/null +++ b/Source/Services/Social/Manager/xbox_user_id_container.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_BEGIN + +xbox_user_id_container::xbox_user_id_container() +{ + initialize_char_arr(m_xboxUserId); +} + +xbox_user_id_container::xbox_user_id_container( + _In_ const char_t* xboxUserId + ) +{ + utils::char_t_copy(m_xboxUserId, ARRAYSIZE(m_xboxUserId), xboxUserId); +} + +const char_t* +xbox_user_id_container::xbox_user_id() const +{ + return m_xboxUserId; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/PresenceFilter_WinRT.h b/Source/Services/Social/WinRT/PresenceFilter_WinRT.h new file mode 100644 index 00000000..355987b1 --- /dev/null +++ b/Source/Services/Social/WinRT/PresenceFilter_WinRT.h @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// The filter level of information +/// Title will only show users associated with a particular title +/// +public enum class PresenceFilter +{ + /// Unknown + Unknown = xbox::services::social::manager::presence_filter::unknown, + + /// Is currently playing current title and is online + TitleOnline = xbox::services::social::manager::presence_filter::title_online, + + /// Has played this title and is offline + TitleOffline = xbox::services::social::manager::presence_filter::title_offline, + + /// Everyone currently online + AllOnline = xbox::services::social::manager::presence_filter::all_online, + + /// Everyone currently offline + AllOffline = xbox::services::social::manager::presence_filter::all_offline, + + /// Everyone who has played or is playing the title + AllTitle = xbox::services::social::manager::presence_filter::all_title, + + /// Everyone + All = xbox::services::social::manager::presence_filter::all +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/ProfileService_WinRT.cpp b/Source/Services/Social/WinRT/ProfileService_WinRT.cpp new file mode 100644 index 00000000..85d18261 --- /dev/null +++ b/Source/Services/Social/WinRT/ProfileService_WinRT.cpp @@ -0,0 +1,94 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ProfileService_winrt.h" +#include "Utils_WinRT.h" + +using namespace pplx; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace Platform::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::social; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +ProfileService::ProfileService( + _In_ profile_service cppObj + ): + m_cppObj(std::move(cppObj)) +{ +} + +IAsyncOperation^ +ProfileService::GetUserProfileAsync( + _In_ String^ xboxUserId + ) +{ + auto task = m_cppObj.get_user_profile( + STRING_T_FROM_PLATFORM_STRING(xboxUserId) + ) + .then([](xbox::services::xbox_live_result cppUserProfile) + { + THROW_HR_IF_ERR(cppUserProfile.err()); + return ref new XboxUserProfile(cppUserProfile.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +ProfileService::GetUserProfilesAsync( + _In_ IVectorView^ xboxUserIds + ) +{ + std::vector vecXboxUserIds = UtilsWinRT::CovertVectorViewToStdVectorString(xboxUserIds); + + auto task = m_cppObj.get_user_profiles(vecXboxUserIds) + .then([](xbox::services::xbox_live_result> cppUserProfiles) + { + THROW_HR_IF_ERR(cppUserProfiles.err()); + Vector^ responseVector = ref new Vector(); + const auto& result = cppUserProfiles.payload(); + for (auto& cppUserProfile : result) + { + auto userProfile = ref new XboxUserProfile(cppUserProfile); + responseVector->Append(userProfile); + } + return responseVector->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +ProfileService::GetUserProfilesForSocialGroupAsync( + _In_ Platform::String^ socialGroup + ) +{ + auto task = m_cppObj.get_user_profiles_for_social_group(STRING_T_FROM_PLATFORM_STRING(socialGroup)) + .then([](xbox_live_result> cppUserProfileList) + { + THROW_IF_ERR(cppUserProfileList); + Vector^ responseVector = ref new Vector(); + for (auto& cppUserProfile : cppUserProfileList.payload()) + { + XboxUserProfile^ userProfile = ref new XboxUserProfile(cppUserProfile); + responseVector->Append(userProfile); + } + return responseVector->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/ProfileService_WinRT.h b/Source/Services/Social/WinRT/ProfileService_WinRT.h new file mode 100644 index 00000000..0ce17f55 --- /dev/null +++ b/Source/Services/Social/WinRT/ProfileService_WinRT.h @@ -0,0 +1,71 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "XboxUserProfile_winrt.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN +/// +/// Services that manage user profile. +/// + +public ref class ProfileService sealed +{ +public: + /// + /// Gets a user profile for a specific Xbox user. + /// + /// The Xbox User ID of the user to get the profile for. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is an XboxUserProfile object. + /// + /// Calls V2 GET /users/batch/profile/settings + Windows::Foundation::IAsyncOperation^ GetUserProfileAsync( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Gets one or more user profiles for a collection of specified Xbox users. + /// + /// The collection of Xbox User IDs of the users to get profiles for + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is a collection of XboxUserProfile objects. + /// + /// Calls V2 GET /users/batch/profile/settings + Windows::Foundation::IAsyncOperation^>^ GetUserProfilesAsync( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds + ); + + /// + /// Gets user profiles for users in a specified social group. + /// + /// The name of the social group of users to search. + /// See Microsoft::Xbox::Services::Social::SocialGroupConstants for the latest options. + /// + /// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. + /// The result of the asynchronous operation is a collection of XboxUserProfile objects. + /// + /// Calls V2 GET /users/{userId}/profile/settings/people/{socialGroup} + Windows::Foundation::IAsyncOperation^>^ GetUserProfilesForSocialGroupAsync( + _In_ Platform::String^ socialGroup + ); + +internal: + ProfileService( + _In_ xbox::services::social::profile_service cppObj + ); + +private: + xbox::services::social::profile_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/RelationshipFilter_WinRT.h b/Source/Services/Social/WinRT/RelationshipFilter_WinRT.h new file mode 100644 index 00000000..a6e90542 --- /dev/null +++ b/Source/Services/Social/WinRT/RelationshipFilter_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social_manager.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_BEGIN + +/// +/// Possible relationship types to filter by +/// +public enum class RelationshipFilter +{ + /// Friends of the user (user is following) + Friends = xbox::services::social::manager::relationship_filter::friends, + + /// Favorites of the user + Favorite = xbox::services::social::manager::relationship_filter::favorite +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_MANAGER_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/ReputationFeedbackType_WinRT.h b/Source/Services/Social/WinRT/ReputationFeedbackType_WinRT.h new file mode 100644 index 00000000..33f1a950 --- /dev/null +++ b/Source/Services/Social/WinRT/ReputationFeedbackType_WinRT.h @@ -0,0 +1,144 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi\social.h" +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +/// Defines values for reputation feedback types. +public enum class ReputationFeedbackType +{ + /// + /// Titles that are able to automatically determine that a user kills a teammate + /// may send this feedback without user intervention. + /// + FairPlayKillsTeammates = xbox::services::social::reputation_feedback_type::fair_play_kills_teammates, + + /// + /// Titles that are able to automatically determine that a user is cheating + /// may send this feedback without user intervention. + /// + FairPlayCheater = xbox::services::social::reputation_feedback_type::fair_play_cheater, + + /// + /// Titles that are able to automatically determine that a user has tampered with on-disk content + /// may send this feedback without user intervention. + /// + FairPlayTampering = xbox::services::social::reputation_feedback_type::fair_play_tampering, + + /// + /// Titles that are able to automatically determine that a user quit a game early + /// may send this feedback without user intervention. + /// + FairPlayQuitter = xbox::services::social::reputation_feedback_type::fair_play_quitter, + + /// + /// When a user is voted out of a game (kicked), titles + /// may send this feedback without user intervention. + /// + FairPlayKicked = xbox::services::social::reputation_feedback_type::fair_play_kicked, + + /// + /// Titles that allow users to report innappropriate video communications + /// may send this feedback. + /// + CommunicationsInappropriateVideo = xbox::services::social::reputation_feedback_type::communications_inappropiate_video, + + /// + /// Titles that allow users to report innappropriate voice communications + /// may send this feedback. + /// + CommunicationsAbusiveVoice = xbox::services::social::reputation_feedback_type::communications_abusive_voice, + + /// + /// Titles that allow users to report innappropriate user generated content + /// may send this feedback. + /// + InappropriateUserGeneratedContent = xbox::services::social::reputation_feedback_type::inappropiate_user_generated_content, + + /// + /// Titles that allow users to vote on a most valuable player at the end of a multiplayer session + /// may send this feedback. + /// + PositiveSkilledPlayer = xbox::services::social::reputation_feedback_type::positive_skilled_player, + + /// + /// Titles that allow users to submit positive feedback on helpful fellow players + /// may send this feedback. + /// + PositiveHelpfulPlayer = xbox::services::social::reputation_feedback_type::positive_helpful_player, + + /// + /// Titles that allow users to submit positive feedback on shared user generated content + /// may send this feedback. + /// + PositiveHighQualityUserGeneratedContent = xbox::services::social::reputation_feedback_type::positive_high_quality_user_generated_content, + + /// + /// Titles that allow users to report phishing message may send this feedback. + /// + CommsPhishing = xbox::services::social::reputation_feedback_type::comms_phishing, + + /// + /// Titles that allow users to report communication based on a picture may send this feedback. + /// + CommsPictureMessage = xbox::services::social::reputation_feedback_type::comms_picture_message, + + /// + /// Titles that allow users to report spam messages may send this feedback. + /// + CommsSpam = xbox::services::social::reputation_feedback_type::comms_spam, + + /// + /// Titles that allow users to report text messages may send this feedback. + /// + CommsTextMessage = xbox::services::social::reputation_feedback_type::comms_text_message, + + /// + /// Titles that allow users to report voice messages may send this feedback. + /// + CommsVoiceMessage = xbox::services::social::reputation_feedback_type::comms_voice_message, + + /// + /// Titles that allow users to report voice messages may send this feedback. + /// + FairPlayConsoleBanRequest = xbox::services::social::reputation_feedback_type::fair_play_console_ban_request, + + /// + /// Titles that allow users to report if determine if a user stands idle on purpose in a game, usually round after round, may send this feedback. + /// + FairPlayIdler = xbox::services::social::reputation_feedback_type::fair_play_idler, + + /// + /// Titles that report a recommendation to ban a user from Xbox Live may send this feedback. + /// + FairPlayUserBanRequest = xbox::services::social::reputation_feedback_type::fair_play_user_ban_request, + + /// + /// Titles that allow users to report inappropriate gamer picture may send this feedback. + /// + UserContentGamerpic = xbox::services::social::reputation_feedback_type::user_content_gamerpic, + + /// + /// Titles that allow users to report inappropriate biography and other personal information may send this feedback. + /// + UserContentPersonalinfo = xbox::services::social::reputation_feedback_type::user_content_personalinfo, + + /// + /// Titles that allow users to report unsporting behavior may send this feedback. + /// + FairPlayUnsporting = xbox::services::social::reputation_feedback_type::fair_play_unsporting, + + /// + /// Titles that allow users to report leaderboard cheating may send this feedback. + /// + FairPlayLeaderboardCheater = xbox::services::social::reputation_feedback_type::fair_play_leaderboard_cheater +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END diff --git a/Source/Services/Social/WinRT/ReputationService_WinRT.cpp b/Source/Services/Social/WinRT/ReputationService_WinRT.cpp new file mode 100644 index 00000000..79b5967a --- /dev/null +++ b/Source/Services/Social/WinRT/ReputationService_WinRT.cpp @@ -0,0 +1,108 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ReputationService_WinRT.h" +#include "Utils_WinRT.h" +#include "utils.h" + +using namespace pplx; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace Platform::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::social; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +ReputationService::ReputationService( + _In_ reputation_service cppObj + ) : + m_cppObj(cppObj) +{ +} + +IAsyncAction^ +ReputationService::SubmitReputationFeedbackAsync( + _In_ Platform::String^ xboxUserId, + _In_ ReputationFeedbackType reputationFeedbackType, + _In_opt_ Platform::String^ sessionName, + _In_opt_ Platform::String^ reasonMessage, + _In_opt_ Platform::String^ evidenceResourceId + ) +{ + auto task = m_cppObj.submit_reputation_feedback( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + static_cast(reputationFeedbackType), + STRING_T_FROM_PLATFORM_STRING(sessionName), + STRING_T_FROM_PLATFORM_STRING(reasonMessage), + STRING_T_FROM_PLATFORM_STRING(evidenceResourceId) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncAction^ +ReputationService::SubmitBatchReputationFeedbackAsync( + _In_ IVectorView^ feedbackItems + ) +{ + auto task = m_cppObj.submit_batch_reputation_feedback( + UtilsWinRT::CreateStdVectorObjectFromPlatformVectorObj(feedbackItems) + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + + +ReputationFeedbackItem::ReputationFeedbackItem() +{ +} + +ReputationFeedbackItem::ReputationFeedbackItem( + _In_ Platform::String^ xboxUserId, + _In_ ReputationFeedbackType reputationFeedbackType, + _In_ Xbox::Services::Multiplayer::MultiplayerSessionReference^ sessionRef, + _In_ Platform::String^ reasonMessage, + _In_ Platform::String^ evidenceResourceId + ) : + m_cppObj( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + static_cast(reputationFeedbackType), + sessionRef == nullptr ? xbox::services::multiplayer::multiplayer_session_reference() : sessionRef->GetCppObj(), + STRING_T_FROM_PLATFORM_STRING(reasonMessage), + STRING_T_FROM_PLATFORM_STRING(evidenceResourceId) + ) +{ + m_sessionRef = sessionRef; +} + +Xbox::Services::Multiplayer::MultiplayerSessionReference^ ReputationFeedbackItem::SessionReference::get() +{ + return m_sessionRef; +} + +xbox::services::social::reputation_feedback_item ReputationFeedbackItem::GetCppObj() const +{ + return m_cppObj; +} + + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/ReputationService_WinRT.h b/Source/Services/Social/WinRT/ReputationService_WinRT.h new file mode 100644 index 00000000..8f0716cc --- /dev/null +++ b/Source/Services/Social/WinRT/ReputationService_WinRT.h @@ -0,0 +1,119 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "Macros_WinRT.h" +#include "ReputationFeedbackType_WinRT.h" +#include "MultiplayerSessionReference_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +/// +/// Represents the parameters for submitting reputation feedback on a user +/// +public ref class ReputationFeedbackItem sealed +{ +public: + ReputationFeedbackItem(); + + /// + /// Construct a ReputationFeedbackItem object + /// + /// The Xbox User ID of the user that reputation feedback is being submitted on. + /// The reputation feedback type being submitted. + /// The session reference of the multiplayer session directory session the user is sending feedback from. (Optional) + /// User supplied text added to explain the reason for the feedback. (Optional) + /// The Id of a resource that can be used as evidence for the feedback. Example: the Id of a video file. (Optional) + ReputationFeedbackItem( + _In_ Platform::String^ xboxUserId, + _In_ ReputationFeedbackType reputationFeedbackType, + _In_ Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ sessionReference, + _In_ Platform::String^ reasonMessage, + _In_ Platform::String^ evidenceResourceId + ); + + /// + /// The Xbox User ID of the user that reputation feedback is being submitted on. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The reputation feedback type being submitted. + /// + DEFINE_PROP_GET_ENUM_OBJ(FeedbackType, feedback_type, ReputationFeedbackType); + + /// + /// The reference to the multiplayer session directory session the user is sending feedback from. + /// + property Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ SessionReference { Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ get(); } + + /// + /// User supplied text added to explain the reason for the feedback. + /// + DEFINE_PROP_GET_STR_OBJ(ReasonMessage, reason_message); + + /// + /// The Id of a resource that can be used as evidence for the feedback. Example: the Id of a video file. + /// + DEFINE_PROP_GET_STR_OBJ(EvidenceResourceId, evidence_resource_id); + +internal: + xbox::services::social::reputation_feedback_item GetCppObj() const; + +private: + Microsoft::Xbox::Services::Multiplayer::MultiplayerSessionReference^ m_sessionRef; + xbox::services::social::reputation_feedback_item m_cppObj; +}; + + +/// +/// Provides access methods for the reputation service. +/// +public ref class ReputationService sealed +{ +public: + /// + /// Submits reputation feedback on the specified user. + /// + /// The Xbox User ID of the user that reputation feedback is being submitted on. + /// The reputation feeback type being submitted. + /// The name of the multiplayer session directory session the user is sending feedback from. (Optional) + /// User supplied text added to explain the reason for the feedback. (Optional) + /// The Id of a resource that can be used as evidence for the feedback. Example: the Id of a video file. (Optional) + /// The async object for notifying when the operation has been completed. + /// Calls V100 POST /users/xuid({xuid})/feedback + Windows::Foundation::IAsyncAction^ SubmitReputationFeedbackAsync( + _In_ Platform::String^ xboxUserId, + _In_ ReputationFeedbackType reputationFeedbackType, + _In_opt_ Platform::String^ sessionName, + _In_opt_ Platform::String^ reasonMessage, + _In_opt_ Platform::String^ evidenceResourceId + ); + + /// + /// Submits batch reputation feedback on the specified users. + /// + /// A vector of reputation_feedback_item objects to submit reputation feedback on. + /// The async object for notifying when the operation has been completed. + /// Calls V101 POST /users/batchfeedback + Windows::Foundation::IAsyncAction^ SubmitBatchReputationFeedbackAsync( + _In_ Windows::Foundation::Collections::IVectorView^ feedbackItems + ); + +internal: + ReputationService( + _In_ xbox::services::social::reputation_service cppObj + ); + +private: + xbox::services::social::reputation_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialGroupConstants_WinRT.h b/Source/Services/Social/WinRT/SocialGroupConstants_WinRT.h new file mode 100644 index 00000000..6a6e91bb --- /dev/null +++ b/Source/Services/Social/WinRT/SocialGroupConstants_WinRT.h @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi\social.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +/// +/// Contains constant data about social groups. +/// + +public ref class SocialGroupConstants sealed +{ +public: + + /// + /// A string describing the social group's favorites. + /// + static property Platform::String^ Favorite + { + Platform::String^ get() + { + return ref new Platform::String(xbox::services::social::social_group_constants::favorite().c_str()); + } + } + + /// + /// A string describing the people in the social group. + /// + + static property Platform::String^ People + { + Platform::String^ get() + { + return ref new Platform::String(xbox::services::social::social_group_constants::people().c_str()); + } + } +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialNotificationType_WinRT.h b/Source/Services/Social/WinRT/SocialNotificationType_WinRT.h new file mode 100644 index 00000000..3e583bc7 --- /dev/null +++ b/Source/Services/Social/WinRT/SocialNotificationType_WinRT.h @@ -0,0 +1,37 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +public enum class SocialNotificationType +{ + /// + /// unknown + /// + Unknown = xbox::services::social::social_notification_type::unknown, + + /// + /// User(s) were added. + /// + added = xbox::services::social::social_notification_type::added, + + /// + /// User(s) data changed. + /// + changed = xbox::services::social::social_notification_type::changed, + + /// + /// User(s) were removed. + /// + removed = xbox::services::social::social_notification_type::removed +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.cpp b/Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.cpp new file mode 100644 index 00000000..616017b1 --- /dev/null +++ b/Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialRelationshipChangeEventArgs_WinRT.h" +#include "Utils_WinRT.h" + +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +SocialRelationshipChangeEventArgs::SocialRelationshipChangeEventArgs( + _In_ xbox::services::social::social_relationship_change_event_args cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_xboxUserIds = UtilsWinRT::CreatePlatformVectorFromStdVectorString(m_cppObj.xbox_user_ids())->GetView(); +} + +IVectorView^ +SocialRelationshipChangeEventArgs::XboxUserIds::get() +{ + return m_xboxUserIds; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.h b/Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.h new file mode 100644 index 00000000..956781d0 --- /dev/null +++ b/Source/Services/Social/WinRT/SocialRelationshipChangeEventArgs_WinRT.h @@ -0,0 +1,39 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social.h" +#include "SocialNotificationType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +public ref class SocialRelationshipChangeEventArgs sealed +{ +public: + /// + /// The Xbox user ID for the user who's social graph changes are being listed for. + /// + DEFINE_PROP_GET_STR_OBJ(CallerXboxUserId, caller_xbox_user_id); + + /// + /// The type of notification change. + /// + DEFINE_PROP_GET_ENUM_OBJ(SocialNotification, social_notification, Microsoft::Xbox::Services::Social::SocialNotificationType); + + property Windows::Foundation::Collections::IVectorView^ XboxUserIds { Windows::Foundation::Collections::IVectorView^ get(); } + +internal: + SocialRelationshipChangeEventArgs(_In_ xbox::services::social::social_relationship_change_event_args cppObj); + +private: + Windows::Foundation::Collections::IVectorView^ m_xboxUserIds; + xbox::services::social::social_relationship_change_event_args m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.cpp b/Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.cpp new file mode 100644 index 00000000..d023ea0c --- /dev/null +++ b/Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.cpp @@ -0,0 +1,35 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialRelationshipChangeSubscription_WinRT.h" + +using namespace Microsoft::Xbox::Services::RealTimeActivity; +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +SocialRelationshipChangeSubscription::SocialRelationshipChangeSubscription( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +RealTimeActivitySubscriptionState +SocialRelationshipChangeSubscription::State::get() +{ + return static_cast(m_cppObj->state()); +} + +std::shared_ptr +SocialRelationshipChangeSubscription::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_PRESENCE_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.h b/Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.h new file mode 100644 index 00000000..42015af8 --- /dev/null +++ b/Source/Services/Social/WinRT/SocialRelationshipChangeSubscription_WinRT.h @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social.h" +#include "RealTimeActivitySubscriptionState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +public ref class SocialRelationshipChangeSubscription sealed +{ +public: + /// + /// The current state of the subscription. + /// + property Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState State{ Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState get(); } + + /// + /// The resource uri for the request. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ResourceUri, resource_uri); + + /// + /// The unique subscription id for the request. + /// + DEFINE_PTR_PROP_GET_OBJ(SubscriptionId, subscription_id, uint32_t); + + /// + /// The Xbox user ID for the user who's social graph changes are being listed for. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + +internal: + SocialRelationshipChangeSubscription(_In_ std::shared_ptr cppObj); + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialRelationship_WinRT.h b/Source/Services/Social/WinRT/SocialRelationship_WinRT.h new file mode 100644 index 00000000..475f858d --- /dev/null +++ b/Source/Services/Social/WinRT/SocialRelationship_WinRT.h @@ -0,0 +1,29 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/social.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +/// Defines values for the {view} field +public enum class SocialRelationship +{ + /// All the people on the user's people list + All = xbox::services::social::xbox_social_relationship_filter::all, + + /// Filters to only the people on the user's people list that have the attribute "Favorite" associated with them. + Favorite = xbox::services::social::xbox_social_relationship_filter::favorite, + + /// Filters to only the people on the user's people list that are also legacy Xbox Live friends + LegacyXboxLiveFriends = xbox::services::social::xbox_social_relationship_filter::legacy_xbox_live_friends, +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END diff --git a/Source/Services/Social/WinRT/SocialService_WinRT.cpp b/Source/Services/Social/WinRT/SocialService_WinRT.cpp new file mode 100644 index 00000000..00156c28 --- /dev/null +++ b/Source/Services/Social/WinRT/SocialService_WinRT.cpp @@ -0,0 +1,177 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialService_WinRT.h" +#include "Utils_WinRT.h" +#include "XboxLiveContextSettings_WinRT.h" + +using namespace pplx; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace xbox::services::social; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +SocialService::SocialService( + _In_ social_service cppObj + ) : + m_cppObj(cppObj) +{ + m_socialRelationshipSubscriptionEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + m_socialRelationshipSubscriptionEventBind->AddSocialRelationshipSubscriptionEvent(); +} + +SocialService::~SocialService() +{ + m_socialRelationshipSubscriptionEventBind->RemoveSocialChangeSubcriptionEvent(m_cppObj); +} + +IAsyncOperation^ +SocialService::GetSocialRelationshipsAsync() +{ + return GetSocialRelationshipsAsync(SocialRelationship::All, 0, 0); +} + +IAsyncOperation^ +SocialService::GetSocialRelationshipsAsync( + _In_ SocialRelationship socialRelationshipFilter + ) +{ + return GetSocialRelationshipsAsync(socialRelationshipFilter, 0, 0); +} + +Windows::Foundation::IAsyncOperation^ +SocialService::GetSocialRelationshipsAsync( + _In_ Platform::String^ xboxUserId + ) +{ + auto task = m_cppObj.get_social_relationships(STRING_T_FROM_PLATFORM_STRING(xboxUserId)) + .then([](xbox::services::xbox_live_result cppSocialRelationshipResult) + { + THROW_IF_ERR(cppSocialRelationshipResult); + return ref new XboxSocialRelationshipResult(cppSocialRelationshipResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +SocialService::GetSocialRelationshipsAsync( + _In_ SocialRelationship socialRelationshipFilter, + _In_ uint32 startIndex, + _In_ uint32 maxItems + ) +{ + xbox_social_relationship_filter cppSocialRelationshipFilter = static_cast(socialRelationshipFilter); + auto task = m_cppObj.get_social_relationships(cppSocialRelationshipFilter, startIndex, maxItems) + .then([](xbox::services::xbox_live_result cppSocialRelationshipResult) + { + THROW_IF_ERR(cppSocialRelationshipResult); + return ref new XboxSocialRelationshipResult(cppSocialRelationshipResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +SocialRelationshipChangeSubscription^ +SocialService::SubscribeToSocialRelationshipChange( + _In_ Platform::String^ xboxUserId + ) +{ + std::shared_ptr subscription; + auto subscriptionResult = m_cppObj.subscribe_to_social_relationship_change( + STRING_T_FROM_PLATFORM_STRING(xboxUserId) + ); + + THROW_IF_ERR(subscriptionResult); + + subscription = subscriptionResult.payload(); + + return ref new SocialRelationshipChangeSubscription(subscription); +} + +void +SocialService::UnsubscribeFromSocialRelationshipChange( + _In_ SocialRelationshipChangeSubscription^ subscription + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(subscription); + + auto unsubscribeResult = m_cppObj.unsubscribe_from_social_relationship_change( + subscription->GetCppObj() + ); + + THROW_IF_ERR(unsubscribeResult); +} + +void SocialService::RaiseSocialRelationshipChange ( + _In_ SocialRelationshipChangeEventArgs^ args + ) +{ + SocialRelationshipChanged(this, args); +} + +SocialRelationshipSubscriptionEventBind::SocialRelationshipSubscriptionEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::social::social_service& cppObj + ) : + m_setting(setting), + m_cppObj(cppObj) +{ +} + +void +SocialRelationshipSubscriptionEventBind::SocialRelationshipChangeRouter( + _In_ const xbox::services::social::social_relationship_change_event_args& args + ) +{ + SocialService^ socialService = m_setting.Resolve(); + if (socialService != nullptr) + { + if (m_cppObj._Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([socialService, args]() + { + socialService->RaiseSocialRelationshipChange(ref new SocialRelationshipChangeEventArgs(args)); + })); + } + else + { + socialService->RaiseSocialRelationshipChange(ref new SocialRelationshipChangeEventArgs(args)); + } + } +} + +void +SocialRelationshipSubscriptionEventBind::RemoveSocialChangeSubcriptionEvent( + _In_ xbox::services::social::social_service& cppObj + ) +{ + cppObj.remove_social_relationship_changed_handler(m_functionContext); +} + +void SocialRelationshipSubscriptionEventBind::AddSocialRelationshipSubscriptionEvent() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_cppObj.add_social_relationship_changed_handler([thisWeakPtr](_In_ const xbox::services::social::social_relationship_change_event_args& args) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->SocialRelationshipChangeRouter(args); + } + }); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/SocialService_WinRT.h b/Source/Services/Social/WinRT/SocialService_WinRT.h new file mode 100644 index 00000000..af36184c --- /dev/null +++ b/Source/Services/Social/WinRT/SocialService_WinRT.h @@ -0,0 +1,121 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/xbox_live_context_settings.h" +#include "XboxSocialRelationshipResult_WinRT.h" +#include "SocialRelationship_WinRT.h" +#include "SocialGroupConstants_WinRT.h" +#include "SocialRelationshipChangeSubscription_WinRT.h" +#include "SocialRelationshipChangeEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +class SocialRelationshipSubscriptionEventBind : public std::enable_shared_from_this +{ +public: + SocialRelationshipSubscriptionEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::social::social_service& cppObj + ); + + void AddSocialRelationshipSubscriptionEvent(); + + void SocialRelationshipChangeRouter(_In_ const xbox::services::social::social_relationship_change_event_args& args); + + void RemoveSocialChangeSubcriptionEvent(_In_ xbox::services::social::social_service& cppObj); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + xbox::services::social::social_service m_cppObj; +}; + +/// +/// Defines access methods that return social relationship information between the user and one or more other Xbox Live users. +/// +public ref class SocialService sealed +{ +public: + /// + /// Registers for social relationship change notifications. Event handlers will receive SocialRelationshipChangeEventArgs^. + /// + event Windows::Foundation::EventHandler^ SocialRelationshipChanged; + + /// + /// Returns a XboxSocialRelationshipResult containing a the list of people that the user is connected to. + /// Defaults to filtering to PersonView.All + /// Defaults to startIndex and maxItems of 0 to return entire list if possible + /// + /// An XboxSocialRelationshipResult object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + Windows::Foundation::IAsyncOperation^ GetSocialRelationshipsAsync(); + + /// + /// Returns a XboxSocialRelationshipResult containing a the list of people that the user is connected to. + /// + /// Controls how the list is filtered + /// An XboxSocialRelationshipResult object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + [Windows::Foundation::Metadata::DefaultOverload] + Windows::Foundation::IAsyncOperation^ GetSocialRelationshipsAsync( + _In_ SocialRelationship socialRelationshipFilter + ); + + Windows::Foundation::IAsyncOperation^ GetSocialRelationshipsAsync( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Returns a XboxSocialRelationshipResult containing a the list of people that the user is connected to. + /// + /// Controls how the list is filtered + /// Controls the starting index to return + /// Controls the number of XboxSocialRelationship objects to get. 0 will return as many as possible + /// An XboxSocialRelationshipResult object. + /// Calls V1 GET /users/{ownerId}/people?view={view}&startIndex={startIndex}&maxItems={maxItems} + Windows::Foundation::IAsyncOperation^ GetSocialRelationshipsAsync( + _In_ SocialRelationship socialRelationshipFilter, + _In_ uint32 startIndex, + _In_ uint32 maxItems + ); + + /// + /// Subscribes to social relationship change notifications via the SocialRelationshipChanged event + /// + /// The Xbox User ID of the person of the subscription + /// SocialRelationshipChangeSubscription containing the initial value of the Xbox User Id + /// Register for social relationship changes via the SocialRelationshipChanged event + SocialRelationshipChangeSubscription^ SubscribeToSocialRelationshipChange( + _In_ Platform::String^ xboxUserId + ); + + /// + /// Unsubscribes a previously created social relationship change subscription + /// + /// The subscription object to unsubscribe + void UnsubscribeFromSocialRelationshipChange( + _In_ SocialRelationshipChangeSubscription^ subscription + ); + +internal: + SocialService( + _In_ xbox::services::social::social_service cppObj + ); + + void RaiseSocialRelationshipChange(_In_ SocialRelationshipChangeEventArgs^ args); +private: + ~SocialService(); + + xbox::services::social::social_service m_cppObj; + std::shared_ptr m_socialRelationshipSubscriptionEventBind; + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END diff --git a/Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.cpp b/Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.cpp new file mode 100644 index 00000000..60af7c2e --- /dev/null +++ b/Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.cpp @@ -0,0 +1,58 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "XboxSocialRelationshipResult_WinRT.h" +#include "SocialService_WinRT.h" +#include "Utils_WinRT.h" + +using namespace pplx; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::social; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +XboxSocialRelationshipResult::XboxSocialRelationshipResult( + _In_ xbox_social_relationship_result cppObj + ) : m_cppObj(std::move(cppObj)) +{ + Vector^ itemsVector = ref new Vector(); + const std::vector& cppItems = m_cppObj.items(); + for (auto& cppItem : cppItems) + { + itemsVector->Append(ref new XboxSocialRelationship(cppItem)); + } + m_itemView = itemsVector->GetView(); +} + +IVectorView^ +XboxSocialRelationshipResult::Items::get() +{ + return m_itemView; +} + +IAsyncOperation^ +XboxSocialRelationshipResult::GetNextAsync( + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox::services::xbox_live_result cppSocialRelationshipResult) + { + return ref new XboxSocialRelationshipResult(cppSocialRelationshipResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.h b/Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.h new file mode 100644 index 00000000..ba68a2ab --- /dev/null +++ b/Source/Services/Social/WinRT/XboxSocialRelationshipResult_WinRT.h @@ -0,0 +1,58 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "XboxSocialRelationship_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN +/// +/// Contains a collection of social relationships the user has with other Xbox Live users. +/// + +public ref class XboxSocialRelationshipResult sealed +{ +public: + /// + /// Collection of XboxSocialRelationship objects returned by a request + /// + property Windows::Foundation::Collections::IVectorView^ Items { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// The total number of XboxSocialRelationship objects that can be requested + /// + DEFINE_PROP_GET_OBJ(TotalCount, total_count, uint32); + + /// + /// Returns a boolean value that indicates if there are more pages of social relationships to retrieve. + /// + /// True if there are more pages, otherwise false. + DEFINE_PROP_GET_OBJ(HasNext, has_next, bool); + + /// + /// Returns an XboxSocialRelationshipResult object containing the next page + /// + /// The maximum number of items the response can contain. Pass 0 to attempt + /// retrieving all items. + /// Returns a XboxSocialRelationshipResult object + /// Calls V1 GET /users/{ownerId}/people + Windows::Foundation::IAsyncOperation^ GetNextAsync( + _In_ uint32 maxItems + ); + +internal: + XboxSocialRelationshipResult( + _In_ xbox::services::social::xbox_social_relationship_result cppObj + ); + +private: + xbox::services::social::xbox_social_relationship_result m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_itemView; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END diff --git a/Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.cpp b/Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.cpp new file mode 100644 index 00000000..153f46e5 --- /dev/null +++ b/Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "SocialRelationship_WinRT.h" +#include "XboxSocialRelationship_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace xbox::services::social; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +XboxSocialRelationship::XboxSocialRelationship( + _In_ ::xbox_social_relationship cppObj + ) : m_cppObj(cppObj) +{ + Vector^ responseVector = ref new Vector(); + const std::vector& cppSocialNetworks = m_cppObj.social_networks(); + for (auto& cppUserProfile : cppSocialNetworks) + { + responseVector->Append(ref new String(cppUserProfile.c_str())); + } + m_socialNetworksView = responseVector->GetView(); +} + +IVectorView^ +XboxSocialRelationship::SocialNetworks::get() +{ + return m_socialNetworksView; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.h b/Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.h new file mode 100644 index 00000000..39cdb0c4 --- /dev/null +++ b/Source/Services/Social/WinRT/XboxSocialRelationship_WinRT.h @@ -0,0 +1,58 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/social.h" +#include "shared_macros.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN +/// +/// Represents the relationship the user has with another Xbox Live user. +/// + +public ref class XboxSocialRelationship sealed +{ +public: + /// + /// The person's Xbox user identifier + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// Indicates whether the person is one that the user cares about more. + /// Users can have a very large number of people in their people list, + /// favorite people should be prioritized first in experiences and shown before others that are not favorites. + /// + DEFINE_PROP_GET_OBJ(IsFavorite, is_favorite, bool); + + /// + /// Indicates whether the person is following the person that requested the information. + /// + DEFINE_PROP_GET_OBJ(IsFollowingCaller, is_following_caller, bool); + + /// + /// A collection of strings indicating which social networks this person has a relationship with. + /// + property Windows::Foundation::Collections::IVectorView^ SocialNetworks + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + XboxSocialRelationship( + _In_ xbox::services::social::xbox_social_relationship cppObj + ); + +private: + xbox::services::social::xbox_social_relationship m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_socialNetworksView; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END diff --git a/Source/Services/Social/WinRT/XboxUserProfile_WinRT.cpp b/Source/Services/Social/WinRT/XboxUserProfile_WinRT.cpp new file mode 100644 index 00000000..bbf9c757 --- /dev/null +++ b/Source/Services/Social/WinRT/XboxUserProfile_WinRT.cpp @@ -0,0 +1,28 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "XboxUserProfile_winrt.h" + +using namespace pplx; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace xbox::services::social; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN + +XboxUserProfile::XboxUserProfile( + _In_ xbox_user_profile cppObj + ): + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/WinRT/XboxUserProfile_WinRT.h b/Source/Services/Social/WinRT/XboxUserProfile_WinRT.h new file mode 100644 index 00000000..87f343d0 --- /dev/null +++ b/Source/Services/Social/WinRT/XboxUserProfile_WinRT.h @@ -0,0 +1,81 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "shared_macros.h" +#include "xsapi/profile.h" +#include "Macros_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_BEGIN +/// +/// Represents a user's Xbox Live profile. +/// + +public ref class XboxUserProfile sealed +{ +public: + /// + /// The user's display name to be used in application UI. This value is privacy gated and could + /// be a user's real name or their gamertag. + /// + DEFINE_PROP_GET_STR_OBJ(ApplicationDisplayName, app_display_name) + + /// + /// Uri for the user's display picture to be used in application UI. + /// The Uri is a resizable Uri. It can be used to specify one of the following sizes and formats by appending '&format={format}&w={width}&h={height}: + /// Format: png + /// Width Height + /// 64 64 + /// 208 208 + /// 424 424 + /// + DEFINE_PROP_GET_URI_OBJ(ApplicationDisplayPictureResizeUri, app_display_picture_resize_uri) + + /// + /// The user's display name to be used in game UI. This value is privacy gated and could + /// be a user's real name or their gamertag. + /// + DEFINE_PROP_GET_STR_OBJ(GameDisplayName, game_display_name) + + /// + /// Uri for the user's display picture to be used in games. + /// The Uri is a resizable Uri. It can be used to specify one of the following sizes and formats by appending '&format={format}&w={width}&h={height}: + /// Format: png + /// Width Height + /// 64 64 + /// 208 208 + /// 424 424 + /// + DEFINE_PROP_GET_URI_OBJ(GameDisplayPictureResizeUri, game_display_picture_resize_uri) + + /// + /// The user's gamerscore. + /// + DEFINE_PROP_GET_STR_OBJ(Gamerscore, gamerscore) + + /// + /// The user's gamertag. + /// + DEFINE_PROP_GET_STR_OBJ(Gamertag, gamertag) + + /// + /// The user's Xbox user ID. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id) + +internal: + XboxUserProfile( + _In_ xbox::services::social::xbox_user_profile cppObj + ); + +private: + xbox::services::social::xbox_user_profile m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_END \ No newline at end of file diff --git a/Source/Services/Social/profile_service.cpp b/Source/Services/Social/profile_service.cpp new file mode 100644 index 00000000..2be44d09 --- /dev/null +++ b/Source/Services/Social/profile_service.cpp @@ -0,0 +1,219 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/profile.h" +#include "utils.h" +#include "user_context.h" +#include "xbox_system_factory.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +std::mutex profile_service::m_settingsLock; + +const string_t profile_service::SETTINGS_ARRAY[] = { + _T("AppDisplayName"), + _T("AppDisplayPicRaw"), + _T("GameDisplayName"), + _T("GameDisplayPicRaw"), + _T("Gamerscore"), + _T("Gamertag") +}; + +const web::json::value profile_service::SETTINGS_SERIALIZED = serialize_settings_json(); + +const string_t profile_service::SETTINGS_QUERY = settings_query(); + +profile_service::profile_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +profile_service::get_user_profile( + _In_ string_t xboxUserId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserId.empty(), xbox_user_profile, "xboxUserId is empty"); + std::vector< string_t> xboxUserIds; + xboxUserIds.push_back(std::move(xboxUserId)); + + auto task = get_user_profiles(xboxUserIds) + .then([](xbox_live_result> result) + { + if (result.payload().size() == 1) + { + return xbox_live_result(result.payload()[0], result.err(), result.err_message()); + } + else + { + return xbox_live_result(result.err(), result.err_message()); + } + }); + + return utils::create_exception_free_task( + task + ); +} + + +pplx::task>> +profile_service::get_user_profiles( + _In_ const std::vector< string_t >& xboxUserIds + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserIds.size() == 0, std::vector, "xbox user ids size is 0"); + for (string_t s : xboxUserIds) + { + RETURN_TASK_CPP_INVALIDARGUMENT_IF(s.empty(), std::vector, "Found empty string in xbox user ids"); + } + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("profile"), m_appConfig), + _T("/users/batch/profile/settings"), + xbox_live_api::get_user_profiles + ); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + web::json::value request; + request[_T("userIds")] = utils::serialize_vector(utils::json_string_serializer, xboxUserIds); + request[_T("settings")] = SETTINGS_SERIALIZED; + + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + if (response->response_body_json().size() != 0) + { + std::error_code errc = xbox_live_error_code::no_error; + auto profileVector = utils::extract_xbox_live_result_json_vector( + xbox_user_profile::_Deserialize, + response->response_body_json(), + _T("profileUsers"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + profileVector, + response + ); + } + else + { + return xbox_live_result>(response->err_code(), response->err_message()); + } + }); + + return utils::create_exception_free_task>( + task + ); +} + +pplx::task>> +profile_service::get_user_profiles_for_social_group( + _In_ const string_t& socialGroup + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(socialGroup.empty(), std::vector, "socialGroup is empty"); + + string_t pathAndQuery = pathandquery_user_profiles_for_social_group( + socialGroup + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("profile"), m_appConfig), + pathAndQuery, + xbox_live_api::get_user_profiles_for_social_group + ); + httpCall->set_xbox_contract_version_header_value(_T("2")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + if (response->response_body_json().size() != 0) // I don't think this is possible with this call? + { + std::error_code errc = xbox_live_error_code::no_error; + auto profileVector = utils::extract_xbox_live_result_json_vector( + xbox_user_profile::_Deserialize, + response->response_body_json(), + _T("profileUsers"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + profileVector, + response + ); + } + else + { + return xbox_live_result>(response->err_code(), response->err_message()); + } + }); + + return utils::create_exception_free_task>( + task + ); +} + +const string_t +profile_service::pathandquery_user_profiles_for_social_group( + _In_ const string_t& socialGroup + ) +{ + stringstream_t source; + source << _T("/users/me/profile/settings/people/"); + source << socialGroup; + source << _T("?settings="); + source << SETTINGS_QUERY; + + return source.str(); +} + +const string_t +profile_service::settings_query() +{ + stringstream_t source; + uint32_t arraySize = ARRAYSIZE(SETTINGS_ARRAY); + for (uint32_t i = 0; i < arraySize; ++i) + { + const string_t& setting = SETTINGS_ARRAY[i]; + source << web::http::uri::encode_uri(setting); + if (i + 1 != arraySize) + { + source << _T(","); + } + } + + return source.str(); +} + +web::json::value +profile_service::serialize_settings_json() +{ + std::vector settingsVector(SETTINGS_ARRAY, SETTINGS_ARRAY + sizeof(SETTINGS_ARRAY) / sizeof(SETTINGS_ARRAY[0])); + return utils::serialize_vector(utils::json_string_serializer, settingsVector); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/reputation_feedback_request.cpp b/Source/Services/Social/reputation_feedback_request.cpp new file mode 100644 index 00000000..fc6d4f47 --- /dev/null +++ b/Source/Services/Social/reputation_feedback_request.cpp @@ -0,0 +1,207 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" +#include "utils.h" +#include "social_internal.h" + +using namespace xbox::services::social; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +reputation_feedback_request::reputation_feedback_request( + _In_ reputation_feedback_type feedbackType, + _In_ string_t sessionName, + _In_ string_t reasonMessage, + _In_ string_t evidenceResourceId + ) : + m_feedbackType(feedbackType), + m_sessionName(std::move(sessionName)), + m_reasonMessage(std::move(reasonMessage)), + m_evidenceResourceId(std::move(evidenceResourceId)) +{ +} + +web::json::value +reputation_feedback_request::serialize_batch_feedback_request( + _In_ const std::vector< reputation_feedback_item >& feedbackItems, + _Out_ std::error_code& err + ) +{ + web::json::value itemArrayJson = web::json::value::array(); + uint32_t i = 0; + err = xbox_live_error_code::no_error; + + for (auto& feedbackItem : feedbackItems) + { + // Example: + // + // "targetXuid": "33445566778899", + // "titleId" : "6487", + // "sessionRef" : + // { + // "scid": "1234-1234-471F-B696-07B61F09EC20", + // "templateName" : "CaptureFlag5", + // "name" : "Example556932", + // }, + // "feedbackType": "FairPlayKillsTeammates", + // "textReason" : "Killed 19 team members in a single session", + // "evidenceId" : null + + xbox_live_result feedbackTypeToString = convert_reputation_feedback_type_to_string(feedbackItem.feedback_type()); + err = feedbackTypeToString.err(); + if (err) + { + break; + } + + web::json::value itemJson; + itemJson[_T("targetXuid")] = web::json::value::string(feedbackItem.xbox_user_id()); + itemJson[_T("titleId")] = web::json::value::null(); + + web::json::value sessionRefJson; + if (!feedbackItem.session_reference().is_null()) + { + sessionRefJson[_T("scid")] = web::json::value::string(feedbackItem.session_reference().service_configuration_id()); + sessionRefJson[_T("templateName")] = web::json::value::string(feedbackItem.session_reference().session_template_name()); + sessionRefJson[_T("name")] = web::json::value::string(feedbackItem.session_reference().session_name()); + itemJson[_T("sessionRef")] = sessionRefJson; + } + else + { + itemJson[_T("sessionRef")] = web::json::value::null(); + } + + itemJson[_T("feedbackType")] = web::json::value::string(feedbackTypeToString.payload()); + itemJson[_T("textReason")] = web::json::value::string(feedbackItem.reason_message()); + if (!feedbackItem.evidence_resource_id().empty()) + { + itemJson[_T("evidenceId")] = web::json::value::string(feedbackItem.evidence_resource_id()); + } + else + { + itemJson[_T("evidenceId")] = web::json::value::null(); + } + + itemArrayJson[i++] = itemJson; + } + + web::json::value request; + request[_T("items")] = itemArrayJson; + return request; +} + +web::json::value +reputation_feedback_request::serialize_feedback_request() +{ + web::json::value request; + xbox_live_result feedbackTypeToString = convert_reputation_feedback_type_to_string(m_feedbackType); + if (!feedbackTypeToString.err()) + { + request[_T("sessionName")] = web::json::value::string(m_sessionName); + request[_T("feedbackType")] = web::json::value::string(feedbackTypeToString.payload()); + request[_T("textReason")] = web::json::value::string(m_reasonMessage); + if (!m_evidenceResourceId.empty()) + { + request[_T("evidenceId")] = web::json::value::string(m_evidenceResourceId); + } + else + { + request[_T("evidenceId")] = web::json::value::null(); + } + } + + return request; +} + +const xbox_live_result +reputation_feedback_request::convert_reputation_feedback_type_to_string(reputation_feedback_type feedbackType) +{ + switch (feedbackType) + { + case reputation_feedback_type::fair_play_kills_teammates: return xbox_live_result(_T("FairPlayKillsTemmates")); + case reputation_feedback_type::fair_play_cheater: return xbox_live_result(_T("FairPlayCheater")); + case reputation_feedback_type::fair_play_tampering: return xbox_live_result(_T("FairPlayTampering")); + case reputation_feedback_type::fair_play_quitter: return xbox_live_result(_T("FairPlayQuitter")); + case reputation_feedback_type::fair_play_kicked: return xbox_live_result(_T("FairPlayKicked")); + case reputation_feedback_type::communications_inappropiate_video: return xbox_live_result(_T("CommsInappropriateVideo")); + case reputation_feedback_type::communications_abusive_voice: return xbox_live_result(_T("CommsAbusiveVoice")); + case reputation_feedback_type::inappropiate_user_generated_content: return xbox_live_result(_T("UserContentInappropriateUGC")); + case reputation_feedback_type::positive_skilled_player: return xbox_live_result(_T("PositiveSkilledPlayer")); + case reputation_feedback_type::positive_helpful_player: return xbox_live_result(_T("PositiveHelpfulPlayer")); + case reputation_feedback_type::positive_high_quality_user_generated_content: return xbox_live_result(_T("PositiveHighQualityUGC")); + case reputation_feedback_type::comms_phishing: return xbox_live_result(_T("CommsPhishing")); + case reputation_feedback_type::comms_picture_message: return xbox_live_result(_T("CommsPictureMessage")); + case reputation_feedback_type::comms_spam: return xbox_live_result(_T("CommsSpam")); + case reputation_feedback_type::comms_text_message: return xbox_live_result(_T("CommsTextMessage")); + case reputation_feedback_type::comms_voice_message: return xbox_live_result(_T("CommsVoiceMessage")); + case reputation_feedback_type::fair_play_console_ban_request: return xbox_live_result(_T("FairPlayConsoleBanRequest")); + case reputation_feedback_type::fair_play_idler: return xbox_live_result(_T("FairPlayIdler")); + case reputation_feedback_type::fair_play_user_ban_request: return xbox_live_result(_T("FairPlayUserBanRequest")); + case reputation_feedback_type::user_content_gamerpic: return xbox_live_result(_T("UserContentGamertag")); + case reputation_feedback_type::user_content_personalinfo: return xbox_live_result(_T("UserContentPersonalInfo")); + case reputation_feedback_type::fair_play_unsporting: return xbox_live_result(_T("FairplayUnsporting")); + case reputation_feedback_type::fair_play_leaderboard_cheater: return xbox_live_result(_T("FairplayLeaderboardCheater")); + + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Enum out of range"); + } +} + +reputation_feedback_item::reputation_feedback_item() : + m_reputationFeedbackType(reputation_feedback_type::fair_play_kills_teammates) +{ +} + +reputation_feedback_item::reputation_feedback_item( + _In_ string_t xboxUserId, + _In_ reputation_feedback_type reputationFeedbackType, + _In_ xbox::services::multiplayer::multiplayer_session_reference sessionRef, + _In_ string_t reasonMessage, + _In_ string_t evidenceResourceId + ) : + m_xboxUserId(std::move(xboxUserId)), + m_reputationFeedbackType(reputationFeedbackType), + m_sessionRef(std::move(sessionRef)), + m_reasonMessage(std::move(reasonMessage)), + m_evidenceResourceId(std::move(evidenceResourceId)) +{ +} + +const string_t& +reputation_feedback_item::xbox_user_id() const +{ + return m_xboxUserId; +} + +reputation_feedback_type +reputation_feedback_item::feedback_type() const +{ + return m_reputationFeedbackType; +} + +const xbox::services::multiplayer::multiplayer_session_reference& +reputation_feedback_item::session_reference() const +{ + return m_sessionRef; +} + +const string_t& +reputation_feedback_item::reason_message() const +{ + return m_reasonMessage; +} + +const string_t& +reputation_feedback_item::evidence_resource_id() const +{ + return m_evidenceResourceId; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/reputation_service.cpp b/Source/Services/Social/reputation_service.cpp new file mode 100644 index 00000000..19b622bd --- /dev/null +++ b/Source/Services/Social/reputation_service.cpp @@ -0,0 +1,140 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" +#include "user_context.h" +#include "utils.h" +#include "xbox_system_factory.h" +#include "social_internal.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +reputation_service::reputation_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +reputation_service::submit_batch_reputation_feedback( + _In_ const std::vector< reputation_feedback_item >& feedbackItems + ) +{ + for (auto& feedbackItem : feedbackItems) + { + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(feedbackItem.xbox_user_id(), void, "Xbox user id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF( + feedbackItem.feedback_type() < reputation_feedback_type::fair_play_kills_teammates || + feedbackItem.feedback_type() > reputation_feedback_type::fair_play_leaderboard_cheater, + void, + "Reputation feedback type is out of range" + ); + } + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("reputation"), m_appConfig), + _T("/users/batchtitlefeedback"), + xbox_live_api::submit_batch_reputation_feedback + ); + + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(_T("101")); + + std::error_code err; + web::json::value request = reputation_feedback_request::serialize_batch_feedback_request(feedbackItems, err); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(err, void, "Invalid reputation_feedback_item"); + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext, http_call_response_body_type::string_body) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + + +pplx::task> +reputation_service::submit_reputation_feedback( + _In_ const string_t& xboxUserId, + _In_ reputation_feedback_type reputationFeedbackType, + _In_ const string_t& sessionName, + _In_ const string_t& reasonMessage, + _In_ const string_t& evidenceResourceId + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(xboxUserId, void, "Xbox user id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF( + reputationFeedbackType < reputation_feedback_type::fair_play_kills_teammates || + reputationFeedbackType > reputation_feedback_type::fair_play_leaderboard_cheater, + void, + "Reputation feedback type is out of range" + ); + + string_t pathAndQuery = reputation_feedback_subpath(xboxUserId); + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("reputation"), m_appConfig), + pathAndQuery, + xbox_live_api::submit_reputation_feedback + ); + + httpCall->set_retry_allowed(false); + httpCall->set_xbox_contract_version_header_value(_T("100")); + + reputation_feedback_request reputationFeedbackRequest( + reputationFeedbackType, + sessionName, + reasonMessage, + evidenceResourceId + ); + + web::json::value request = reputationFeedbackRequest.serialize_feedback_request(); + httpCall->set_request_body(request.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext, http_call_response_body_type::string_body) + .then([](std::shared_ptr response) + { + return xbox_live_result(response->err_code(), response->err_message()); + }); + + return utils::create_exception_free_task( + task + ); +} + +string_t +reputation_service::reputation_feedback_subpath( + _In_ const string_t& xboxUserId +) +{ + stringstream_t source; + source << _T("/users/xuid("); + source << xboxUserId; + source << _T(")/feedback"); + + return source.str(); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/social_internal.h b/Source/Services/Social/social_internal.h new file mode 100644 index 00000000..b5b362e7 --- /dev/null +++ b/Source/Services/Social/social_internal.h @@ -0,0 +1,116 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "system_internal.h" + +namespace xbox { namespace services { namespace social { + +/// +/// Used to provide feedback within a game session. +/// +class reputation_feedback_request +{ + // Example: + //{ + // "evidenceId":"992399", + // "feedbackType" : "PositiveHighQualityUGC", + // "sessionName" : "Game", + // "textReason" : "Great level" + //} + +public: + /// + /// Sends a feedback report for a game session. + /// + /// The type of report being made. + /// The name of the session in which the reported action occurred. + /// The user supplied reason the report is being made. + /// An identifier for the resource that shows evidance supporting the report. + reputation_feedback_request( + _In_ reputation_feedback_type feedbackType, + _In_ string_t sessionName, + _In_ string_t reasonMessage, + _In_ string_t evidenceResourceId + ); + + web::json::value serialize_feedback_request(); + static web::json::value serialize_batch_feedback_request(_In_ const std::vector< reputation_feedback_item >& feedbackItems, _Out_ std::error_code& err); + static const xbox_live_result convert_reputation_feedback_type_to_string(reputation_feedback_type feedbackType); + +private: + reputation_feedback_type m_feedbackType; + string_t m_sessionName; + string_t m_reasonMessage; + string_t m_evidenceResourceId; +}; + +class social_service_impl : public std::enable_shared_from_this +{ +public: + social_service_impl( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivityService + ); + + xbox_live_result> subscribe_to_social_relationship_change( + _In_ const string_t& xboxUserId + ); + + xbox_live_result unsubscribe_from_social_relationship_change( + _In_ std::shared_ptr subscription + ); + + function_context add_social_relationship_changed_handler( + _In_ std::function handler + ); + + void remove_social_relationship_changed_handler( + _In_ function_context context + ); + + pplx::task> get_social_relationships( + _In_ xbox_social_relationship_filter socialRelationshipFilter, + _In_ uint32_t startIndex, + _In_ uint32_t maxItems + ); + + pplx::task> get_social_relationships( + _In_ const string_t& xboxUserId, + _In_ xbox_social_relationship_filter filter, + _In_ unsigned int startIndex, + _In_ unsigned int maxItems + ); + +private: + void social_relationship_changed(_In_ social_relationship_change_event_args eventArgs); + static string_t pathandquery_social_subpath( + _In_ const string_t& ownerId, + _In_ bool includeViewFilter, + _In_ const string_t& view, + _In_ uint64_t startIndex, + _In_ uint64_t maxItems + ); + + static const string_t xbox_social_relationship_filter_to_string( + _In_ xbox_social_relationship_filter xboxSocialRelationshipFilter + ); + + std::shared_ptr m_userContext; + std::shared_ptr m_xboxLiveContextSettings; + std::shared_ptr m_appConfig; + std::unordered_map> m_socialRelationshipChangeHandler; + function_context m_socialRelationshipChangeHandlerCounter; + xbox::services::system::xbox_live_mutex m_socialRelationshipChangeHandlerLock; + std::shared_ptr m_realTimeActivityService; +}; + +}}} \ No newline at end of file diff --git a/Source/Services/Social/social_relationship_change_event_args.cpp b/Source/Services/Social/social_relationship_change_event_args.cpp new file mode 100644 index 00000000..65f9aaaa --- /dev/null +++ b/Source/Services/Social/social_relationship_change_event_args.cpp @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +social_relationship_change_event_args::social_relationship_change_event_args() +{ +} + +social_relationship_change_event_args::social_relationship_change_event_args( + _In_ string_t callerXboxUserId, + _In_ social_notification_type notificationType, + _In_ std::vector xboxUserIds + ) : + m_callerXboxUserId(std::move(callerXboxUserId)), + m_notificationType(notificationType), + m_xboxUserIds(std::move(xboxUserIds)) +{ +} + +const string_t& +social_relationship_change_event_args::caller_xbox_user_id() const +{ + return m_callerXboxUserId; +} + +social_notification_type +social_relationship_change_event_args::social_notification() const +{ + return m_notificationType; +} + +const std::vector& +social_relationship_change_event_args::xbox_user_ids() const +{ + return m_xboxUserIds; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/social_relationship_change_subscription.cpp b/Source/Services/Social/social_relationship_change_subscription.cpp new file mode 100644 index 00000000..a3c133da --- /dev/null +++ b/Source/Services/Social/social_relationship_change_subscription.cpp @@ -0,0 +1,108 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" + +using namespace xbox::services::real_time_activity; +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +social_relationship_change_subscription::social_relationship_change_subscription( + _In_ string_t xboxUserId, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ) : + real_time_activity_subscription(subscriptionErrorHandler), + m_xboxUserId(std::move(xboxUserId)), + m_handler(std::move(handler)) +{ + XSAPI_ASSERT(!m_xboxUserId.empty()); + XSAPI_ASSERT(m_handler != nullptr); + + stringstream_t uri; + uri << _T("http://social.xboxlive.com/users/xuid(") << m_xboxUserId << _T(")/friends"); + + m_resourceUri = uri.str(); +} + +const string_t& +social_relationship_change_subscription::xbox_user_id() const +{ + return m_xboxUserId; +} + +void +social_relationship_change_subscription::on_subscription_created( + _In_ uint32_t id, + _In_ const web::json::value& data + ) +{ + real_time_activity_subscription::on_subscription_created(id, data); + + if (!data.is_null()) + { + m_subscriptionErrorHandler( + real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON Deserialization Failure" + ) + ); + } + +} + +void +social_relationship_change_subscription::on_event_received(_In_ const web::json::value& data) +{ + std::error_code errc; + auto notificationTypeString = utils::extract_json_string(data, _T("NotificationType"), errc); + auto notificationType = convert_string_type_to_notification_type(notificationTypeString); + auto xboxUserIds = utils::extract_json_vector( + utils::json_string_extractor, + data, + _T("Xuids"), + errc, + false + ); + + if (errc || notificationType == social_notification_type::unknown) + { + m_subscriptionErrorHandler( + real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON Deserialization Failure" + ) + ); + } + else + { + m_handler( + social_relationship_change_event_args( + m_xboxUserId, + notificationType, + xboxUserIds + ) + ); + } +} + +social_notification_type +social_relationship_change_subscription::convert_string_type_to_notification_type( + _In_ const string_t& notificationTypeString + ) const +{ + if (utils::str_icmp(notificationTypeString, _T("added")) == 0) return social_notification_type::added; + else if (utils::str_icmp(notificationTypeString, _T("removed")) == 0) return social_notification_type::removed; + else if (utils::str_icmp(notificationTypeString, _T("changed")) == 0) return social_notification_type::changed; + else return social_notification_type::unknown; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/social_service.cpp b/Source/Services/Social/social_service.cpp new file mode 100644 index 00000000..8e512e2c --- /dev/null +++ b/Source/Services/Social/social_service.cpp @@ -0,0 +1,125 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" +#include "social_internal.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +social_service::social_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivityService + ) : + m_userContext(userContext), + m_xboxLiveContextSettings(xboxLiveContextSettings), + m_socialServiceImpl(std::make_shared(userContext, xboxLiveContextSettings, appConfig, realTimeActivityService)) +{ +} + +pplx::task> +social_service::get_social_relationships() +{ + return get_social_relationships(m_userContext->xbox_user_id(), xbox_social_relationship_filter::all, 0, 0); +} + +pplx::task> +social_service::get_social_relationships( + _In_ const string_t& xboxUserId + ) +{ + return get_social_relationships(xboxUserId, xbox_social_relationship_filter::all, 0, 0); +} + +pplx::task> +social_service::get_social_relationships( + _In_ xbox_social_relationship_filter socialRelationshipFilter + ) +{ + return get_social_relationships(m_userContext->xbox_user_id(), socialRelationshipFilter, 0, 0); +} + +pplx::task> +social_service::get_social_relationships( + _In_ xbox_social_relationship_filter filter, + _In_ unsigned int startIndex, + _In_ unsigned int maxItems + ) +{ + return m_socialServiceImpl->get_social_relationships( + filter, + startIndex, + maxItems + ); +} + +pplx::task> +social_service::get_social_relationships( + _In_ const string_t& xboxUserId, + _In_ xbox_social_relationship_filter filter, + _In_ unsigned int startIndex, + _In_ unsigned int maxItems + ) +{ + return m_socialServiceImpl->get_social_relationships( + xboxUserId, + filter, + startIndex, + maxItems + ); +} + +xbox_live_result> +social_service::subscribe_to_social_relationship_change( + _In_ const string_t& xboxUserId + ) +{ + return m_socialServiceImpl->subscribe_to_social_relationship_change( + xboxUserId + ); +} + +xbox_live_result +social_service::unsubscribe_from_social_relationship_change( + _In_ std::shared_ptr subscription + ) +{ + return m_socialServiceImpl->unsubscribe_from_social_relationship_change( + subscription + ); +} + +function_context +social_service::add_social_relationship_changed_handler( + _In_ std::function handler + ) +{ + return m_socialServiceImpl->add_social_relationship_changed_handler( + std::move(handler) + ); +} + +void +social_service::remove_social_relationship_changed_handler( + _In_ function_context context + ) +{ + m_socialServiceImpl->remove_social_relationship_changed_handler( + context + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/social_service_impl.cpp b/Source/Services/Social/social_service_impl.cpp new file mode 100644 index 00000000..3e5cc1e9 --- /dev/null +++ b/Source/Services/Social/social_service_impl.cpp @@ -0,0 +1,268 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" +#include "social_internal.h" +#include "http_call_impl.h" +#include "user_context.h" +#include "xbox_system_factory.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +social_service_impl::social_service_impl( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr realTimeActivityService + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_realTimeActivityService(realTimeActivityService), + m_socialRelationshipChangeHandlerCounter(0) +{ +} + +xbox_live_result> +social_service_impl::subscribe_to_social_relationship_change( + _In_ const string_t& xboxUserId + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + auto socialRelationshipSub = std::make_shared( + xboxUserId, + ([thisWeakPtr](social_relationship_change_event_args eventArgs) + { + std::shared_ptr pThis(thisWeakPtr); + if (pThis) + { + pThis->social_relationship_changed(eventArgs); + } + }), + ([thisWeakPtr](const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr); + if (pThis) + { + pThis->m_realTimeActivityService->_Trigger_subscription_error(eventArgs); + } + }) + ); + + auto subscriptionSucceed = m_realTimeActivityService->_Add_subscription( + socialRelationshipSub + ); + + if (!subscriptionSucceed.err()) + { + return xbox_live_result>(socialRelationshipSub); + } + + return xbox_live_result>(subscriptionSucceed.err(), subscriptionSucceed.err_message()); +} + +xbox_live_result +social_service_impl::unsubscribe_from_social_relationship_change( + _In_ std::shared_ptr subscription + ) +{ + return m_realTimeActivityService->_Remove_subscription( + subscription + ); +} + +function_context +social_service_impl::add_social_relationship_changed_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_socialRelationshipChangeHandlerLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_socialRelationshipChangeHandlerCounter; + m_socialRelationshipChangeHandler[m_socialRelationshipChangeHandlerCounter] = std::move(handler); + } + + return context; +} + +void +social_service_impl::remove_social_relationship_changed_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_socialRelationshipChangeHandlerLock.get()); + + m_socialRelationshipChangeHandler.erase(context); +} + +void +social_service_impl::social_relationship_changed( + _In_ social_relationship_change_event_args eventArgs + ) +{ + std::unordered_map> socialRelationshipChangedHandlersCopy; + { + std::lock_guard lock(m_socialRelationshipChangeHandlerLock.get()); + socialRelationshipChangedHandlersCopy = m_socialRelationshipChangeHandler; + } + + for (auto& handler : socialRelationshipChangedHandlersCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(eventArgs); + } + catch (...) + { + LOG_ERROR("social_relationship_changed call threw an exception"); + } + } + } +} + +pplx::task> +social_service_impl::get_social_relationships( + _In_ xbox_social_relationship_filter filter, + _In_ unsigned int startIndex, + _In_ unsigned int maxItems + ) +{ + return get_social_relationships(m_userContext->xbox_user_id(), filter, startIndex, maxItems); +} + +pplx::task> +social_service_impl::get_social_relationships( + _In_ const string_t& xboxUserId, + _In_ xbox_social_relationship_filter filter, + _In_ unsigned int startIndex, + _In_ unsigned int maxItems + ) +{ + bool includeViewFilter = (filter != xbox_social_relationship_filter::all); + + string_t pathAndQuery = pathandquery_social_subpath( + xboxUserId, + includeViewFilter, + xbox_social_relationship_filter_to_string(filter), + startIndex, + maxItems + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("social"), m_appConfig), + pathAndQuery, + xbox_live_api::get_social_relationships + ); + + auto userContext = m_userContext; + auto xboxLiveContextSettings = m_xboxLiveContextSettings; + auto appConfig = m_appConfig; + + std::shared_ptr thisShared = shared_from_this(); + auto task = httpCall->get_response_with_auth(m_userContext) + .then([thisShared, userContext, xboxLiveContextSettings, appConfig, startIndex, filter](std::shared_ptr response) + { + auto result = xbox_social_relationship_result::_Deserialize(response->response_body_json()); + + auto& socialRelationship = result.payload(); + uint32_t itemSize = static_cast(socialRelationship.items().size()); + if (itemSize > 0) + { + unsigned continuationSkip = startIndex + itemSize; + + // Initialize the request params for get_next() + socialRelationship._Init_next_page_info( + thisShared, + filter, + continuationSkip + ); + } + + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +const string_t +social_service_impl::xbox_social_relationship_filter_to_string( + _In_ xbox_social_relationship_filter xboxSocialRelationshipFilter + ) +{ + switch (xboxSocialRelationshipFilter) + { + case xbox_social_relationship_filter::favorite: + return _T("Favorite"); + + case xbox_social_relationship_filter::legacy_xbox_live_friends: + return _T("LegacyXboxLiveFriends"); + + default: + case xbox_social_relationship_filter::all: + return string_t(); + } +} + +string_t +social_service_impl::pathandquery_social_subpath( + _In_ const string_t& ownerId, + _In_ bool includeViewFilter, + _In_ const string_t& view, + _In_ uint64_t startIndex, + _In_ uint64_t maxItems + ) +{ + stringstream_t source; + source << _T("/users/xuid("); + source << ownerId; + source << ")/people"; + + string_t nextDelimiter = _T("?"); + + if (includeViewFilter) + { + source << nextDelimiter; + source << _T("view="); + source << view; + nextDelimiter = _T("&"); + } + + if (startIndex > 0) + { + source << nextDelimiter; + source << _T("startIndex="); + source << startIndex; + nextDelimiter = _T("&"); + } + + if (maxItems > 0) + { + source << nextDelimiter; + source << _T("maxItems="); + source << maxItems; + nextDelimiter = _T("&"); + } + + return source.str(); +} +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/xbox_social_relationship.cpp b/Source/Services/Social/xbox_social_relationship.cpp new file mode 100644 index 00000000..06b14516 --- /dev/null +++ b/Source/Services/Social/xbox_social_relationship.cpp @@ -0,0 +1,77 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" +#include "utils.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +xbox_social_relationship::xbox_social_relationship(): + m_isFavorite(false), + m_isFollowingCaller(false) +{ +} + +xbox_social_relationship::xbox_social_relationship( + _In_ string_t xboxUserId, + _In_ bool isFavorite, + _In_ bool isFollowingCaller, + _In_ std::vector socialNetworks + ) : + m_xboxUserId(std::move(xboxUserId)), + m_isFavorite(isFavorite), + m_isFollowingCaller(isFollowingCaller), + m_socialNetworks(std::move(socialNetworks)) +{ +} + +const string_t& xbox_social_relationship::xbox_user_id() const +{ + return m_xboxUserId; +} + +bool xbox_social_relationship::is_favorite() const +{ + return m_isFavorite; +} + +bool xbox_social_relationship::is_following_caller() const +{ + return m_isFollowingCaller; +} + +const std::vector< string_t >& xbox_social_relationship::social_networks() const +{ + return m_socialNetworks; +} + +xbox_live_result +xbox_social_relationship::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + auto result = xbox_social_relationship( + utils::extract_json_string(json, _T("xuid"), errc, true), + utils::extract_json_bool(json, _T("isFavorite"), errc), + utils::extract_json_bool(json, _T("isFollowingCaller"), errc), + utils::extract_json_vector(utils::json_string_extractor, json, _T("socialNetworks"), errc, false) + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/xbox_social_relationship_result.cpp b/Source/Services/Social/xbox_social_relationship_result.cpp new file mode 100644 index 00000000..420a7bf8 --- /dev/null +++ b/Source/Services/Social/xbox_social_relationship_result.cpp @@ -0,0 +1,92 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/social.h" +#include "social_internal.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_context.h" + +using namespace pplx; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN +xbox_social_relationship_result::xbox_social_relationship_result(): + m_totalCount(0), + m_filter(xbox_social_relationship_filter::all), + m_continuationSkip(0) +{ +} + +xbox_social_relationship_result::xbox_social_relationship_result( + _In_ std::vector socialRelationships, + _In_ uint32_t totalCount + ) : + m_socialRelationships(std::move(socialRelationships)), + m_totalCount(totalCount) +{ +} + +void xbox_social_relationship_result::_Init_next_page_info( + _In_ std::shared_ptr socialImpl, + _In_ xbox_social_relationship_filter filter, + _In_ uint32_t continuationSkip + ) +{ + m_socialImpl = socialImpl; + m_filter = filter; + m_continuationSkip = continuationSkip; +} + +const std::vector< xbox_social_relationship >& +xbox_social_relationship_result::items() const +{ + return m_socialRelationships; +} + +uint32_t xbox_social_relationship_result::total_count() const +{ + return m_totalCount; +} + +bool +xbox_social_relationship_result::has_next() +{ + return (m_continuationSkip < m_totalCount); +} + +pplx::task> +xbox_social_relationship_result::get_next( + _In_ uint32_t maxItems + ) +{ + m_socialImpl->get_social_relationships( + m_filter, + m_continuationSkip, + maxItems + ); + return m_socialImpl->get_social_relationships(m_filter, m_continuationSkip, maxItems); +} + +xbox_live_result +xbox_social_relationship_result::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + + auto result = xbox_social_relationship_result( + utils::extract_json_vector(xbox_social_relationship::_Deserialize, json, _T("people"), errc, true), + utils::extract_json_int(json, _T("totalCount"), errc, false, 0) + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Social/xbox_user_profile.cpp b/Source/Services/Social/xbox_user_profile.cpp new file mode 100644 index 00000000..53f9b244 --- /dev/null +++ b/Source/Services/Social/xbox_user_profile.cpp @@ -0,0 +1,144 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "shared_macros.h" +#include "xsapi/system.h" +#include "xsapi/profile.h" +#include "utils.h" + +using namespace pplx; +using namespace xbox::services; +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_BEGIN + +xbox_user_profile::xbox_user_profile() +{ +} + +xbox_user_profile::xbox_user_profile( + _In_ string_t appDisplayName, + _In_ web::uri appDisplayPictureResizeUri, + _In_ string_t gameDisplayName, + _In_ web::uri gameDisplayPictureResizeUri, + _In_ string_t gamerscore, + _In_ string_t gamertag, + _In_ string_t xboxUserId + ) : + m_appDisplayName(std::move(appDisplayName)), + m_appDisplayPictureResizeUri(std::move(appDisplayPictureResizeUri)), + m_gameDisplayName(std::move(gameDisplayName)), + m_gameDisplayPictureResizeUri(std::move(gameDisplayPictureResizeUri)), + m_gamerscore(std::move(gamerscore)), + m_gamertag(std::move(gamertag)), + m_xboxUserId(std::move(xboxUserId)) +{ +} + +const string_t& xbox_user_profile::app_display_name() const +{ + return m_appDisplayName; +} + +const web::uri& xbox_user_profile::app_display_picture_resize_uri() const +{ + return m_appDisplayPictureResizeUri; +} + +const string_t& xbox_user_profile::game_display_name() const +{ + return m_gameDisplayName; +} + +const web::uri& xbox_user_profile::game_display_picture_resize_uri() const +{ + return m_gameDisplayPictureResizeUri; +} + +const string_t& xbox_user_profile::gamerscore() const +{ + return m_gamerscore; +} + +const string_t& xbox_user_profile::gamertag() const +{ + return m_gamertag; +} + +const string_t& xbox_user_profile::xbox_user_id() const +{ + return m_xboxUserId; +} + +xbox_live_result +xbox_user_profile::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value jsonSettings = utils::extract_json_field(json, _T("settings"), errc, true); + + web::json::array setttings = jsonSettings.as_array(); + + string_t appDisplayName; + web::uri appDisplayPictureResizeUri; + string_t gameDisplayName; + web::uri gameDisplayPictureResizeUri; + string_t gamerscore; + string_t gamertag; + string_t xboxUserId = utils::extract_json_string(json, _T("id"), errc, true); + + for (const auto& setting : setttings) + { + string_t name = utils::extract_json_string(setting, _T("id"), errc, true); + string_t stringValue = utils::extract_json_string(setting, _T("value"), errc, true); + + if (name == _T("AppDisplayName")) + { + appDisplayName = std::move(stringValue); + } + else if (name == _T("AppDisplayPicRaw")) + { + appDisplayPictureResizeUri = std::move(stringValue); + } + else if (name == _T("GameDisplayName")) + { + gameDisplayName = std::move(stringValue); + } + else if (name == _T("GameDisplayPicRaw")) + { + gameDisplayPictureResizeUri = std::move(stringValue); + } + else if (name == _T("Gamerscore")) + { + gamerscore = std::move(stringValue); + } + else if (name == _T("Gamertag")) + { + gamertag = std::move(stringValue); + } + } + + auto result = xbox_user_profile( + std::move(appDisplayName), + std::move(appDisplayPictureResizeUri), + std::move(gameDisplayName), + std::move(gameDisplayPictureResizeUri), + std::move(gamerscore), + std::move(gamertag), + std::move(xboxUserId) + ); + + return xbox_live_result(result, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_SOCIAL_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/RequestedStatistics_WinRT.cpp b/Source/Services/Stats/WinRT/RequestedStatistics_WinRT.cpp new file mode 100644 index 00000000..3cfa4902 --- /dev/null +++ b/Source/Services/Stats/WinRT/RequestedStatistics_WinRT.cpp @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" +#include "RequestedStatistics_winrt.h" +#include "Utils_WinRT.h" + +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::Foundation::Collections; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::user_statistics; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +RequestedStatistics::RequestedStatistics( + Platform::String^ serviceConfigurationId, + IVectorView^ statistics + ) : + m_cppObj(STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), UtilsWinRT::CovertVectorViewToStdVectorString(statistics)), + m_statistics(statistics) +{ +} + +IVectorView^ +RequestedStatistics::Statistics::get() +{ + return m_statistics; +} + +const requested_statistics& +RequestedStatistics::GetCppObj() const +{ + return m_cppObj; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/RequestedStatistics_WinRT.h b/Source/Services/Stats/WinRT/RequestedStatistics_WinRT.h new file mode 100644 index 00000000..b5e7c02a --- /dev/null +++ b/Source/Services/Stats/WinRT/RequestedStatistics_WinRT.h @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +/// +/// Contains requested statistics. +/// +public ref class RequestedStatistics sealed +{ +public: + /// + /// Constructor for a RequestedStatistics object. + /// + /// The service configuration ID to use. + /// A collection of statistics. + RequestedStatistics( + Platform::String^ serviceConfigurationId, + Windows::Foundation::Collections::IVectorView^ statistics + ); + + /// + /// The service configuration ID in use. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// A collection of statistics. + /// + property Windows::Foundation::Collections::IVectorView^ Statistics + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + const xbox::services::user_statistics::requested_statistics& GetCppObj() const; + +private: + xbox::services::user_statistics::requested_statistics m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_statistics; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.cpp b/Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.cpp new file mode 100644 index 00000000..e0a303f3 --- /dev/null +++ b/Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.cpp @@ -0,0 +1,34 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "ServiceConfigurationStatistic_winrt.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::user_statistics; +using namespace Microsoft::Xbox::Services::System; +using namespace Windows::Foundation::Collections; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +ServiceConfigurationStatistic::ServiceConfigurationStatistic( + _In_ service_configuration_statistic cppObj + ) : + m_cppObj(cppObj) +{ + m_stats = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.statistics()); +} + +IVectorView^ +ServiceConfigurationStatistic::Statistics::get() +{ + return m_stats->GetView(); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END diff --git a/Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.h b/Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.h new file mode 100644 index 00000000..e8afe845 --- /dev/null +++ b/Source/Services/Stats/WinRT/ServiceConfigurationStatistic_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "Statistic_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +/// +/// Contains statistical information from a service configuration. +/// +public ref class ServiceConfigurationStatistic sealed +{ +public: + /// + /// The service configuration ID associated with the leaderboard. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// A collection of statistics used in leaderboards. + /// + property Windows::Foundation::Collections::IVectorView^ Statistics + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + ServiceConfigurationStatistic( + _In_ xbox::services::user_statistics::service_configuration_statistic cppObj + ); + +private: + Windows::Foundation::Collections::IVector^ m_stats; + xbox::services::user_statistics::service_configuration_statistic m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.cpp b/Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.cpp new file mode 100644 index 00000000..25c42a30 --- /dev/null +++ b/Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.cpp @@ -0,0 +1,29 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "StatisticChangeEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +StatisticChangeEventArgs::StatisticChangeEventArgs( + _In_ xbox::services::user_statistics::statistic_change_event_args cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_latestStatistic = ref new Statistic(m_cppObj.latest_statistic()); +} + +Statistic^ +StatisticChangeEventArgs::LatestStatistic::get() +{ + return m_latestStatistic; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.h b/Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.h new file mode 100644 index 00000000..07a416fa --- /dev/null +++ b/Source/Services/Stats/WinRT/StatisticChangeEventArgs_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/user_statistics.h" +#include "Statistic_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +/// +/// Contains information about a change to a subscribed statistic. +/// +public ref class StatisticChangeEventArgs sealed +{ +public: + /// + /// The Xbox user ID used to create the subscription. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The service configuration ID used to create the subscription. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The statistic with an updated value. + /// + property Statistic^ LatestStatistic{ Statistic^ get(); } + +internal: + StatisticChangeEventArgs(_In_ xbox::services::user_statistics::statistic_change_event_args cppObj); + +private: + xbox::services::user_statistics::statistic_change_event_args m_cppObj; + Statistic^ m_latestStatistic; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.cpp b/Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.cpp new file mode 100644 index 00000000..f2af381a --- /dev/null +++ b/Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.cpp @@ -0,0 +1,42 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "StatisticChangeSubscription_WinRT.h" + +using namespace Microsoft::Xbox::Services::RealTimeActivity; +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +StatisticChangeSubscription::StatisticChangeSubscription( + _In_ std::shared_ptr cppObj + ) : + m_cppObj(cppObj) +{ + m_statisticName = ref new Platform::String(m_cppObj->statistic().statistic_name().c_str()); +} + +RealTimeActivitySubscriptionState +StatisticChangeSubscription::State::get() +{ + return static_cast(m_cppObj->state()); +} + +Platform::String^ +StatisticChangeSubscription::StatisticName::get() +{ + return m_statisticName; +} + +std::shared_ptr +StatisticChangeSubscription::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.h b/Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.h new file mode 100644 index 00000000..30cccd01 --- /dev/null +++ b/Source/Services/Stats/WinRT/StatisticChangeSubscription_WinRT.h @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/user_statistics.h" +#include "Statistic_WinRT.h" +#include "RealTimeActivitySubscriptionState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +/// +/// Handles notification when the state of a statistic subscription changes. +/// +public ref class StatisticChangeSubscription sealed +{ +public: + /// + /// Indicates the state of the subscription. + /// + property Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState State{ Microsoft::Xbox::Services::RealTimeActivity::RealTimeActivitySubscriptionState get(); } + + /// + /// The resource uri for the request. + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ResourceUri, resource_uri); + + /// + /// The unique subscription id for the request. + /// + DEFINE_PTR_PROP_GET_OBJ(SubscriptionId, subscription_id, uint32_t); + + /// + /// The xbox user id the subscription is for + /// + DEFINE_PTR_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The service configuration id the subscription is under + /// + DEFINE_PTR_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The Statistic name the subscription is for + /// + property Platform::String^ StatisticName + { + Platform::String^ get(); + }; + +internal: + StatisticChangeSubscription(_In_ std::shared_ptr cppObj); + std::shared_ptr GetCppObj() const; + +private: + std::shared_ptr m_cppObj; + Platform::String^ m_statisticName; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/Statistic_WinRT.cpp b/Source/Services/Stats/WinRT/Statistic_WinRT.cpp new file mode 100644 index 00000000..ecde7f8a --- /dev/null +++ b/Source/Services/Stats/WinRT/Statistic_WinRT.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Statistic_winrt.h" +#include "Utils_WinRT.h" + +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::user_statistics; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +Statistic::Statistic( + _In_ statistic cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_statType = UtilsWinRT::ConvertStringToPropertyType(m_cppObj.statistic_type()); +} + +Windows::Foundation::PropertyType +Statistic::StatisticType::get() +{ + return m_statType; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/Statistic_WinRT.h b/Source/Services/Stats/WinRT/Statistic_WinRT.h new file mode 100644 index 00000000..1e805de9 --- /dev/null +++ b/Source/Services/Stats/WinRT/Statistic_WinRT.h @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/user_statistics.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +/// +/// Contains information about a user statistic. +/// +public ref class Statistic sealed +{ +public: + /// + /// The name of the statistic. + /// + DEFINE_PROP_GET_STR_OBJ(StatisticName, statistic_name); + + /// + /// The type of the statistic. + /// It can be one of the following values: + /// PropertyType.Int64, PropertyType.Double, + /// PropertyType.String, PropertyType.DateTime, + /// or PropertyType.OtherType if unknown. + /// + property Windows::Foundation::PropertyType StatisticType { Windows::Foundation::PropertyType get(); } + + /// + /// The value of the statistic. + /// + DEFINE_PROP_GET_STR_OBJ(Value, value); + +internal: + Statistic( + _In_ xbox::services::user_statistics::statistic cppObj + ); + +private: + Windows::Foundation::PropertyType m_statType; + xbox::services::user_statistics::statistic m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END diff --git a/Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.cpp b/Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.cpp new file mode 100644 index 00000000..dab2a481 --- /dev/null +++ b/Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.cpp @@ -0,0 +1,39 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Statistic_winrt.h" +#include "ServiceConfigurationStatistic_winrt.h" +#include "UserStatisticsResult_winrt.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::user_statistics; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +UserStatisticsResult::UserStatisticsResult( + _In_ user_statistics_result cppObj + ) : + m_cppObj(cppObj) +{ + m_serviceConfigStatistics = UtilsWinRT::CreatePlatformVectorFromStdVectorObj(m_cppObj.service_configuration_statistics()); + +} + +Windows::Foundation::Collections::IVectorView^ +UserStatisticsResult::ServiceConfigurationStatistics::get() +{ + return m_serviceConfigStatistics->GetView(); +} + +} // UserStats Namespace +} // Services Namespace +} // Xbox Namespace +} // Microsoft Namespace diff --git a/Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.h b/Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.h new file mode 100644 index 00000000..e6518570 --- /dev/null +++ b/Source/Services/Stats/WinRT/UserStatisticsResult_WinRT.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "ServiceConfigurationStatistic_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +/// +/// Represents the results of a user statistic query. +/// +public ref class UserStatisticsResult sealed +{ +public: + /// + /// The Xbox User ID for the user in a statistic. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// A collection of statistics from a service configuration. + /// + property Windows::Foundation::Collections::IVectorView^ ServiceConfigurationStatistics + { + Windows::Foundation::Collections::IVectorView^ get(); + } + +internal: + UserStatisticsResult( + _In_ xbox::services::user_statistics::user_statistics_result cppObj + ); + + property Platform::String^ InputServiceConfigurationId; + +private: + Windows::Foundation::Collections::IVector^ m_serviceConfigStatistics; + xbox::services::user_statistics::user_statistics_result m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/UserStatisticsService_WinRT.cpp b/Source/Services/Stats/WinRT/UserStatisticsService_WinRT.cpp new file mode 100644 index 00000000..1284891f --- /dev/null +++ b/Source/Services/Stats/WinRT/UserStatisticsService_WinRT.cpp @@ -0,0 +1,236 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "UserStatisticsService_WinRT.h" +#include "Utils_WinRT.h" +#include "XboxLiveContextSettings_WinRT.h" + +using namespace concurrency; +using namespace Platform::Collections; +using namespace Platform; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Services::System; +using namespace xbox::services::user_statistics; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +UserStatisticsService::UserStatisticsService( + _In_ user_statistics_service cppObj + ) : + m_cppObj(cppObj) +{ + m_userStatisticsServiceEventBind = std::make_shared(Platform::WeakReference(this), m_cppObj); + m_userStatisticsServiceEventBind->AddUserStatisticsServiceEvent(); +} + +UserStatisticsService::~UserStatisticsService() +{ + m_userStatisticsServiceEventBind->RemoveUserStatisticChangeEvent(m_cppObj); +} + +UserStatisticsServiceEventBind::UserStatisticsServiceEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::user_statistics::user_statistics_service& cppObj + ) : + m_setting(setting), + m_cppObj(cppObj) +{ +} + +void +UserStatisticsServiceEventBind::RemoveUserStatisticChangeEvent( + _In_ xbox::services::user_statistics::user_statistics_service& cppObj + ) +{ + cppObj.remove_statistic_changed_handler(m_functionContext); +} + +void UserStatisticsServiceEventBind::StatisticChangeRouter(_In_ const xbox::services::user_statistics::statistic_change_event_args& statisticChangeEventArgs) +{ + UserStatisticsService^ setting = m_setting.Resolve(); + if (setting != nullptr) + { + if (m_cppObj._Xbox_live_context_settings()->use_core_dispatcher_for_event_routing() && Xbox::Services::XboxLiveContextSettings::Dispatcher != nullptr) + { + Xbox::Services::XboxLiveContextSettings::Dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler([setting, statisticChangeEventArgs]() + { + setting->RaiseStatisticChange(ref new StatisticChangeEventArgs(statisticChangeEventArgs)); + })); + } + else + { + setting->RaiseStatisticChange(ref new StatisticChangeEventArgs(statisticChangeEventArgs)); + } + } +} + +void UserStatisticsServiceEventBind::AddUserStatisticsServiceEvent() +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + m_functionContext = m_cppObj.add_statistic_changed_handler([thisWeakPtr](_In_ const xbox::services::user_statistics::statistic_change_event_args& statisticChangeEventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->StatisticChangeRouter(statisticChangeEventArgs); + } + }); +} + +void UserStatisticsService::RaiseStatisticChange(_In_ StatisticChangeEventArgs^ args) +{ + StatisticChanged(this, args); +} + +IAsyncOperation^ +UserStatisticsService::GetSingleUserStatisticsAsync( + _In_ String^ xboxUserId, + _In_ String^ serviceConfigurationId, + _In_ String^ statName + ) +{ + auto task = m_cppObj.get_single_user_statistics( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(statName) + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new UserStatisticsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^ +UserStatisticsService::GetSingleUserStatisticsAsync( + _In_ String^ xboxUserId, + _In_ String^ serviceConfigurationId, + _In_ IVectorView^ statNames + ) +{ + std::vector vecStatNames = UtilsWinRT::CovertVectorViewToStdVectorString(statNames); + auto task = m_cppObj.get_single_user_statistics( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + vecStatNames + ) + .then([](xbox_live_result cppResult) + { + THROW_IF_ERR(cppResult); + return ref new UserStatisticsResult(cppResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + + +IAsyncOperation^>^ +UserStatisticsService::GetMultipleUserStatisticsAsync( +_In_ IVectorView^ xboxUserIds, +_In_ String^ serviceConfigurationId, +_In_ IVectorView^ statNames +) +{ + std::vector vecXboxUserIds = UtilsWinRT::CovertVectorViewToStdVectorString(xboxUserIds); + std::vector vecStatNames = UtilsWinRT::CovertVectorViewToStdVectorString(statNames); + auto task = m_cppObj.get_multiple_user_statistics( + vecXboxUserIds, + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + vecStatNames + ) + .then([](xbox_live_result> cppResults) + { + THROW_IF_ERR(cppResults); + Vector^ results = ref new Platform::Collections::Vector(); + for (auto& cppResult : cppResults.payload()) + { + results->Append(ref new UserStatisticsResult(cppResult)); + } + + return results->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +IAsyncOperation^>^ +UserStatisticsService::GetMultipleUserStatisticsForMultipleServiceConfigurationsAsync( + _In_ IVectorView^ xboxUserIds, + _In_ IVectorView^ requestedServiceConfigurationStatisticsCollection + ) +{ + std::vector vecxboxUserIds = UtilsWinRT::CovertVectorViewToStdVectorString(xboxUserIds); + + std::vector requests; + for(const auto& requestedServiceConfig : requestedServiceConfigurationStatisticsCollection) + { + requests.push_back(requestedServiceConfig->GetCppObj()); + } + + auto task = m_cppObj.get_multiple_user_statistics_for_multiple_service_configurations( + vecxboxUserIds, + requests + ) + .then([](xbox_live_result> cppResults) + { + Vector^ results = ref new Platform::Collections::Vector(); + for (auto& cppResult : cppResults.payload()) + { + results->Append(ref new UserStatisticsResult(cppResult)); + } + + return results->GetView(); + }); + + return ASYNC_FROM_TASK(task); +} + +StatisticChangeSubscription^ +UserStatisticsService::SubscribeToStatisticChange( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName + ) +{ + std::shared_ptr subscription; + auto subscriptionResult = m_cppObj.subscribe_to_statistic_change( + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(statisticName) + ); + + THROW_IF_ERR(subscriptionResult); + + subscription = subscriptionResult.payload(); + + return ref new StatisticChangeSubscription(subscription); +} + +void +UserStatisticsService::UnsubscribeFromStatisticChange( + _In_ StatisticChangeSubscription^ subscription + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(subscription); + + auto unsubscribeResult = m_cppObj.unsubscribe_from_statistic_change( + subscription->GetCppObj() + ); + + THROW_IF_ERR(unsubscribeResult); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END \ No newline at end of file diff --git a/Source/Services/Stats/WinRT/UserStatisticsService_WinRT.h b/Source/Services/Stats/WinRT/UserStatisticsService_WinRT.h new file mode 100644 index 00000000..b599ab73 --- /dev/null +++ b/Source/Services/Stats/WinRT/UserStatisticsService_WinRT.h @@ -0,0 +1,154 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/user_statistics.h" +#include "xsapi/xbox_live_context_settings.h" +#include "RequestedStatistics_WinRT.h" +#include "UserStatisticsResult_WinRT.h" +#include "StatisticChangeSubscription_WinRT.h" +#include "StatisticChangeEventArgs_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_BEGIN + +ref class UserStatisticsService; + +class UserStatisticsServiceEventBind : public std::enable_shared_from_this +{ +public: + UserStatisticsServiceEventBind( + _In_ Platform::WeakReference setting, + _In_ xbox::services::user_statistics::user_statistics_service& cppObj + ); + + void AddUserStatisticsServiceEvent(); + + void RemoveUserStatisticChangeEvent( + _In_ xbox::services::user_statistics::user_statistics_service& cppObj + ); + + void StatisticChangeRouter(_In_ const xbox::services::user_statistics::statistic_change_event_args& statisticChangeEventArgs); + +private: + function_context m_functionContext; + Platform::WeakReference m_setting; + xbox::services::user_statistics::user_statistics_service m_cppObj; +}; + +/// +/// Represents an endpoint that you can use to access the user statistic service. +/// +public ref class UserStatisticsService sealed +{ +public: + /// + /// Registers for statistic change notifications. Event handlers receive a StatisticChangeEventArgs^ object. + /// + event Windows::Foundation::EventHandler^ StatisticChanged; + + /// + /// Get a specified statistic for a specified user. + /// + /// The Xbox User ID of the player to get statistics for. + /// The service configuration ID for the service holding the statistic. + /// The name of the statistic to return. + /// An interface for tracking the progress of the asynchronous call. The result is the requested statistic. + /// Calls V1 GET /users/xuid({xuid})/scids/{scid}/stats/{statname1} + [Windows::Foundation::Metadata::DefaultOverloadAttribute] + Windows::Foundation::IAsyncOperation^ + GetSingleUserStatisticsAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName + ); + + /// + /// Get specified statictics for a single user. + /// + /// The Xbox User ID of the player to get statistics for. + /// The service configuration ID of the service holding the statistics. + /// A collection of statistic names to lookup. + /// An interface for tracking the progress of the asynchronous call. The result is the requested statisitics. + /// Only statistics with values are returned. For example, if you ask for 3 statistic names and only 2 have values, + /// only 2 statistics are returned by the service. + /// Calls V1 GET /users/xuid({xuid})/scids/{scid}/stats/{statname1},...,{statnameN} + Windows::Foundation::IAsyncOperation^ + GetSingleUserStatisticsAsync( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Windows::Foundation::Collections::IVectorView^ statisticNames + ); + + /// + /// Get statistics for multiple users. + /// + /// A list of the user Xbox user IDs to get stats for. + /// The service configuration ID (SCID) of the title + /// A collection of statistic names to lookup. + /// An interface for tracking the progress of the asynchronous call. The result is a collection + /// of user statistics results. + /// Only statistics with values are returned. For example, if you ask for 3 statistic names and only 2 have values, + /// only 2 statistics are returned by the service. + /// Calls V1 POST /batch + Windows::Foundation::IAsyncOperation^>^ + GetMultipleUserStatisticsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Platform::String^ serviceConfigurationId, + _In_ Windows::Foundation::Collections::IVectorView^ statisticNames + ); + + /// + /// Get statistics for users across different Service configurations. + /// + /// A list of the user Xbox user ID to get stats for. + /// A list of the service config IDs and its associated array of statistics. + /// An interface for tracking the progress of the asynchronous call. The result is a collection of user statistics results. + /// Calls V1 POST /batch + Windows::Foundation::IAsyncOperation^>^ + GetMultipleUserStatisticsForMultipleServiceConfigurationsAsync( + _In_ Windows::Foundation::Collections::IVectorView^ xboxUserIds, + _In_ Windows::Foundation::Collections::IVectorView^ requestedServiceConfigurationStatisticsCollection + ); + + /// + /// Subscribes to statistic update notifications via the StatisticChanged event. + /// + /// The Xbox User ID of the player requesting the subscription. + /// The service configuration ID (SCID) of the subscription. + /// The name of the statistic to subscribe to. + /// A subscription object that contains the state of the subscription. + /// You can register an event handler for statistic changes by using the StatisticChanged event. + StatisticChangeSubscription^ SubscribeToStatisticChange( + _In_ Platform::String^ xboxUserId, + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ statisticName + ); + + /// + /// Unsubscribes a previously created statistic change subscription. + /// + /// The subscription object to unsubscribe. + void UnsubscribeFromStatisticChange( + _In_ StatisticChangeSubscription^ subscription + ); + +internal: + UserStatisticsService( + _In_ xbox::services::user_statistics::user_statistics_service cppObj + ); + + void RaiseStatisticChange(_In_ StatisticChangeEventArgs^ args); +private: + ~UserStatisticsService(); + xbox::services::user_statistics::user_statistics_service m_cppObj; + std::shared_ptr m_userStatisticsServiceEventBind; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_END diff --git a/Source/Services/Stats/requested_statistics.cpp b/Source/Services/Stats/requested_statistics.cpp new file mode 100644 index 00000000..d3d9bbc5 --- /dev/null +++ b/Source/Services/Stats/requested_statistics.cpp @@ -0,0 +1,34 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +requested_statistics::requested_statistics( + _In_ string_t serviceConfigurationId, + _In_ std::vector statistics + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_statistics(std::move(statistics)) +{ +} + +const string_t& requested_statistics::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const std::vector& requested_statistics::statistics() const +{ + return m_statistics; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/service_configuration_statistic.cpp b/Source/Services/Stats/service_configuration_statistic.cpp new file mode 100644 index 00000000..605431ff --- /dev/null +++ b/Source/Services/Stats/service_configuration_statistic.cpp @@ -0,0 +1,68 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +service_configuration_statistic::service_configuration_statistic() +{ +} + +service_configuration_statistic::service_configuration_statistic( + _In_ string_t serviceConfigurationId, + _In_ std::vector stats + ) : + m_serviceConfigurationId(serviceConfigurationId), + m_stats(stats) +{ +} + +const string_t& +service_configuration_statistic::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +void +service_configuration_statistic::_Set_input_service_configuration_id(string_t serviceConfigId) +{ + m_serviceConfigurationId = std::move(serviceConfigId); +} + +const std::vector& +service_configuration_statistic::statistics() const +{ + return m_stats; +} + +xbox_live_result +service_configuration_statistic::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = service_configuration_statistic( + utils::extract_json_string(json, _T("scid"), errc, true), + utils::extract_json_vector(statistic::_Deserialize, json, _T("stats"), errc, true) + ); + + return xbox_live_result( + result, + errc, + "" + ); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/statistic.cpp b/Source/Services/Stats/statistic.cpp new file mode 100644 index 00000000..8d3b0bbb --- /dev/null +++ b/Source/Services/Stats/statistic.cpp @@ -0,0 +1,94 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +statistic::statistic() +{ +} + +// class statistic +statistic::statistic( + _In_ string_t name, + _In_ string_t type, + _In_ string_t value + ) : + m_statName(std::move(name)), + m_statType(std::move(type)), + m_value(std::move(value)) +{ +} + +const string_t& +statistic::statistic_name() const +{ + return m_statName; +} + +const string_t& +statistic::statistic_type() const +{ + return m_statType; +} + +const string_t& +statistic::value() const +{ + return m_value; +} + +void +statistic::_Set_statistic_name( + _In_ string_t name + ) +{ + m_statName = std::move(name); +} + +void +statistic::_Set_statistic_type( + _In_ string_t type + ) +{ + m_statType = std::move(type); +} + +void +statistic::_Set_statistic_value( + _In_ string_t value + ) +{ + m_value = std::move(value); +} + +xbox_live_result +statistic::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto result = statistic( + utils::extract_json_string(json, _T("statname"), errc, true), + utils::extract_json_string(json, _T("type"), errc, true), + utils::extract_json_string(json, _T("value"), errc, true) + ); + + return xbox_live_result( + result, + errc, + "" + ); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/statistic_change_event_args.cpp b/Source/Services/Stats/statistic_change_event_args.cpp new file mode 100644 index 00000000..1feb8372 --- /dev/null +++ b/Source/Services/Stats/statistic_change_event_args.cpp @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +statistic_change_event_args::statistic_change_event_args() +{ +} + +statistic_change_event_args::statistic_change_event_args( + _In_ string_t xboxUserId, + _In_ string_t serviceConfigurationId, + _In_ statistic latestStatistic + ) : + m_xboxUserId(std::move(xboxUserId)), + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_latestStatistic(std::move(latestStatistic)) +{ +} + +const string_t& +statistic_change_event_args::xbox_user_id() const +{ + return m_xboxUserId; +} + +const string_t& +statistic_change_event_args::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const statistic& +statistic_change_event_args::latest_statistic() const +{ + return m_latestStatistic; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/statistic_change_subscription.cpp b/Source/Services/Stats/statistic_change_subscription.cpp new file mode 100644 index 00000000..29192bab --- /dev/null +++ b/Source/Services/Stats/statistic_change_subscription.cpp @@ -0,0 +1,157 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +statistic_change_subscription::statistic_change_subscription( + _In_ string_t xboxUserId, + _In_ string_t serviceConfigurationId, + _In_ xbox::services::user_statistics::statistic initialStatistic, + _In_ std::function handler, + _In_ std::function subscriptionErrorHandler + ) : + real_time_activity_subscription(subscriptionErrorHandler), + m_xboxUserId(std::move(xboxUserId)), + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_statistic(std::move(initialStatistic)), + m_statisticChangeHandler(handler) +{ + XSAPI_ASSERT(handler != nullptr); + + stringstream_t uriPath; + uriPath << _T("https://userstats.xboxlive.com/users/xuid(") << m_xboxUserId << _T(")/scids/") << m_serviceConfigurationId << _T("/stats/") << m_statistic.statistic_name(); + m_resourceUri = uriPath.str(); +} + +void +statistic_change_subscription::on_subscription_created( + _In_ uint32_t id, + _In_ const web::json::value& data + ) +{ + real_time_activity_subscription::on_subscription_created( + id, + data + ); + + if (m_statisticChangeHandler && !data.is_null()) + { + std::error_code errc; + m_statistic._Set_statistic_name( + utils::extract_json_string( + data, + _T("name") + ) + ); + + m_statistic._Set_statistic_type( + utils::extract_json_string( + data, + _T("type") + ) + ); + + string_t value; + web::json::value field(utils::extract_json_field(data, _T("value"), false)); + if (field.is_integer()) + { + stringstream_t stream; + stream << field.as_integer(); + value = stream.str(); + } + else if (field.is_string()) + { + value = field.as_string(); + } + + m_statistic._Set_statistic_value( + value + ); + + m_statisticChangeHandler( + statistic_change_event_args( + m_xboxUserId, + m_serviceConfigurationId, + m_statistic + ) + ); + } + else + { + if (m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON not found on subscription" + ) + ); + } + } +} + +void +statistic_change_subscription::on_event_received( + _In_ const web::json::value& data + ) +{ + statistic_change_event_args statisticChangeEventArgs; + + if (m_statisticChangeHandler && !data.is_null()) + { + m_statistic._Set_statistic_value( + data.serialize() + ); + + m_statisticChangeHandler( + statistic_change_event_args( + m_xboxUserId, + m_serviceConfigurationId, + m_statistic + ) + ); + } + else + { + if (m_subscriptionErrorHandler != nullptr) + { + m_subscriptionErrorHandler( + xbox::services::real_time_activity::real_time_activity_subscription_error_event_args( + *this, + xbox_live_error_code::json_error, + "JSON not found on change event" + ) + ); + } + } +} + +const string_t& +statistic_change_subscription::xbox_user_id() const +{ + return m_xboxUserId; +} + +const string_t& +statistic_change_subscription::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const xbox::services::user_statistics::statistic& +statistic_change_subscription::statistic() const +{ + return m_statistic; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/user_statistics_internal.h b/Source/Services/Stats/user_statistics_internal.h new file mode 100644 index 00000000..397ac340 --- /dev/null +++ b/Source/Services/Stats/user_statistics_internal.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "system_internal.h" +namespace xbox { namespace services { namespace user_statistics { + +class user_statistics_service_impl : public std::enable_shared_from_this +{ +public: + user_statistics_service_impl( + _In_ std::shared_ptr realTimeActivityService + ); + + ~user_statistics_service_impl(); + + xbox_live_result> subscribe_to_statistic_change( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& statisticName + ); + + xbox_live_result unsubscribe_from_statistic_change( + _In_ std::shared_ptr subscription + ); + + function_context add_statistic_changed_handler(_In_ std::function handler); + + void remove_statistic_changed_handler(_In_ function_context context); + +private: + void statistic_changed(_In_ const statistic_change_event_args& eventArgs); + + xbox::services::system::xbox_live_mutex m_statisticHandlerLock; + std::shared_ptr m_realTimeActivityService; + std::unordered_map> m_statisticChangeHandler; + function_context m_statisticChangeHandlerCounter; +}; + +}}} \ No newline at end of file diff --git a/Source/Services/Stats/user_statistics_result.cpp b/Source/Services/Stats/user_statistics_result.cpp new file mode 100644 index 00000000..d64d32c4 --- /dev/null +++ b/Source/Services/Stats/user_statistics_result.cpp @@ -0,0 +1,77 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" +#include "utils.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +user_statistics_result::user_statistics_result() +{ +} + +// class user_statistics_result +user_statistics_result::user_statistics_result( + _In_ string_t xboxUserId, + _In_ std::vector serviceConfigStatistics + ) : + m_xboxUserId(std::move(xboxUserId)), + m_serviceConfigStatistics(std::move(serviceConfigStatistics)) +{} + +const string_t& +user_statistics_result::xbox_user_id() const +{ + return m_xboxUserId; +} + +const std::vector& +user_statistics_result::service_configuration_statistics() const +{ + return m_serviceConfigStatistics; +} + +void +user_statistics_result::_Set_input_service_configuration_id(string_t serviceConfigId) +{ + for (auto& stat : m_serviceConfigStatistics) + { + stat._Set_input_service_configuration_id(serviceConfigId); + } +} + +xbox_live_result +user_statistics_result::_Deserialize(_In_ const web::json::value& json) +{ + if (json.is_null()) return xbox_live_result(xbox_live_error_code::json_error, "Json is null or empty"); + + std::error_code errc = xbox_live_error_code::no_error; + std::vector serviceConfigStatisticses = + utils::extract_json_vector(service_configuration_statistic::_Deserialize, json, _T("scids"), errc, false); + if (serviceConfigStatisticses.size() == 0) + { + std::vector statistics = utils::extract_json_vector(statistic::_Deserialize, json, _T("stats"), errc, false); + service_configuration_statistic serviceConfigStatistics(string_t(), statistics); + serviceConfigStatisticses.push_back(serviceConfigStatistics); + } + + auto result = user_statistics_result( + utils::extract_json_string(json, _T("xuid"), errc, true), + serviceConfigStatisticses + ); + + return xbox_live_result( + result, + errc, + "" + ); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/user_statistics_service.cpp b/Source/Services/Stats/user_statistics_service.cpp new file mode 100644 index 00000000..162ab777 --- /dev/null +++ b/Source/Services/Stats/user_statistics_service.cpp @@ -0,0 +1,268 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include +#include "xsapi/user_statistics.h" +#include "xbox_system_factory.h" +#include "utils.h" +#include "user_statistics_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +user_statistics_service::user_statistics_service() +{ +} + +user_statistics_service::user_statistics_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ std::shared_ptr rtaService + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)), + m_userStatisticsServiceImpl(std::make_shared(rtaService)) +{ +} + +pplx::task> +user_statistics_service::get_single_user_statistics( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& statisticName + ) +{ + std::vector statistics; + statistics.push_back(statisticName); + return get_single_user_statistics( + xboxUserId, + serviceConfigurationId, + statistics + ); +} + +pplx::task> +user_statistics_service::get_single_user_statistics( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const std::vector& statisticNames + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(xboxUserId, user_statistics_result, "xboxUserId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, user_statistics_result, "serviceConfigurationId is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(xboxUserId, user_statistics_result, "xboxUserId is empty"); + auto subPath = user_stats_sub_path( + xboxUserId, + serviceConfigurationId, + statisticNames + ); + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("userstats"), m_appConfig), + subPath, + xbox_live_api::get_single_user_statistics + ); + httpCall->set_xbox_contract_version_header_value(_T("1")); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([serviceConfigurationId](std::shared_ptr response) + { + auto result = user_statistics_result::_Deserialize(response->response_body_json()); + auto& userStatisticsResult = result.payload(); + userStatisticsResult._Set_input_service_configuration_id(serviceConfigurationId); + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task>> +user_statistics_service::get_multiple_user_statistics( + _In_ const std::vector& xboxUserIds, + _In_ const string_t& serviceConfigurationId, + _In_ std::vector& statisticNames + ) +{ + std::vector statistics; + statistics.push_back(requested_statistics(serviceConfigurationId, statisticNames)); + return get_multiple_user_statistics_for_multiple_service_configurations( + xboxUserIds, + statistics + ); +} + +pplx::task>> +user_statistics_service::get_multiple_user_statistics_for_multiple_service_configurations( + _In_ const std::vector& xboxUserIds, + _In_ const std::vector& requestedServiceConfigurationStatisticsCollection + ) +{ + // Set request body to something like: + //{ + // "requestedusers": + // [ + // "1234567890123460", + // "1234567890123234" + // ], + // "requestedscids": + // [ + // { + // "scid": "c402ff50-3e76-11e2-a25f-0800200c1212", + // "requestedstats": + // [ + // "Game4FirefightKills", + // "Game4FirefightHeadshots" + // ] + // }, + // { + // "scid": "c402ff50-3e76-11e2-a25f-0800200c0343", + // "requestedstats": + // [ + // "OverallGameKills", + // "GameHeadshots" + // ] + // } + // ] + //} + + RETURN_TASK_CPP_INVALIDARGUMENT_IF(xboxUserIds.empty(), std::vector, "xboxUserIds are empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(requestedServiceConfigurationStatisticsCollection.empty(), std::vector, "requestedServiceConfigurationStatisticsCollection are empty"); + + web::json::value rootJson; + rootJson[_T("requestedusers")] = utils::serialize_vector(utils::json_string_serializer, xboxUserIds); + + //requestedscids + web::json::value requestedscidsJson = web::json::value::array(); + uint32_t i = 0; + for (const auto& request : requestedServiceConfigurationStatisticsCollection) + { + web::json::value requestedJson; + requestedJson[_T("scid")] = web::json::value::string(request.service_configuration_id()); + + web::json::value requestedstatsJson = web::json::value::array(); + uint32_t j = 0; + for (const auto& stat : request.statistics()) + { + requestedstatsJson[j++] = web::json::value::string(stat); + } + requestedJson[_T("requestedstats")] = requestedstatsJson; + + requestedscidsJson[i++] = requestedJson; + } + + rootJson[_T("requestedscids")] = requestedscidsJson; + + std::shared_ptr httpCall = xbox::services::system::xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("POST"), + utils::create_xboxlive_endpoint(_T("userstats"), m_appConfig), + _T("/batch?operation=read"), + xbox_live_api::get_multiple_user_statistics_for_multiple_service_configurations + ); + httpCall->set_xbox_contract_version_header_value(_T("1")); + httpCall->set_request_body(rootJson.serialize()); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + std::error_code errc = xbox_live_error_code::no_error; + auto userStatistics = utils::extract_xbox_live_result_json_vector( + user_statistics_result::_Deserialize, + response->response_body_json(), + _T("users"), + errc, + true + ); + + return utils::generate_xbox_live_result>( + userStatistics, + response + ); + }); + + return utils::create_exception_free_task>( + task + ); +} + +string_t +user_statistics_service::user_stats_sub_path( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ std::vector statNames + ) +{ + stringstream_t ss; + ss << _T("/users/xuid(") << xboxUserId << _T(")/scids/") << serviceConfigurationId << _T("/stats/"); + + auto& last = statNames.back(); + for (const string_t& statName : statNames) + { + ss << statName; + if (&statName != &last) + { + ss << _T(","); + } + } + + return ss.str(); +} + +function_context +user_statistics_service::add_statistic_changed_handler( + _In_ std::function handler + ) +{ + return m_userStatisticsServiceImpl->add_statistic_changed_handler( + std::move(handler) + ); +} + +void +user_statistics_service::remove_statistic_changed_handler( + _In_ function_context context + ) +{ + return m_userStatisticsServiceImpl->remove_statistic_changed_handler( + context + ); +} + +xbox_live_result> +user_statistics_service::subscribe_to_statistic_change( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& statisticName + ) +{ + return m_userStatisticsServiceImpl->subscribe_to_statistic_change( + xboxUserId, + serviceConfigurationId, + statisticName + ); +} + +xbox_live_result +user_statistics_service::unsubscribe_from_statistic_change( + _In_ std::shared_ptr subscription + ) +{ + return m_userStatisticsServiceImpl->unsubscribe_from_statistic_change(subscription); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/Stats/user_statistics_service_impl.cpp b/Source/Services/Stats/user_statistics_service_impl.cpp new file mode 100644 index 00000000..d0b419bb --- /dev/null +++ b/Source/Services/Stats/user_statistics_service_impl.cpp @@ -0,0 +1,138 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/user_statistics.h" +#include "user_statistics_internal.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_BEGIN + +user_statistics_service_impl::user_statistics_service_impl( + _In_ std::shared_ptr realTimeActivityService + ) : + m_realTimeActivityService(realTimeActivityService), + m_statisticChangeHandlerCounter(0) +{ +} + +user_statistics_service_impl::~user_statistics_service_impl() +{ + m_statisticChangeHandler.clear(); +} + +function_context +user_statistics_service_impl::add_statistic_changed_handler( + _In_ std::function handler + ) +{ + std::lock_guard lock(m_statisticHandlerLock.get()); + + function_context context = -1; + if (handler != nullptr) + { + context = ++m_statisticChangeHandlerCounter; + m_statisticChangeHandler[m_statisticChangeHandlerCounter] = std::move(handler); + } + + return context; +} + +void +user_statistics_service_impl::remove_statistic_changed_handler( + _In_ function_context context + ) +{ + std::lock_guard lock(m_statisticHandlerLock.get()); + m_statisticChangeHandler.erase(context); +} + +void +user_statistics_service_impl::statistic_changed( + _In_ const statistic_change_event_args& eventArgs + ) +{ + std::unordered_map> statisticChangeHandlerCopy; + { + std::lock_guard lock(m_statisticHandlerLock.get()); + statisticChangeHandlerCopy = m_statisticChangeHandler; + } + + for (auto& handler : statisticChangeHandlerCopy) + { + XSAPI_ASSERT(handler.second != nullptr); + if (handler.second != nullptr) + { + try + { + handler.second(eventArgs); + } + catch (...) + { + LOG_ERROR("statistic_changed handler threw an exception"); + } + } + } +} + +xbox_live_result> +user_statistics_service_impl::subscribe_to_statistic_change( + _In_ const string_t& xboxUserId, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& statisticName + ) +{ + std::weak_ptr thisWeakPtr = shared_from_this(); + + std::shared_ptr statChangeSub = std::make_shared( + xboxUserId, + serviceConfigurationId, + statistic( + statisticName, + string_t(), + string_t() + ), + ([thisWeakPtr](const statistic_change_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->statistic_changed(eventArgs); + } + }), + ([thisWeakPtr](const xbox::services::real_time_activity::real_time_activity_subscription_error_event_args& eventArgs) + { + std::shared_ptr pThis(thisWeakPtr.lock()); + if (pThis != nullptr) + { + pThis->m_realTimeActivityService->_Trigger_subscription_error(eventArgs); + } + }) + ); + + auto subscriptionSucceeded = m_realTimeActivityService->_Add_subscription( + statChangeSub + ); + + if (!subscriptionSucceeded.err()) + { + return xbox_live_result>(statChangeSub); + } + + return xbox_live_result>(subscriptionSucceeded.err(), subscriptionSucceeded.err_message()); +} + +xbox_live_result +user_statistics_service_impl::unsubscribe_from_statistic_change( + _In_ std::shared_ptr subscription + ) +{ + return m_realTimeActivityService->_Remove_subscription(subscription); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_USERSTATISTICS_CPP_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.cpp b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.cpp new file mode 100644 index 00000000..cb5c5d05 --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.cpp @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TitleStorageBlobMetadataResult_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::title_storage; +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +TitleStorageBlobMetadataResult::TitleStorageBlobMetadataResult( + _In_ xbox::services::title_storage::title_storage_blob_metadata_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + m_items = Xbox::Services::System::UtilsWinRT::CreatePlatformVectorFromStdVectorObj( + m_cppObj.items() + )->GetView(); +} + +Windows::Foundation::Collections::IVectorView^ +TitleStorageBlobMetadataResult::Items::get() +{ + return m_items; +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageBlobMetadataResult::GetNextAsync( + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_next(maxItems) + .then([](xbox::services::xbox_live_result metadataResult) + { + THROW_IF_ERR(metadataResult); + return ref new TitleStorageBlobMetadataResult(metadataResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.h new file mode 100644 index 00000000..e8651477 --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadataResult_WinRT.h @@ -0,0 +1,49 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/title_storage.h" +#include "TitleStorageBlobMetadata_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// +/// Metadata about blob data returned from the cloud. +/// +public ref class TitleStorageBlobMetadataResult sealed +{ +public: + /// + /// The collection of blob metadata objects returned by a service metadata request. + /// + property Windows::Foundation::Collections::IVectorView^ Items { Windows::Foundation::Collections::IVectorView^ get(); } + + /// + /// Gets the next page of blob metadata results. + /// + /// The maximum number of items the result can contain. Pass 0 to request all items. + /// A TitleStorageBlobMetadataResult object containing the next page of TitleStorageBlobMetadata objects. + Windows::Foundation::IAsyncOperation^ GetNextAsync( + _In_ uint32 maxItems + ); + + /// + /// Indicates if there is additional data to retrieve from a GetNextAsync call + /// + DEFINE_PROP_GET_OBJ(HasNext, has_next, bool); + +internal: + TitleStorageBlobMetadataResult(_In_ xbox::services::title_storage::title_storage_blob_metadata_result cppObj); + +private: + xbox::services::title_storage::title_storage_blob_metadata_result m_cppObj; + Windows::Foundation::Collections::IVectorView^ m_items; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.cpp b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.cpp new file mode 100644 index 00000000..efd58a6b --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.cpp @@ -0,0 +1,124 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TitleStorageBlobMetadata_WinRT.h" +#include "Utils_WinRT.h" + +using namespace xbox::services::title_storage; +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +TitleStorageBlobMetadata::TitleStorageBlobMetadata( + _In_ title_storage_blob_metadata cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +TitleStorageBlobMetadata::TitleStorageBlobMetadata( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_opt_ Platform::String^ xboxUserId + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj = title_storage_blob_metadata( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + static_cast(storageType), + STRING_T_FROM_PLATFORM_STRING(blobPath), + static_cast(blobType), + STRING_T_FROM_PLATFORM_STRING(xboxUserId) + ); + ); +} + +TitleStorageBlobMetadata::TitleStorageBlobMetadata( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_opt_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ displayName, + _In_opt_ Platform::String^ eTag + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj = title_storage_blob_metadata( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + static_cast(storageType), + STRING_T_FROM_PLATFORM_STRING(blobPath), + static_cast(blobType), + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(displayName), + STRING_T_FROM_PLATFORM_STRING(eTag) + ); + ); +} + +TitleStorageBlobMetadata::TitleStorageBlobMetadata( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_opt_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ displayName, + _In_opt_ Platform::String^ eTag, + _In_ Windows::Foundation::DateTime clientTimestamp + ) +{ + CONVERT_STD_EXCEPTION( + m_cppObj = title_storage_blob_metadata( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + static_cast(storageType), + STRING_T_FROM_PLATFORM_STRING(blobPath), + static_cast(blobType), + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + STRING_T_FROM_PLATFORM_STRING(displayName), + STRING_T_FROM_PLATFORM_STRING(eTag), + Xbox::Services::System::UtilsWinRT::ConvertDateTimeToNativeDateTime(clientTimestamp) + ); + ); +} + +TitleStorageBlobMetadata^ +TitleStorageBlobMetadata::CreateTitleStorageBlobMetadataForSessionStorage( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_ Platform::String^ multiplayerSessionTemplateName, + _In_ Platform::String^ multiplayerSessionName, + _In_opt_ Platform::String^ displayName, + _In_opt_ Platform::String^ eTag + ) +{ + title_storage_blob_metadata cppObj; + CONVERT_STD_EXCEPTION( + cppObj = title_storage_blob_metadata::create_title_storage_blob_metadata_for_session_storage( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(blobPath), + static_cast(blobType), + STRING_T_FROM_PLATFORM_STRING(multiplayerSessionTemplateName), + STRING_T_FROM_PLATFORM_STRING(multiplayerSessionName), + STRING_T_FROM_PLATFORM_STRING(displayName), + STRING_T_FROM_PLATFORM_STRING(eTag) + ); + ); + + return ref new TitleStorageBlobMetadata(cppObj); +} + +xbox::services::title_storage::title_storage_blob_metadata +TitleStorageBlobMetadata::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.h new file mode 100644 index 00000000..1a5daad8 --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobMetadata_WinRT.h @@ -0,0 +1,186 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/title_storage.h" +#include "Macros_WinRT.h" +#include "TitleStorageType_WinRT.h" +#include "TitleStorageBlobType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// +/// Metadata about a blob. +/// +public ref class TitleStorageBlobMetadata sealed +{ +public: + /// + /// Initializes a new instance of the TitleStorageBlobMetadata class with the minimum arguments. + /// + /// The service configuration ID (SCID) of the title + /// The TitleStorageType to get blob metadata objects for. Valid values are TrustedPlatormStorage, JsonStorage and GlobalStorage. + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The Xbox User ID of the title storage to enumerate. Ignored when dealing with GlobalStorage, so passing nullptr is acceptable in that case. (Optional) + /// + /// All other properties of this class are optional. To initialize optional properties, use the other constructors. + /// ClientTimestamp.UniversalTime is initialized to 0. Length is initialized to 0. + /// TitleStorageBlobMetadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + TitleStorageBlobMetadata( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_opt_ Platform::String^ xboxUserId + ); + + /// + /// Initializes a new instance of the TitleStorageBlobMetadata class including support for all optional properties except ClientTimestamp. + /// + /// The service configuration ID (SCID) of the title + /// The TitleStorageType to get blob metadata objects for. Valid values are TrustedPlatormStorage, JsonStorage and GlobalStorage. + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The Xbox User ID of the title storage to enumerate. Ignored when dealing with GlobalStorage, so passing nullptr is acceptable in that case. (Optional) + /// A display name suitable for displaying to the user. (Optional) + /// An ETag value to be associated with this instance. It is used for upload, download and delete operations. (Optional) + /// + /// ClientTimestamp.UniversalTime is initialized to 0. Length is initialized to 0. + /// TitleStorageBlobMetadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + TitleStorageBlobMetadata( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_opt_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ displayName, + _In_opt_ Platform::String^ eTag + ); + + /// + /// Initializes a new instance of the TitleStorageBlobMetadata class including support for all optional properties. + /// + /// The service configuration ID (SCID) of the title + /// The TitleStorageType to get blob metadata objects for. Valid values are TrustedPlatormStorage, JsonStorage and GlobalStorage. + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json". + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The Xbox User ID of the title storage to enumerate. Ignored when dealing with GlobalStorage, so passing nullptr is acceptable in that case. (Optional) + /// A display name suitable for displaying to the user. (Optional) + /// An ETag value to be associated with this instance. It is used for upload, download and delete operations. (Optional) + /// A client provided timestamp value to be associated with this instance. + /// + /// Length is initialized to 0. + /// TitleStorageBlobMetadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + TitleStorageBlobMetadata( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_opt_ Platform::String^ xboxUserId, + _In_opt_ Platform::String^ displayName, + _In_opt_ Platform::String^ eTag, + _In_ Windows::Foundation::DateTime clientTimestamp + ); + + /// + /// Creates metadata for a blob for session storage, including support for all optional properties except ClientTimestamp. + /// + /// The service configuration ID (SCID) of the title + /// The full path to to the blob. examples: "gameconfig.json" and "user/settings/playerconfiguration.json" + /// The TitleStorageBlobType of this object. Valid values are Binary, Json and Config. + /// The multiplayer session template name associated with this object + /// The multiplayer session name associated with this object + /// A display name suitable for displaying to the user. (Optional) + /// An ETag value to be associated with this instance. It is used for upload, download and delete operations. (Optional) + /// + /// A new instance of the TitleStorageBlobMetadata class for SessionStorage. + /// + /// + /// ClientTimestamp.UniversalTime is initialized to 0. Length is initialized to 0. + /// TitleStorageBlobMetadata objects retrieved using TitleStorageService::GetBlobMetadataAsync will have current Length and ETag values. + /// + static TitleStorageBlobMetadata^ CreateTitleStorageBlobMetadataForSessionStorage( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ blobPath, + _In_ TitleStorageBlobType blobType, + _In_ Platform::String^ multiplayerSessionTemplateName, + _In_ Platform::String^ multiplayerSessionName, + _In_opt_ Platform::String^ displayName, + _In_opt_ Platform::String^ eTag + ); + + /// + /// The blob path is a unique string that conforms to a SubPath\file format. For example: "alpha\beta\blob.txt". + /// + DEFINE_PROP_GET_STR_OBJ(BlobPath, blob_path); + + /// + /// The type of storage used by the blob. Possible values are: Binary, Json, and Config. + /// + DEFINE_PROP_GET_ENUM_OBJ(BlobType, blob_type, TitleStorageBlobType); + + /// + /// The type of storage that contains the blob. + /// + DEFINE_PROP_GET_ENUM_OBJ(StorageType, storage_type, TitleStorageType); + + /// + /// [optional] The friendly display name to show in app UI. + /// + DEFINE_PROP_GET_STR_OBJ(DisplayName, display_name); + + /// + /// The ETag for the file used in read and write requests. + /// Etags are used to determine if a file have been updated. Each time the file is changes, a new ETag is applied by the service. + /// + DEFINE_PROP_GET_STR_OBJ(ETag, e_tag); + + /// + /// [optional] The timestamp assigned for the blob by the client. + /// + DEFINE_PROP_GETSET_DATETIME_OBJ(ClientTimestamp, client_timestamp); + + /// + /// Gets the number of bytes of the blob data. + /// + DEFINE_PROP_GET_OBJ(Length, length, uint64); + + /// + /// The service configuration ID associated with this blob data. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The Xbox User ID of the player that this file belongs to. + /// This value is null for Global and Session files. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The multiplayer session template name this file belongs to if the StorageType is SessionStorage, otherwise null. + /// + DEFINE_PROP_GET_STR_OBJ(MultiplayerSessionTemplateName, multiplayer_session_template_name); + + /// + /// The multiplayer session name this file belongs to if the StorageType is SessionStorage, otherwise null. + /// + DEFINE_PROP_GET_STR_OBJ(MultiplayerSessionName, multiplayer_session_name); + +internal: + TitleStorageBlobMetadata(_In_ xbox::services::title_storage::title_storage_blob_metadata cppObj); + xbox::services::title_storage::title_storage_blob_metadata GetCppObj() const; + +private: + xbox::services::title_storage::title_storage_blob_metadata m_cppObj; +}; +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.cpp b/Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.cpp new file mode 100644 index 00000000..2f999dde --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.cpp @@ -0,0 +1,49 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TitleStorageBlobResult_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +TitleStorageBlobResult::TitleStorageBlobResult( + _In_ xbox::services::title_storage::title_storage_blob_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ + auto nativeBlobBuffer = m_cppObj.blob_buffer(); + auto writer = ref new Windows::Storage::Streams::DataWriter(); + + auto nativeBlobBufferSize = nativeBlobBuffer->size(); + if(nativeBlobBufferSize <= UINT32_MAX) + { + writer->WriteBytes(Platform::ArrayReference(&(nativeBlobBuffer->at(0)), static_cast(nativeBlobBufferSize))); + } + else + { + throw ref new Platform::OutOfBoundsException(L"Stream size is too large"); + } + + m_blobBuffer = writer->DetachBuffer(); + m_blobMetadata = ref new TitleStorageBlobMetadata(m_cppObj.blob_metadata()); +} + +Windows::Storage::Streams::IBuffer^ +TitleStorageBlobResult::BlobBuffer::get() +{ + return m_blobBuffer; +} + +TitleStorageBlobMetadata^ +TitleStorageBlobResult::BlobMetadata::get() +{ + return m_blobMetadata; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.h new file mode 100644 index 00000000..655efbf0 --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobResult_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/title_storage.h" +#include "TitleStorageBlobMetadata_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// +/// Blob data returned from the cloud. +/// +public ref class TitleStorageBlobResult sealed +{ +public: + /// + /// The contents of the title storage blob. + /// + property Windows::Storage::Streams::IBuffer^ BlobBuffer { Windows::Storage::Streams::IBuffer^ get(); } + + /// + /// Updated TitleStorageBlobMetadata object following an upload or download. + /// + property TitleStorageBlobMetadata^ BlobMetadata { TitleStorageBlobMetadata^ get(); }; + +internal: + TitleStorageBlobResult(_In_ xbox::services::title_storage::title_storage_blob_result cppObj); + +private: + xbox::services::title_storage::title_storage_blob_result m_cppObj; + Windows::Storage::Streams::IBuffer^ m_blobBuffer; + TitleStorageBlobMetadata^ m_blobMetadata; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageBlobType_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageBlobType_WinRT.h new file mode 100644 index 00000000..fe63b29d --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageBlobType_WinRT.h @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// Defines values that indicate title storage blob type. +public enum class TitleStorageBlobType +{ + /// Unknown blob type. + Unknown = xbox::services::title_storage::title_storage_blob_type::unknown, + + /// Binary blob type. + Binary = xbox::services::title_storage::title_storage_blob_type::binary, + + /// JSON blob type. + Json = xbox::services::title_storage::title_storage_blob_type::json, + + /// Configuration information blob type. + Config = xbox::services::title_storage::title_storage_blob_type::config +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageETagMatchCondition_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageETagMatchCondition_WinRT.h new file mode 100644 index 00000000..79233f21 --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageETagMatchCondition_WinRT.h @@ -0,0 +1,27 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// Defines values that indicate the ETag match condition used when downloading, uploading or deleting title storage data. +public enum class TitleStorageETagMatchCondition +{ + /// There is no match condition, perform the request regardless of the ETag value. + NotUsed = xbox::services::title_storage::title_storage_e_tag_match_condition::not_used, + + /// Perform the request if the Etag value specified matches the service value. + IfMatch = xbox::services::title_storage::title_storage_e_tag_match_condition::if_match, + + /// Perform the request if the Etag value specified does not match the service value. + IfNotMatch = xbox::services::title_storage::title_storage_e_tag_match_condition::if_not_match +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.cpp b/Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.cpp new file mode 100644 index 00000000..2928788f --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.cpp @@ -0,0 +1,23 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "pch.h" +#include "TitleStorageQuota_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +TitleStorageQuota::TitleStorageQuota( + _In_ xbox::services::title_storage::title_storage_quota cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.h new file mode 100644 index 00000000..a4769ec8 --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageQuota_WinRT.h @@ -0,0 +1,65 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/title_storage.h" +#include "TitleStorageType_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// +/// Returns the amount of storage space allocated and used. +/// +public ref class TitleStorageQuota sealed +{ +public: + /// + /// The service configuration ID associated with the quota. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + + /// + /// The type of storage counted in the quota. + /// + DEFINE_PROP_GET_ENUM_OBJ(StorageType, storage_type, TitleStorageType); + + /// + /// The Xbox User ID associated with the quota if StorageType is TrustedPlatformStorage or JsonStorage, otherwise null. + /// + DEFINE_PROP_GET_STR_OBJ(XboxUserId, xbox_user_id); + + /// + /// The multiplayer session template name associated with the quota if StorageType is SessionStorage, otherwise null. + /// + DEFINE_PROP_GET_STR_OBJ(MultiplayerSessionTemplateName, multiplayer_session_template_name); + + /// + /// The multiplayer session name associated with the quota if StorageType is SessionStorage, otherwise null. + /// + DEFINE_PROP_GET_STR_OBJ(MultiplayerSessionName, multiplayer_session_name); + + /// + /// The number of bytes used in title storage of type StorageType. + /// + DEFINE_PROP_GET_OBJ(UsedBytes, used_bytes, uint64); + + /// + /// The maximum number of bytes that can be used in title storage of type StorageType. + /// Note that this is a soft limit and the used bytes can actually exceed this value. + /// + DEFINE_PROP_GET_OBJ(QuotaBytes, quota_bytes, uint64); + +internal: + TitleStorageQuota(_In_ xbox::services::title_storage::title_storage_quota cppObj); + +private: + xbox::services::title_storage::title_storage_quota m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.cpp b/Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.cpp new file mode 100644 index 00000000..5e224d0a --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.cpp @@ -0,0 +1,232 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TitleStorageService_WinRT.h" + +using namespace xbox::services::title_storage; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +TitleStorageService::TitleStorageService( + _In_ xbox::services::title_storage::title_storage_service cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::GetQuotaAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType + ) +{ + auto task = m_cppObj.get_quota( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + static_cast(storageType) + ) + .then([](xbox_live_result titleStorageQuota) + { + THROW_IF_ERR(titleStorageQuota); + return ref new TitleStorageQuota(titleStorageQuota.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::GetQuotaForSessionStorageAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ multiplayerSessionTemplateName, + _In_ Platform::String^ multiplayerSessionName + ) +{ + auto task = m_cppObj.get_quota_for_session_storage( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(multiplayerSessionTemplateName), + STRING_T_FROM_PLATFORM_STRING(multiplayerSessionName) + ) + .then([](xbox_live_result titleStorageQuota) + { + THROW_IF_ERR(titleStorageQuota); + return ref new TitleStorageQuota(titleStorageQuota.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::GetBlobMetadataAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_opt_ Platform::String^ blobPath, + _In_opt_ Platform::String^ xboxUserId, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_blob_metadata( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + static_cast(storageType), + STRING_T_FROM_PLATFORM_STRING(blobPath), + STRING_T_FROM_PLATFORM_STRING(xboxUserId), + skipItems, + maxItems + ) + .then([](xbox_live_result blobMetadataResult) + { + THROW_IF_ERR(blobMetadataResult); + return ref new TitleStorageBlobMetadataResult(blobMetadataResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::GetBlobMetadataForSessionStorageAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ blobPath, + _In_ Platform::String^ multiplayerSessionTemplateName, + _In_ Platform::String^ multiplayerSessionName, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ) +{ + auto task = m_cppObj.get_blob_metadata_for_session_storage( + STRING_T_FROM_PLATFORM_STRING(serviceConfigurationId), + STRING_T_FROM_PLATFORM_STRING(blobPath), + STRING_T_FROM_PLATFORM_STRING(multiplayerSessionTemplateName), + STRING_T_FROM_PLATFORM_STRING(multiplayerSessionName), + skipItems, + maxItems + ) + .then([](xbox_live_result blobMetadataResult) + { + THROW_IF_ERR(blobMetadataResult); + return ref new TitleStorageBlobMetadataResult(blobMetadataResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncAction^ +TitleStorageService::DeleteBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ bool deleteOnlyIfETagMatches + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(blobMetadata); + + auto task = m_cppObj.delete_blob( + blobMetadata->GetCppObj(), + deleteOnlyIfETagMatches + ) + .then([](xbox_live_result result) + { + THROW_IF_ERR(result); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::DownloadBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ Windows::Storage::Streams::IBuffer^ blobBuffer, + _In_ TitleStorageETagMatchCondition etagMatchCondition, + _In_opt_ Platform::String^ selectQuery + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(blobMetadata); + THROW_INVALIDARGUMENT_IF_NULL(blobBuffer); + + std::shared_ptr> nativeBlobBuffer = std::make_shared>(blobBuffer->Length); + + auto task = m_cppObj.download_blob( + blobMetadata->GetCppObj(), + nativeBlobBuffer, + static_cast(etagMatchCondition), + STRING_T_FROM_PLATFORM_STRING(selectQuery), + title_storage_service::DEFAULT_DOWNLOAD_BLOCK_SIZE + ) + .then([](xbox_live_result blobResult) + { + THROW_IF_ERR(blobResult); + return ref new TitleStorageBlobResult(blobResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::DownloadBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ Windows::Storage::Streams::IBuffer^ blobBuffer, + _In_ TitleStorageETagMatchCondition etagMatchCondition, + _In_opt_ Platform::String^ selectQuery, + _In_ uint32 preferredDownloadBlockSize + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(blobBuffer); + THROW_INVALIDARGUMENT_IF_NULL(blobMetadata); + + std::shared_ptr> nativeBlobBuffer = std::make_shared>(blobBuffer->Length); + + auto task = m_cppObj.download_blob( + blobMetadata->GetCppObj(), + nativeBlobBuffer, + static_cast(etagMatchCondition), + STRING_T_FROM_PLATFORM_STRING(selectQuery), + preferredDownloadBlockSize + ) + .then([](xbox_live_result blobResult) + { + THROW_IF_ERR(blobResult); + return ref new TitleStorageBlobResult(blobResult.payload()); + }); + + return ASYNC_FROM_TASK(task); +} + +Windows::Foundation::IAsyncOperation^ +TitleStorageService::UploadBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ Windows::Storage::Streams::IBuffer^ blobBuffer, + _In_ TitleStorageETagMatchCondition etagMatchCondition, + _In_ uint32 preferredUploadBlockSize + ) +{ + THROW_INVALIDARGUMENT_IF_NULL(blobBuffer); + THROW_INVALIDARGUMENT_IF_NULL(blobMetadata); + + auto reader = Windows::Storage::Streams::DataReader::FromBuffer(blobBuffer); + std::shared_ptr> nativeBlobBuffer = std::make_shared>(reader->UnconsumedBufferLength); + + auto nativeBlobBufferSize = nativeBlobBuffer->size(); + THROW_INVALIDARGUMENT_IF(nativeBlobBufferSize > UINT32_MAX); + reader->ReadBytes(Platform::ArrayReference(&(nativeBlobBuffer->at(0)), static_cast(nativeBlobBufferSize))); + + auto task = m_cppObj.upload_blob( + blobMetadata->GetCppObj(), + nativeBlobBuffer, + static_cast(etagMatchCondition), + preferredUploadBlockSize + ) + .then([](xbox_live_result blobMetadata) + { + THROW_IF_ERR(blobMetadata); + return ref new TitleStorageBlobMetadata(blobMetadata.payload()); + }); + + return ASYNC_FROM_TASK(task); + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.h new file mode 100644 index 00000000..e99da8ef --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageService_WinRT.h @@ -0,0 +1,229 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/title_storage.h" +#include "TitleStorageQuota_WinRT.h" +#include "TitleStorageType_WinRT.h" +#include "TitleStorageBlobMetadataResult_WinRT.h" +#include "TitleStorageBlobResult_WinRT.h" +#include "TitleStorageETagMatchCondition_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// +/// Represents an endpoint that provides methods that you can use to access the Title Storage service. +/// +public ref class TitleStorageService sealed +{ +public: + /// + /// Gets title storage quota information for the specified service configuration and storage type. + /// For user storage types (TrustedPlatform and Json) the request is made for the calling user's + /// Xbox user Id. + /// + /// The service configuration ID (SCID) of the title + /// The storage type to get quota information for. + /// + /// An interface for tracking the process of the asynchronous call. + /// The result is a TitleStorageQuota object containing the quota information. + /// + /// Calls + /// V1 GET trustedplatform/users/xuid({xuid})/scids/{scid} or + /// V1 GET json/users/xuid({xuid})/scids/{scid} or + /// V1 GET global/scids/{scid} + /// + Windows::Foundation::IAsyncOperation^ GetQuotaAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType + ); + + /// + /// Gets title storage quota information for the SessionStorage associated with the specified multiplayer session. + /// + /// The service configuration ID (SCID) of the title + /// The multiplayer session template name for the session to get quota information for. + /// The multiplayer session name for the session to get quota information for. + /// + /// An interface for tracking the process of the asynchronous call. + /// The result is a TitleStorageQuota object containing the quota information. + /// + /// Calls + /// V1 GET sessions/{sessionId}/scids/{scid} + /// + Windows::Foundation::IAsyncOperation^ GetQuotaForSessionStorageAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ Platform::String^ multiplayerSessionTemplateName, + _In_ Platform::String^ multiplayerSessionName + ); + + /// + /// Gets a list of metadata information about a file in storage, given a specified service configuration, storage type, and storage ID. + /// + /// The service configuration ID (SCID) of the title + /// The storage type to get blob metadata objects for. + /// The root path to search. The results include all blobs contained in this path and all subpaths. (Optional) + /// The Xbox User ID of the title storage to enumerate. Pass nullptr when searching for GlobalStorage type data. (Optional) + /// The number of items to skip before returning results. + /// The maximum number of items to return. + /// + /// An interface for tracking the process of the asynchronous call. + /// The result is a TitleStorageBlobMetadataResult object containing the list of enumerated blob metadata objects. + /// + /// Calls + /// V1 GET trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] or + /// V1 GET json/users/xuid({xuid})/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] or + /// V1 GET global/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] + /// + Windows::Foundation::IAsyncOperation^ GetBlobMetadataAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_ TitleStorageType storageType, + _In_opt_ Platform::String^ blobPath, + _In_opt_ Platform::String^ xboxUserId, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ); + + /// + /// Gets a list of metadata information about a file in session storage under a given path for the specified multiplayer session. + /// + /// The service configuration ID (SCID) of the title + /// The root path to search. The results include all blobs contained in this path and all subpaths. (Optional) + /// The multiplayer session template name for the session to get blob metadata objects for. + /// The multiplayer session name for the session to get blob metadata objects for. + /// The number of items to skip before returning results. + /// The maximum number of items to return. + /// + /// An interface for tracking the process of the asynchronous call. + /// The result is a TitleStorageBlobMetadataResult object containing the list of enumerated blob metadata objects. + /// + /// Calls + /// V1 GET sessions/{sessionId}/scids/{scid}/data/{path}?maxItems={maxItems}[skipItems={skipItems}] + /// + Windows::Foundation::IAsyncOperation^ GetBlobMetadataForSessionStorageAsync( + _In_ Platform::String^ serviceConfigurationId, + _In_opt_ Platform::String^ blobPath, + _In_ Platform::String^ multiplayerSessionTemplateName, + _In_ Platform::String^ multiplayerSessionName, + _In_ uint32 skipItems, + _In_ uint32 maxItems + ); + + /// + /// Deletes a blob from title storage. + /// + /// The blob metadata for the title storage blob to delete. + /// Specifies whether or not to have the delete operation check that the ETag matches before deleting the blob. + /// + /// An interface for tracking the progress of the asynchronous call. + /// + /// Calls + /// V1 DELETE trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 DELETE json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 DELETE sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + Windows::Foundation::IAsyncAction^ DeleteBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ bool deleteOnlyIfETagMatches + ); + + /// + /// Dowloads blob data from title storage. + /// + /// The blob metadata for the title storage blob to download. + /// The client provided buffer to contain the downloaded blob data. + /// The buffer must be large enough to store the downloaded blob. You can retrieve the required buffer size by getting the blob metadata. + /// The ETag match condition used to determine if the blob should be downloaded. + /// A query string that contains a ConfigStorage filter string or JSONStorage json property name string to filter. (Optional) + /// + /// An interface for tracking the progress of the asynchronous call. + /// The result is a TitleStorageBlobResult object containing the client provided blob buffer and an updated TitleStorageBlobMetadata object. + /// The metadata object contains updated ETag and Length properties. + /// + /// + /// This method throws ERROR_INSUFFICIENT_BUFFER (0x8007007A) if the blobBuffer doesn't have enough capacity to hold the blob data. + /// + /// Calls V1 GET trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET global/scids/{scid}/data/{path},{type} or + /// V1 GET sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + Windows::Foundation::IAsyncOperation^ DownloadBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ Windows::Storage::Streams::IBuffer^ blobBuffer, + _In_ TitleStorageETagMatchCondition etagMatchCondition, + _In_opt_ Platform::String^ selectQuery + ); + + /// + /// Dowloads blob data from title storage. + /// + /// The blob metadata for the title storage blob to download. + /// The client provided buffer to contain the downloaded blob data. + /// The buffer must be large enough to store the downloaded blob. You can retrieve the required buffer size by getting the blob metadata. + /// The ETag match condition used to determine if the blob should be downloaded. + /// A query string that contains a ConfigStorage filter string or JSONStorage json property name string to filter. (Optional) + /// The preferred download block size in bytes for binary blobs. + /// + /// An interface for tracking the progress of the asynchronous call. + /// The result is a TitleStorageBlobResult object containing the client provided blob buffer and an updated TitleStorageBlobMetadata object. + /// The metadata object will contain updated ETag and Length properties + /// + /// This method will throw ERROR_INSUFFICIENT_BUFFER (0x8007007A) if the blobBuffer doesn't have enough capacity to hold the blob data. + /// Calls V1 GET trustedplatform/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 GET global/scids/{scid}/data/{path},{type} or + /// V1 GET sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + Windows::Foundation::IAsyncOperation^ DownloadBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ Windows::Storage::Streams::IBuffer^ blobBuffer, + _In_ TitleStorageETagMatchCondition etagMatchCondition, + _In_opt_ Platform::String^ selectQuery, + _In_ uint32 preferredDownloadBlockSize + ); + + /// + /// Uploads a blob to title storage. + /// + /// Contains properties required to upload the buffer to title storage. Uploads require a service configuration ID, blob path, blob type and storage type at a minimum. + /// The buffer containing the blob data to upload. This buffer must be available for the duration of the async operation. Clients should not modify the buffer while an upload is in progress. + /// The ETag match condition used to determine if the blob data should be uploaded. + /// The preferred upload block size in bytes for binary blobs. Binary blobs are + /// uploaded in multiple chunks of this size if they exceed it. Larger sizes are preferred by the service. + /// If timeouts occur, the app should retry with a smaller size. Block size must be within the 1K to 4MB range. This method + /// will use a default size if this parameter is not within the acceptable range. The current minimum size is 1024 bytes, + /// the maximum size is 4194304 bytes, and the default size is 262144 bytes. + /// + /// + /// An interface for tracking the progress of the asynchronous call. + /// The result is a TitleStorageBlobMetadata object with updated Etag and Length properties. + /// + /// + /// V1 PUT json/users/xuid({xuid})/scids/{scid}/data/{path},{type} or + /// V1 PUT global/scids/{scid}/data/{path},{type} or + /// V1 PUT sessions/{sessionId}/scids/{scid}/data/{path},{type} + /// + Windows::Foundation::IAsyncOperation^ UploadBlobAsync( + _In_ TitleStorageBlobMetadata^ blobMetadata, + _In_ Windows::Storage::Streams::IBuffer^ blobBuffer, + _In_ TitleStorageETagMatchCondition etagMatchCondition, + _In_ uint32 preferredUploadBlockSize + ); + +internal: + TitleStorageService( + _In_ xbox::services::title_storage::title_storage_service cppObj + ); + +private: + xbox::services::title_storage::title_storage_service m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/WinRT/TitleStorageType_WinRT.h b/Source/Services/TitleStorage/WinRT/TitleStorageType_WinRT.h new file mode 100644 index 00000000..cf5510cd --- /dev/null +++ b/Source/Services/TitleStorage/WinRT/TitleStorageType_WinRT.h @@ -0,0 +1,54 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_BEGIN + +/// An enumeration that defines values that indicate the title storage type. +public enum class TitleStorageType +{ + /// + /// Per-user data storage such as game state or game settings for trusted platforms including Xbox One. + /// The service configuration for the game specifies if the storage is public or restricted to the owner only. + /// + TrustedPlatformStorage = xbox::services::title_storage::title_storage_type::trusted_platform_storage, + + /// Per-user JSON data storage such as game state, game settings, and user generated content for any platform. + /// The data type is restricted to TitleStorageBlobType::Json. + /// The service configuration for the game specifies if the storage is public or restricted to the owner only. + /// + JsonStorage = xbox::services::title_storage::title_storage_type::json_storage, + + /// + /// Global data storage. This storage type is only writable by the Windows Developer Dashboard or the Xbox Developer Portal (XDP). + /// Any platform may read from this storage type. Data can be rosters, maps, challenges, art resources, etc. + /// + GlobalStorage = xbox::services::title_storage::title_storage_type::global_storage, + + /// + /// Per-session data storage for multiplayer game sessions. This storage type is only writable to users joined + /// to the session. Read access is configurable to public or session-joined only in the service configuration. + /// + SessionStorage = xbox::services::title_storage::title_storage_type::session_storage, + + /// + /// Per-user data storage such as game state or game settings for untrusted platforms. + /// User restrictions can be configured to public or owner only in the service configuration. + /// + UntrustedPlatformStorage = xbox::services::title_storage::title_storage_type::untrusted_platform_storage, + + /// + /// Per-user data storage such as game state or game settings for universal platforms + /// User restrictions can be configured to public or owner only in the service configuration. + /// + Universal = xbox::services::title_storage::title_storage_type::universal +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/title_storage_blob_metadata.cpp b/Source/Services/TitleStorage/title_storage_blob_metadata.cpp new file mode 100644 index 00000000..82b89b52 --- /dev/null +++ b/Source/Services/TitleStorage/title_storage_blob_metadata.cpp @@ -0,0 +1,302 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/title_storage.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_BEGIN + +title_storage_blob_metadata::title_storage_blob_metadata() : + m_storageType(title_storage_type::trusted_platform_storage), + m_blobType(title_storage_blob_type::unknown), + m_lengthBytes(0) +{ +} + +title_storage_blob_metadata::title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ string_t displayName, + _In_ string_t eTag + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_storageType(storageType), + m_blobPath(std::move(blobPath)), + m_blobType(blobType), + m_xboxUserId(std::move(xboxUserId)), + m_multiplayerSessionTemplateName(std::move(multiplayerSessionTemplateName)), + m_multiplayerSessionName(std::move(multiplayerSessionName)), + m_displayName(std::move(displayName)), + m_eTag(std::move(eTag)) +{ + XSAPI_ASSERT(!m_serviceConfigurationId.empty()); + XSAPI_ASSERT(!m_blobPath.empty()); +} + +title_storage_blob_metadata::title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_storageType(storageType), + m_blobPath(std::move(blobPath)), + m_blobType(blobType), + m_xboxUserId(std::move(xboxUserId)), + m_lengthBytes(0) +{ + XSAPI_ASSERT(!m_serviceConfigurationId.empty()); + XSAPI_ASSERT(!m_blobPath.empty()); +} + +title_storage_blob_metadata::title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId, + _In_ string_t displayName, + _In_ string_t eTag + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_storageType(storageType), + m_blobPath(std::move(blobPath)), + m_blobType(blobType), + m_xboxUserId(std::move(xboxUserId)), + m_displayName(std::move(displayName)), + m_eTag(std::move(eTag)) +{ + XSAPI_ASSERT(!m_serviceConfigurationId.empty()); + XSAPI_ASSERT(!m_blobPath.empty()); +} + +title_storage_blob_metadata::title_storage_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t xboxUserId, + _In_ string_t displayName, + _In_ string_t eTag, + _In_ utility::datetime clientTimestamp + ) : + m_serviceConfigurationId(std::move(serviceConfigurationId)), + m_storageType(storageType), + m_blobPath(std::move(blobPath)), + m_blobType(blobType), + m_xboxUserId(std::move(xboxUserId)), + m_displayName(std::move(displayName)), + m_eTag(std::move(eTag)), + m_clientTimestamp(std::move(clientTimestamp)) +{ + XSAPI_ASSERT(!m_serviceConfigurationId.empty()); + XSAPI_ASSERT(!m_blobPath.empty()); +} + +void +title_storage_blob_metadata::_Initialize( + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType + ) +{ + m_xboxUserId = std::move(xboxUserId); + m_multiplayerSessionTemplateName = std::move(multiplayerSessionTemplateName); + m_multiplayerSessionName = std::move(multiplayerSessionName); + m_serviceConfigurationId = std::move(serviceConfigurationId); + m_storageType = storageType; +} + +title_storage_blob_metadata +title_storage_blob_metadata::create_title_storage_blob_metadata_for_session_storage( + _In_ string_t serviceConfigurationId, + _In_ string_t blobPath, + _In_ title_storage_blob_type blobType, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ string_t displayName, + _In_ string_t eTag + ) +{ + return title_storage_blob_metadata( + std::move(serviceConfigurationId), + title_storage_type::session_storage, + std::move(blobPath), + std::move(blobType), + string_t(), + std::move(multiplayerSessionTemplateName), + std::move(multiplayerSessionName), + std::move(displayName), + std::move(eTag) + ); +} + +const string_t& +title_storage_blob_metadata::blob_path() const +{ + return m_blobPath; +} + +title_storage_blob_type +title_storage_blob_metadata::blob_type() const +{ + return m_blobType; +} + +title_storage_type +title_storage_blob_metadata::storage_type() const +{ + return m_storageType; +} + +const string_t& +title_storage_blob_metadata::display_name() const +{ + return m_displayName; +} + +const string_t& +title_storage_blob_metadata::e_tag() const +{ + return m_eTag; +} + +const utility::datetime& +title_storage_blob_metadata::client_timestamp() const +{ + return m_clientTimestamp; +} + +void +title_storage_blob_metadata::set_client_timestamp( + _In_ utility::datetime value + ) +{ + m_clientTimestamp = std::move(value); +} + +uint64_t +title_storage_blob_metadata::length() const +{ + return m_lengthBytes; +} + +const string_t& +title_storage_blob_metadata::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const string_t& +title_storage_blob_metadata::xbox_user_id() const +{ + return m_xboxUserId; +} + +const string_t& +title_storage_blob_metadata::multiplayer_session_template_name() const +{ + return m_multiplayerSessionTemplateName; +} + +const string_t& +title_storage_blob_metadata::multiplayer_session_name() const +{ + return m_multiplayerSessionName; +} + +void +title_storage_blob_metadata::_Set_e_tag_and_length( + _In_ string_t etag, + _In_ uint64_t length + ) +{ + m_eTag = std::move(etag); + m_lengthBytes = length; +} + +title_storage_blob_type +title_storage_blob_metadata::_Convert_string_to_title_storage_blob_type( + _In_ const string_t& value + ) +{ + if (utils::str_icmp(value, _T("binary")) == 0) + { + return title_storage_blob_type::binary; + } + else if (utils::str_icmp(value, _T("json")) == 0) + { + return title_storage_blob_type::json; + } + else if (utils::str_icmp(value, _T("config")) == 0) + { + return title_storage_blob_type::config; + } + + return title_storage_blob_type::unknown; +} + +const xbox_live_result +title_storage_blob_metadata::_Convert_title_storage_blob_type_to_string( + _In_ title_storage_blob_type blobType + ) +{ + switch (blobType) + { + case title_storage_blob_type::binary: return xbox_live_result(_T("binary")); + case title_storage_blob_type::json: return xbox_live_result(_T("json")); + case title_storage_blob_type::config: return xbox_live_result(_T("config")); + default: return xbox_live_result(xbox_live_error_code::invalid_argument, "Enum out of range"); + } +} + +xbox_live_result +title_storage_blob_metadata::_Deserialize( + _In_ const web::json::value& json + ) +{ + title_storage_blob_metadata returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + returnObject.m_clientTimestamp = utils::extract_json_time(json, _T("clientFileTime"), errc); + returnObject.m_displayName = utils::extract_json_string(json, _T("displayName"), errc); + returnObject.m_eTag = utils::extract_json_string(json, _T("etag"), errc); + returnObject.m_lengthBytes = utils::extract_json_uint52(json, _T("size"), errc); + + string_t fileName = utils::extract_json_string(json, _T("fileName"), errc); + if (!fileName.empty()) + { + auto nPos = fileName.find(','); + if (nPos == std::string::npos) + { + return xbox_live_result(returnObject, xbox_live_error_code::json_error, "Blob metadata deserialization failed due to file type not found"); + } + + string_t smartBlobType = fileName.substr(nPos + 1); + returnObject.m_blobType = _Convert_string_to_title_storage_blob_type(smartBlobType); + fileName.resize(nPos); + returnObject.m_blobPath = std::move(fileName); + + } + + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/title_storage_blob_metadata_result.cpp b/Source/Services/TitleStorage/title_storage_blob_metadata_result.cpp new file mode 100644 index 00000000..825923fe --- /dev/null +++ b/Source/Services/TitleStorage/title_storage_blob_metadata_result.cpp @@ -0,0 +1,129 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/title_storage.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_BEGIN + +title_storage_blob_metadata_result::title_storage_blob_metadata_result() +{ +} + +bool +title_storage_blob_metadata_result::has_next() const +{ + return !m_continuationToken.empty(); +} + +const std::vector& +title_storage_blob_metadata_result::items() const +{ + return m_items; +} + +pplx::task> +title_storage_blob_metadata_result::get_next( + _In_ uint32_t maxItems + ) +{ + if (m_continuationToken.empty()) + { + return pplx::task_from_result(xbox_live_result(xbox_live_error_code::runtime_error, "No more data availible")); + } + + title_storage_service titleStorageService( + m_userContext, + m_xboxLiveContextSettings, + m_appConfig + ); + + return titleStorageService.internal_get_blob_metadata( + m_serviceConfigurationId, + m_storageType, + m_blobPath, + m_xboxUserId, + m_multiplayerSessionTemplateName, + m_multiplayerSessionName, + 0, + maxItems, + m_continuationToken + ); +} + +void +title_storage_blob_metadata_result::_Initialize( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig, + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName + ) +{ + m_userContext = std::move(userContext); + m_xboxLiveContextSettings = std::move(xboxLiveContextSettings); + m_appConfig = std::move(appConfig); + m_serviceConfigurationId = std::move(serviceConfigurationId); + m_storageType = storageType; + m_blobPath = std::move(blobPath); + m_xboxUserId = std::move(xboxUserId); + m_multiplayerSessionTemplateName = std::move(multiplayerSessionTemplateName); + m_multiplayerSessionName = std::move(multiplayerSessionName); + + for (auto& item : m_items) + { + item._Initialize( + m_xboxUserId, + m_multiplayerSessionTemplateName, + m_multiplayerSessionName, + m_serviceConfigurationId, + m_storageType + ); + } +} + +xbox_live_result +title_storage_blob_metadata_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + title_storage_blob_metadata_result returnObject; + + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + web::json::value blobs = utils::extract_json_field(json, _T("blobs"), true); + returnObject.m_items = utils::extract_json_vector( + title_storage_blob_metadata::_Deserialize, + blobs, + errc, + true + ); + + web::json::value pagingInfoJson = utils::extract_json_field(json, _T("pagingInfo"), errc, false); + + if (!pagingInfoJson.is_null()) + { + returnObject.m_continuationToken = utils::extract_json_string( + pagingInfoJson, + _T("continuationToken"), + errc + ); + } + + return xbox_live_result(returnObject, errc); +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/title_storage_blob_result.cpp b/Source/Services/TitleStorage/title_storage_blob_result.cpp new file mode 100644 index 00000000..a8764ec9 --- /dev/null +++ b/Source/Services/TitleStorage/title_storage_blob_result.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/title_storage.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_BEGIN + +title_storage_blob_result::title_storage_blob_result() +{ +} + +title_storage_blob_result::title_storage_blob_result( + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_blob_metadata blobMetadata + ) : + m_blobBuffer(blobBuffer), + m_blobMetadata(std::move(blobMetadata)) +{ +} + +std::shared_ptr> const +title_storage_blob_result::blob_buffer() const +{ + return m_blobBuffer; +} + +const title_storage_blob_metadata& +title_storage_blob_result::blob_metadata() const +{ + return m_blobMetadata; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/title_storage_quota.cpp b/Source/Services/TitleStorage/title_storage_quota.cpp new file mode 100644 index 00000000..0f3088db --- /dev/null +++ b/Source/Services/TitleStorage/title_storage_quota.cpp @@ -0,0 +1,100 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/title_storage.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_BEGIN + +title_storage_quota::title_storage_quota() : + m_storageType(title_storage_type::trusted_platform_storage), + m_usedBytes(0), + m_quotaBytes(0) +{ +} + +void +title_storage_quota::_Initialize( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t xboxUserId, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName + ) +{ + m_serviceConfigurationId = std::move(serviceConfigurationId); + m_storageType = storageType; + m_xboxUserId = std::move(xboxUserId); + m_multiplayerSessionTemplateName = std::move(multiplayerSessionTemplateName); + m_multiplayerSessionName = std::move(multiplayerSessionName); +} + +const string_t& +title_storage_quota::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +title_storage_type +title_storage_quota::storage_type() const +{ + return m_storageType; +} + +const string_t& +title_storage_quota::xbox_user_id() const +{ + return m_xboxUserId; +} + +const string_t& +title_storage_quota::multiplayer_session_template_name() const +{ + return m_multiplayerSessionTemplateName; +} + +const string_t& +title_storage_quota::multiplayer_session_name() const +{ + return m_multiplayerSessionName; +} + +uint64_t +title_storage_quota::used_bytes() const +{ + return m_usedBytes; +} + +uint64_t +title_storage_quota::quota_bytes() const +{ + return m_quotaBytes; +} + +xbox_live_result +title_storage_quota::_Deserialize( + _In_ const web::json::value& json + ) +{ + title_storage_quota returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + web::json::value quotaInfoJson = utils::extract_json_field(json, _T("quotaInfo"), errc, false); + + if (!quotaInfoJson.is_null()) + { + returnObject.m_usedBytes = utils::extract_json_uint52(quotaInfoJson, _T("usedBytes"), errc); + returnObject.m_quotaBytes = utils::extract_json_uint52(quotaInfoJson, _T("quotaBytes"), errc); + } + + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_END \ No newline at end of file diff --git a/Source/Services/TitleStorage/title_storage_service.cpp b/Source/Services/TitleStorage/title_storage_service.cpp new file mode 100644 index 00000000..4c7ed3d3 --- /dev/null +++ b/Source/Services/TitleStorage/title_storage_service.cpp @@ -0,0 +1,989 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/title_storage.h" +#include "user_context.h" +#include "xbox_system_factory.h" +#include "utils.h" + +using namespace xbox::services::system; +using namespace xbox::services; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_BEGIN + +static const string_t CONTENT_TYPE_HEADER_VALUE =_T("application/octet-stream"); +static const string_t E_TAG_HEADER_NAME = _T("ETag"); +static const string_t IF_MATCH_HEADER_NAME = _T("If-Match"); +static const string_t IF_NONE_HEADER_NAME = _T("If-None-Match"); +static const string_t E_TAG_INVALID_VALUE = _T("InvalidETagValue"); +static const string_t RANGE_HEADER_NAME = _T("Range"); + +const uint32_t title_storage_service::MIN_UPLOAD_BLOCK_SIZE = 1024; +const uint32_t title_storage_service::MAX_UPLOAD_BLOCK_SIZE = 4 * 1024 * 1024; +const uint32_t title_storage_service::DEFAULT_UPLOAD_BLOCK_SIZE = 256 * 1024; +const uint32_t title_storage_service::MIN_DOWNLOAD_BLOCK_SIZE = 1024; +const uint32_t title_storage_service::DEFAULT_DOWNLOAD_BLOCK_SIZE = 1024 * 1024; + +title_storage_service::title_storage_service( + _In_ std::shared_ptr userContext, + _In_ std::shared_ptr xboxLiveContextSettings, + _In_ std::shared_ptr appConfig + ) : + m_userContext(std::move(userContext)), + m_xboxLiveContextSettings(std::move(xboxLiveContextSettings)), + m_appConfig(std::move(appConfig)) +{ +} + +pplx::task> +title_storage_service::get_quota( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, title_storage_quota, "Service configuration id is empty"); + string_t xboxUserId = m_userContext->xbox_user_id(); + xbox_live_result subpathAndQueryResult = title_storage_quota_subpath( + storageType, + serviceConfigurationId, + xboxUserId, + string_t(), + string_t() + ); + + RETURN_TASK_CPP_IF_ERR(subpathAndQueryResult, title_storage_quota); + + string_t subpathAndQuery = subpathAndQueryResult.payload(); + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("titlestorage"), m_appConfig), + subpathAndQuery, + xbox_live_api::get_quota + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([httpCall, serviceConfigurationId, storageType, xboxUserId](std::shared_ptr response) + { + auto result = title_storage_quota::_Deserialize( + response->response_body_json() + ); + + auto& titleStorageQuota = result.payload(); + titleStorageQuota._Initialize( + serviceConfigurationId, + storageType, + xboxUserId, + string_t(), + string_t() + ); + + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_storage_service::get_quota_for_session_storage( + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, title_storage_quota, "Service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(multiplayerSessionTemplateName, title_storage_quota, "Multiplayer session template name is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(multiplayerSessionName, title_storage_quota, "Multiplayer session name is empty"); + + xbox_live_result subpathAndQueryResult = title_storage_quota_subpath( + title_storage_type::session_storage, + serviceConfigurationId, + string_t(), + multiplayerSessionTemplateName, + multiplayerSessionName + ); + + RETURN_TASK_CPP_IF_ERR(subpathAndQueryResult, title_storage_quota); + + string_t subpathAndQuery = subpathAndQueryResult.payload(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("titlestorage"), m_appConfig), + subpathAndQuery, + xbox_live_api::get_quota_for_session_storage + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([serviceConfigurationId, multiplayerSessionTemplateName, multiplayerSessionName](std::shared_ptr response) + { + auto result = title_storage_quota::_Deserialize( + response->response_body_json() + ); + + auto& titleStorageQuota = result.payload(); + titleStorageQuota._Initialize( + serviceConfigurationId, + title_storage_type::session_storage, + string_t(), + multiplayerSessionTemplateName, + multiplayerSessionName + ); + + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + + +pplx::task> +title_storage_service::get_blob_metadata( + _In_ string_t serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ string_t blobPath, + _In_ string_t xboxUserId, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, title_storage_blob_metadata_result, "Service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(storageType == title_storage_type::global_storage && !xboxUserId.empty(), title_storage_blob_metadata_result, "Global storage type with empty xbox user id"); + + if ((storageType == title_storage_type::trusted_platform_storage || storageType == title_storage_type::json_storage) && xboxUserId.empty()) + { + xboxUserId = m_userContext->xbox_user_id(); + } + + return internal_get_blob_metadata( + std::move(serviceConfigurationId), + storageType, + std::move(blobPath), + std::move(xboxUserId), + string_t(), + string_t(), + skipItems, + maxItems, + string_t() + ); +} + +pplx::task> +title_storage_service::get_blob_metadata_for_session_storage( + _In_ string_t serviceConfigurationId, + _In_ string_t blobPath, + _In_ string_t multiplayerSessionTemplateName, + _In_ string_t multiplayerSessionName, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(serviceConfigurationId, title_storage_blob_metadata_result, "Service configuration id is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(multiplayerSessionTemplateName, title_storage_blob_metadata_result, "Multiplayer session template name is empty"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF_STRING_EMPTY(multiplayerSessionName, title_storage_blob_metadata_result, "Multiplayer session name is empty"); + + return internal_get_blob_metadata( + std::move(serviceConfigurationId), + title_storage_type::session_storage, + std::move(blobPath), + string_t(), + std::move(multiplayerSessionTemplateName), + std::move(multiplayerSessionName), + skipItems, + maxItems, + string_t() + ); +} + +pplx::task> +title_storage_service::delete_blob( + _In_ const title_storage_blob_metadata& blobMetadata, + _In_ bool deleteOnlyIfEtagMatches + ) +{ + title_storage_e_tag_match_condition eTagMatchCondition = deleteOnlyIfEtagMatches ? + title_storage_e_tag_match_condition::if_match : + title_storage_e_tag_match_condition::not_used; + + xbox_live_result subpathAndQueryResult = title_storage_download_blob_subpath( + blobMetadata, + string_t() + ); + + RETURN_TASK_CPP_IF_ERR(subpathAndQueryResult, void); + + string_t subpathAndQuery = subpathAndQueryResult.payload(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("DELETE"), + utils::create_xboxlive_endpoint(_T("titlestorage"), m_appConfig), + subpathAndQuery, + xbox_live_api::delete_blob + ); + + httpCall->set_content_type_header_value(CONTENT_TYPE_HEADER_VALUE); + + set_e_tag_header( + httpCall, + blobMetadata.e_tag(), + eTagMatchCondition + ); + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([](std::shared_ptr response) + { + auto errorStatus = response->err_code(); + return xbox_live_result(errorStatus, "Invalid HTTP recieved on delete"); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_storage_service::internal_get_blob_metadata( + _In_ const string_t& serviceConfigurationId, + _In_ title_storage_type storageType, + _In_ const string_t& blobPath, + _In_ const string_t& xboxUserId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ) +{ + xbox_live_result subpathAndQueryResult = title_storage_blob_metadata_subpath( + storageType, + serviceConfigurationId, + xboxUserId, + multiplayerSessionTemplateName, + multiplayerSessionName, + blobPath, + skipItems, + maxItems, + continuationToken + ); + + RETURN_TASK_CPP_IF_ERR(subpathAndQueryResult, title_storage_blob_metadata_result); + + string_t subpathAndQuery = subpathAndQueryResult.payload(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + m_xboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("titlestorage"), m_appConfig), + subpathAndQuery, + xbox_live_api::get_blob_metadata + ); + + auto userContextShared = m_userContext; + auto xboxLiveContextSettingsShared = m_xboxLiveContextSettings; + auto appConfigShared = m_appConfig; + + auto task = httpCall->get_response_with_auth(m_userContext) + .then([httpCall, + userContextShared, + appConfigShared, + xboxLiveContextSettingsShared, + xboxUserId, + serviceConfigurationId, + storageType, + multiplayerSessionTemplateName, + multiplayerSessionName, + blobPath] + (std::shared_ptr response) + { + auto result = title_storage_blob_metadata_result::_Deserialize( + response->response_body_json() + ); + + auto& titleStorageBlobMetadataResult = result.payload(); + + titleStorageBlobMetadataResult._Initialize( + userContextShared, + xboxLiveContextSettingsShared, + appConfigShared, + serviceConfigurationId, + storageType, + blobPath, + xboxUserId, + multiplayerSessionTemplateName, + multiplayerSessionName + ); + + return utils::generate_xbox_live_result( + result, + response + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_storage_service::download_blob( + _In_ title_storage_blob_metadata blobMetadata, + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_e_tag_match_condition etagMatchCondition, + _In_ string_t selectQuery + ) +{ + return download_blob( + std::move(blobMetadata), + blobBuffer, + etagMatchCondition, + std::move(selectQuery), + DEFAULT_DOWNLOAD_BLOCK_SIZE + ); +} + +pplx::task> +title_storage_service::download_blob( + _In_ title_storage_blob_metadata blobMetadata, + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_e_tag_match_condition etagMatchCondition, + _In_ string_t selectQuery, + _In_ uint32_t preferredDownloadBlockSize + ) +{ + if(blobBuffer == nullptr) + { + return pplx::task_from_result(xbox_live_result(xbox_live_error_code::invalid_argument, "Null blobBuffer Argument")); + } + preferredDownloadBlockSize = preferredDownloadBlockSize < MIN_DOWNLOAD_BLOCK_SIZE ? MIN_DOWNLOAD_BLOCK_SIZE : preferredDownloadBlockSize; + + auto sharedXboxLiveContextSettings = m_xboxLiveContextSettings; + auto sharedUserContext = m_userContext; + auto sharedAppConfig = m_appConfig; + auto task = pplx::create_task([sharedXboxLiveContextSettings, sharedUserContext, sharedAppConfig, blobMetadata, blobBuffer, etagMatchCondition, selectQuery, preferredDownloadBlockSize]() + { + title_storage_blob_metadata resultBlobMetadata( + blobMetadata + ); + + bool isBinaryData = (blobMetadata.blob_type() == title_storage_blob_type::binary); + bool isDownloading = true; + uint32_t startByte = 0; + + xbox_live_result subpathAndQueryResult = title_storage_download_blob_subpath( + blobMetadata, + selectQuery + ); + + if(subpathAndQueryResult.err()) return xbox_live_result(subpathAndQueryResult.err(), subpathAndQueryResult.err_message()); + + string_t subpathAndQuery = subpathAndQueryResult.payload(); + blobBuffer->clear(); + while (isDownloading) + { + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + sharedXboxLiveContextSettings, + _T("GET"), + utils::create_xboxlive_endpoint(_T("titlestorage"), sharedAppConfig), + subpathAndQuery, + xbox_live_api::download_blob + ); + + httpCall->set_content_type_header_value(CONTENT_TYPE_HEADER_VALUE); + httpCall->set_long_http_call(true); + + set_e_tag_header( + httpCall, + blobMetadata.e_tag(), + etagMatchCondition + ); + + if (isBinaryData) + { + set_range_header( + httpCall, + startByte, + startByte + preferredDownloadBlockSize - 1 + ); + } + + std::error_code errc = xbox_live_error_code::no_error; + httpCall->get_response_with_auth(sharedUserContext, http_call_response_body_type::vector_body) + .then([&errc, blobBuffer, &startByte, isBinaryData, preferredDownloadBlockSize, &isDownloading, &resultBlobMetadata](std::shared_ptr response) + { + errc = response->err_code(); + if (!response->err_code()) + { + auto responseVector = response->response_body_vector(); + size_t responseByteLength = responseVector.size(); + blobBuffer->resize(blobBuffer->size() + responseByteLength); + if (responseByteLength > 0) + { + memcpy(&(blobBuffer->at(startByte)), &responseVector[0], responseByteLength); + } + + startByte += static_cast(responseByteLength); + + if (!isBinaryData || responseByteLength < preferredDownloadBlockSize) + { + isDownloading = false; + resultBlobMetadata._Set_e_tag_and_length( + response->e_tag(), + responseByteLength + ); + } + } + }).wait(); + + if (errc) + { + return xbox_live_result(errc, "Download failed"); + } + } + + return xbox_live_result( + title_storage_blob_result( + blobBuffer, + resultBlobMetadata + ), + xbox_live_error_code::no_error + ); + }); + + return utils::create_exception_free_task( + task + ); +} + +pplx::task> +title_storage_service::upload_blob( + _In_ title_storage_blob_metadata blobMetadata, + _In_ std::shared_ptr> blobBuffer, + _In_ title_storage_e_tag_match_condition etagMatchCondition, + _In_ uint32_t preferredUploadBlockSize + ) +{ + RETURN_TASK_CPP_INVALIDARGUMENT_IF(blobBuffer == nullptr, title_storage_blob_metadata, "Blob buffer is null"); + RETURN_TASK_CPP_INVALIDARGUMENT_IF(blobBuffer->empty(), title_storage_blob_metadata, "Blob buffer is empty"); + + preferredUploadBlockSize = preferredUploadBlockSize < MIN_UPLOAD_BLOCK_SIZE ? MIN_UPLOAD_BLOCK_SIZE : preferredUploadBlockSize; + preferredUploadBlockSize = preferredUploadBlockSize > MAX_UPLOAD_BLOCK_SIZE ? MAX_UPLOAD_BLOCK_SIZE : preferredUploadBlockSize; + + auto sharedXboxLiveContextSettings = m_xboxLiveContextSettings; + auto sharedUserContext = m_userContext; + auto appConfig = m_appConfig; + + auto task = pplx::create_task([sharedXboxLiveContextSettings, sharedUserContext, appConfig, blobMetadata, blobBuffer, preferredUploadBlockSize, etagMatchCondition]() + { + title_storage_blob_metadata resultBlobMetadata( + blobMetadata + ); + + bool isBinaryData = resultBlobMetadata.blob_type() == title_storage_blob_type::binary; + bool isFinalBlock = false; + + std::vector dataChunk(0); + auto blobBufferSize = static_cast(blobBuffer->size()); + if (!isBinaryData) + { + dataChunk.resize(blobBufferSize); + } + + size_t start = 0; + size_t count = 0; + string_t continuationToken; + + while (start < blobBufferSize) + { + if (isBinaryData) + { + count = blobBufferSize - start; + + if (count > preferredUploadBlockSize) + { + count = preferredUploadBlockSize; + } + dataChunk.resize(count); + + memcpy(&dataChunk[0], &(blobBuffer->at(start)), count); + + start += count; + isFinalBlock = start == blobBufferSize; + } + else + { + dataChunk = *blobBuffer; + count = static_cast(dataChunk.size()); + start = static_cast(dataChunk.size()); + isFinalBlock = true; + } + + xbox_live_result subpathAndQueryResult = title_storage_upload_blob_subpath( + resultBlobMetadata, + continuationToken, + isFinalBlock + ); + + if (subpathAndQueryResult.err()) return xbox_live_result(subpathAndQueryResult.err(), subpathAndQueryResult.err_message()); + string_t subpathAndQuery = subpathAndQueryResult.payload(); + + std::shared_ptr httpCall = xbox_system_factory::get_factory()->create_http_call( + sharedXboxLiveContextSettings, + _T("PUT"), + utils::create_xboxlive_endpoint(_T("titlestorage"), appConfig), + subpathAndQuery, + xbox_live_api::upload_blob + ); + + httpCall->set_content_type_header_value(CONTENT_TYPE_HEADER_VALUE); + httpCall->set_long_http_call(true); + + set_e_tag_header( + httpCall, + resultBlobMetadata.e_tag(), + etagMatchCondition + ); + + httpCall->set_request_body(dataChunk); + + std::error_code errc = xbox_live_error_code::no_error; + httpCall->get_response_with_auth(sharedUserContext) + .then([&errc, isFinalBlock, &continuationToken, &resultBlobMetadata, blobBufferSize](std::shared_ptr response) + { + errc = response->err_code(); + auto responseJson = response->response_body_json(); + continuationToken = _T(""); + if (!errc && !responseJson.is_null()) + { + continuationToken = utils::extract_json_string(responseJson, _T("continuationToken")); + } + + if (!errc && isFinalBlock) + { + resultBlobMetadata._Set_e_tag_and_length( + response->e_tag(), + blobBufferSize + ); + } + }).wait(); + + if (errc) + { + return xbox_live_result(errc, "Upload failed"); + } + } + + return xbox_live_result(resultBlobMetadata, xbox_live_error_code::no_error, ""); + }); + + return utils::create_exception_free_task( + task + ); +} + +void +title_storage_service::set_e_tag_header( + _In_ std::shared_ptr httpCall, + _In_ string_t etag, + _In_ title_storage_e_tag_match_condition eTagMatchCondition + ) +{ + if (eTagMatchCondition == title_storage_e_tag_match_condition::not_used) + { + httpCall->set_custom_header(E_TAG_HEADER_NAME, E_TAG_INVALID_VALUE); + httpCall->set_custom_header(IF_NONE_HEADER_NAME, E_TAG_INVALID_VALUE); + } + else + { + string_t etagValue = etag.empty() ? + IF_NONE_HEADER_NAME : + etag; + + httpCall->set_custom_header(E_TAG_HEADER_NAME, etagValue); + + if (eTagMatchCondition == title_storage_e_tag_match_condition::if_match) + { + httpCall->set_custom_header(IF_MATCH_HEADER_NAME, etagValue); + } + else + { + httpCall->set_custom_header(IF_NONE_HEADER_NAME, etagValue); + } + } +} + +void +title_storage_service::set_range_header( + _In_ std::shared_ptr httpCall, + _In_ uint32_t startByte, + _In_ uint32_t endByte + ) +{ + stringstream_t byteRange; + byteRange << _T("bytes="); + byteRange << startByte; + byteRange << _T("-"); + byteRange << endByte; + + httpCall->set_custom_header( + RANGE_HEADER_NAME, + byteRange.str() + ); +} + +xbox_live_result +title_storage_service::title_storage_quota_subpath( + _In_ title_storage_type storageType, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& xboxUserId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName + ) +{ + stringstream_t path; + switch (storageType) + { + case title_storage_type::trusted_platform_storage: + path << _T("/trustedplatform/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::json_storage: + path << _T("/json/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::global_storage: + path << _T("/global/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::session_storage: + path << _T("/sessions/"); + path << multiplayerSessionTemplateName; + path << _T("~"); + path << multiplayerSessionName; + path << _T("/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::untrusted_platform_storage: + path << _T("/untrustedplatform/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::universal: + path << _T("/universal/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid storage type"); + } + + return xbox_live_result(path.str()); +} + +xbox_live_result +title_storage_service::title_storage_blob_metadata_subpath( + _In_ title_storage_type storageType, + _In_ const string_t& serviceConfigurationId, + _In_ const string_t& xboxUserId, + _In_ const string_t& multiplayerSessionTemplateName, + _In_ const string_t& multiplayerSessionName, + _In_ const string_t& blobPath, + _In_ uint32_t skipItems, + _In_ uint32_t maxItems, + _In_ const string_t& continuationToken + ) +{ + stringstream_t path; + switch (storageType) + { + case title_storage_type::trusted_platform_storage: + path << _T("/trustedplatform/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::json_storage: + path << _T("/json/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::global_storage: + path << _T("/global/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::session_storage: + path << _T("/sessions/"); + path << multiplayerSessionTemplateName; + path << _T("~"); + path << multiplayerSessionName; + path << _T("/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::untrusted_platform_storage: + path << _T("/untrustedplatform/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + case title_storage_type::universal: + path << _T("/universal/users/xuid("); + path << xboxUserId; + path << _T(")/scids/"); + path << serviceConfigurationId; + break; + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid storage type"); + } + + path << _T("/data"); + + if (!blobPath.empty()) + { + path << _T("/"); + path << web::uri::encode_uri(blobPath, web::uri::components::query); + } + + web::uri_builder params; + utils::append_paging_info( + params, + skipItems, + maxItems, + continuationToken + ); + + + string_t paramPath = params.query(); + if (paramPath.size() > 1) + { + path << "?" << paramPath; + } + + return path.str(); +} + +xbox_live_result +title_storage_service::title_storage_download_blob_subpath( + _In_ const title_storage_blob_metadata& blobMetadata, + _In_ const string_t& selectQuery + ) +{ + stringstream_t path; + xbox_live_result titleStorageBlobToString; + switch (blobMetadata.storage_type()) + { + case title_storage_type::trusted_platform_storage: + titleStorageBlobToString = title_storage_blob_metadata::_Convert_title_storage_blob_type_to_string(blobMetadata.blob_type()); + if (titleStorageBlobToString.err()) + { + return xbox_live_result(titleStorageBlobToString.err(), titleStorageBlobToString.err_message()); + } + + path << _T("/trustedplatform/users/xuid("); + path << blobMetadata.xbox_user_id(); + path << _T(")/scids/"); + path << blobMetadata.service_configuration_id(); + path << _T("/data/"); + path << blobMetadata.blob_path(); + path << _T(","); + path << titleStorageBlobToString.payload(); + break; + + case title_storage_type::json_storage: + path << _T("/json/users/xuid("); + path << blobMetadata.xbox_user_id(); + path << _T(")/scids/"); + path << blobMetadata.service_configuration_id(); + path << _T("/data/"); + path << blobMetadata.blob_path(); + path << _T(",json"); + break; + + case title_storage_type::global_storage: + titleStorageBlobToString = title_storage_blob_metadata::_Convert_title_storage_blob_type_to_string(blobMetadata.blob_type()); + if (titleStorageBlobToString.err()) + { + return xbox_live_result(titleStorageBlobToString.err(), titleStorageBlobToString.err_message()); + } + + path << _T("/global/scids/"); + path << blobMetadata.service_configuration_id(); + path << _T("/data/"); + path << blobMetadata.blob_path(); + path << _T(","); + path << titleStorageBlobToString.payload(); + break; + + case title_storage_type::session_storage: + titleStorageBlobToString = title_storage_blob_metadata::_Convert_title_storage_blob_type_to_string(blobMetadata.blob_type()); + if (titleStorageBlobToString.err()) + { + return xbox_live_result(titleStorageBlobToString.err(), titleStorageBlobToString.err_message()); + } + + path << _T("/sessions/"); + path << blobMetadata.multiplayer_session_template_name(); + path << _T("~"); + path << blobMetadata.multiplayer_session_name(); + path << _T("/scids/"); + path << blobMetadata.service_configuration_id(); + path << _T("/data/"); + path << blobMetadata.blob_path(); + path << _T(","); + path << titleStorageBlobToString.payload(); + break; + + case title_storage_type::untrusted_platform_storage: + titleStorageBlobToString = title_storage_blob_metadata::_Convert_title_storage_blob_type_to_string(blobMetadata.blob_type()); + if (titleStorageBlobToString.err()) + { + return xbox_live_result(titleStorageBlobToString.err(), titleStorageBlobToString.err_message()); + } + + path << _T("/untrustedplatform/users/xuid("); + path << blobMetadata.xbox_user_id(); + path << _T(")/scids/"); + path << blobMetadata.service_configuration_id(); + path << _T("/data/"); + path << blobMetadata.blob_path(); + path << _T(","); + path << titleStorageBlobToString.payload(); + break; + + case title_storage_type::universal: + titleStorageBlobToString = title_storage_blob_metadata::_Convert_title_storage_blob_type_to_string(blobMetadata.blob_type()); + if (titleStorageBlobToString.err()) + { + return xbox_live_result(titleStorageBlobToString.err(), titleStorageBlobToString.err_message()); + } + + path << _T("/universal/users/xuid("); + path << blobMetadata.xbox_user_id(); + path << _T(")/scids/"); + path << blobMetadata.service_configuration_id(); + path << _T("/data/"); + path << blobMetadata.blob_path(); + path << _T(","); + path << titleStorageBlobToString.payload(); + break; + + default: + return xbox_live_result(xbox_live_error_code::invalid_argument, "Invalid storage type"); + } + + std::vector params; + if (!selectQuery.empty()) + { + if (blobMetadata.blob_type() == title_storage_blob_type::config) + { + stringstream_t param; + param << _T("customSelector="); + param << web::uri::encode_uri(selectQuery.c_str()); + params.push_back(param.str()); + } + else if (blobMetadata.blob_type() == title_storage_blob_type::json) + { + stringstream_t param; + param << _T("select="); + param << web::uri::encode_uri(selectQuery.c_str()); + params.push_back(param.str()); + } + } + + path << utils::get_query_from_params(params); + + return xbox_live_result(path.str()); +} + +xbox_live_result +title_storage_service::title_storage_upload_blob_subpath( + _In_ const title_storage_blob_metadata& blobMetadata, + _In_ const string_t& continuationToken, + _In_ bool finalBlock + ) +{ + stringstream_t source; + xbox_live_result titleStorageDlSubpath = title_storage_download_blob_subpath( + blobMetadata, + _T("") + ); + + if (titleStorageDlSubpath.err()) return titleStorageDlSubpath; + + source << titleStorageDlSubpath.payload(); + + std::vector params; + + if (blobMetadata.client_timestamp().to_interval() != 0) + { + string_t clientTimeStamp = blobMetadata.client_timestamp().to_string(); + stringstream_t param; + param << _T("clientFileTime="); + param << web::uri::encode_uri(clientTimeStamp); + params.push_back(param.str()); + } + + if (!blobMetadata.display_name().empty()) + { + stringstream_t param; + param << _T("displayName="); + param << web::uri::encode_uri(blobMetadata.display_name()); + params.push_back(param.str()); + } + + if (!continuationToken.empty()) + { + stringstream_t param; + param << _T("continuationToken="); + param << web::uri::encode_uri(continuationToken); + params.push_back(param.str()); + } + + if (blobMetadata.blob_type() == title_storage_blob_type::binary) + { + string_t param = finalBlock ? _T("finalBlock=true") : _T("finalBlock=false"); + params.push_back(param); + } + + source << utils::get_query_from_params(params); + + return xbox_live_result(source.str()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TITLE_STORAGE_CPP_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentArbitrationState_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentArbitrationState_WinRT.h new file mode 100644 index 00000000..6f789e88 --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentArbitrationState_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Defines values used to indicate the state of a tournament game. +/// +public enum class TournamentArbitrationState +{ + /// + /// Results were fully uploaded and complete + /// + Completed = xbox::services::tournaments::tournament_arbitration_state::completed, + + /// + /// The match was canceled, for example in the case of forfeiting + /// + Canceled = xbox::services::tournaments::tournament_arbitration_state::canceled, + + /// + /// The match begun, but no players or servers reported results in time before the arbitration deadline + /// + NoResults = xbox::services::tournaments::tournament_arbitration_state::no_results, + + /// + /// Some results were received, and results were compiled based on this incomplete data + /// + PartialResults = xbox::services::tournaments::tournament_arbitration_state::partial_results, + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentArbitrationStatus_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentArbitrationStatus_WinRT.h new file mode 100644 index 00000000..0866e5e6 --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentArbitrationStatus_WinRT.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Defines values used to indicate the state of a tournament game. +/// +public enum class TournamentArbitrationStatus +{ + /// + /// Occurs before arbitrationStartTime. + /// + Waiting = xbox::services::tournaments::tournament_arbitration_status::waiting, + + /// + /// Occurs after arbitrationStartTime and at least one user has gone active. + /// + InProgress = xbox::services::tournaments::tournament_arbitration_status::in_progress, + + /// + /// The user has reported results and his role in the arbitration process is now done. + /// Occurs either after (arbitrationForfeitTime and no players have joined), (arbitration succeeded), or (arbitrationFinishTime). + /// + Complete = xbox::services::tournaments::tournament_arbitration_status::complete, + + /// + /// The user has gone active at least once and is now participating in the match. + /// + Playing = xbox::services::tournaments::tournament_arbitration_status::playing, + + /// + /// The user was not able to upload results before the arbitrationTimeout deadline. + /// + InComplete = xbox::services::tournaments::tournament_arbitration_status::incomplete +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentGameResultSource_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentGameResultSource_WinRT.h new file mode 100644 index 00000000..abe80e79 --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentGameResultSource_WinRT.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Defines values used to indicate the source for a tournament game state. +/// +public enum class TournamentGameResultSource +{ + /// + /// No game result source . + /// + None = xbox::services::tournaments::tournament_game_result_source::none, + + /// + /// Game result source is from client arbitration submit. + /// + Arbitration = xbox::services::tournaments::tournament_game_result_source::arbitration, + + /// + /// Game result is determined by game servers. + /// + Server = xbox::services::tournaments::tournament_game_result_source::server, + + /// + /// Game result is adjusted by tournament administrator. + /// + Adjusted = xbox::services::tournaments::tournament_game_result_source::adjusted, + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentGameResultState_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentGameResultState_WinRT.h new file mode 100644 index 00000000..7d5c0628 --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentGameResultState_WinRT.h @@ -0,0 +1,51 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Defines values used to indicate the state of a tournament game. +/// +public enum class TournamentGameResultState +{ + /// + /// No game + /// + NoContest = xbox::services::tournaments::tournament_game_result_state::no_contest, + + /// + /// Win + /// + Win = xbox::services::tournaments::tournament_game_result_state::win, + + /// + /// Loss + /// + Loss = xbox::services::tournaments::tournament_game_result_state::loss, + + /// + /// Draw + /// + Draw = xbox::services::tournaments::tournament_game_result_state::draw, + + /// + /// Rank + /// + Rank = xbox::services::tournaments::tournament_game_result_state::rank, + + /// + /// Didn't show up + /// + NoShow = xbox::services::tournaments::tournament_game_result_state::no_show, + +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentReference_WinRT.cpp b/Source/Services/Tournaments/WinRT/TournamentReference_WinRT.cpp new file mode 100644 index 00000000..cda6cecf --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentReference_WinRT.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TournamentReference_WinRT.h" +#include "Utils_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +TournamentReference::TournamentReference() +{ +} + +TournamentReference::TournamentReference( + _In_ xbox::services::tournaments::tournament_reference cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +const xbox::services::tournaments::tournament_reference& +TournamentReference::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentReference_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentReference_WinRT.h new file mode 100644 index 00000000..dfc3da5c --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentReference_WinRT.h @@ -0,0 +1,53 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Represents a reference to a multiplayer session. +/// +public ref class TournamentReference sealed +{ +public: + TournamentReference(); + + /// + /// The definition name of the tournament. + /// + DEFINE_PROP_GET_STR_OBJ(DefinitionName, definition_name); + + /// + /// The tournament ID specific to the tournament. + /// + DEFINE_PROP_GET_STR_OBJ(TournamentId, tournament_id); + + /// + /// The organizer name of the tournament. + /// + DEFINE_PROP_GET_STR_OBJ(Organizer, organizer); + + /// + /// The service configuration ID specific to the tournament. + /// + DEFINE_PROP_GET_STR_OBJ(ServiceConfigurationId, service_configuration_id); + +internal: + TournamentReference( + _In_ xbox::services::tournaments::tournament_reference cppObj + ); + + const xbox::services::tournaments::tournament_reference& GetCppObj() const; +private: + xbox::services::tournaments::tournament_reference m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END diff --git a/Source/Services/Tournaments/WinRT/TournamentRegistrationReason_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentRegistrationReason_WinRT.h new file mode 100644 index 00000000..74a99a7b --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentRegistrationReason_WinRT.h @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Defines values used to indicate the reason why the team in under selected tournament registration state. +/// +public enum class TournamentRegistrationReason +{ + /// + /// The team registration reason is unknown. + /// + Unknown = xbox::services::tournaments::tournament_registration_reason::unknown, + + /// + /// The registration for this tournament has been closed. + /// + RegistrationClosed = xbox::services::tournaments::tournament_registration_reason::registration_closed, + + /// + /// One of the team members have already been registered for this tournament. + /// + MemberAlreadyRegistered = xbox::services::tournaments::tournament_registration_reason::member_already_registered, + + /// + /// The tournament has reached its max team registration limit and is now full. + /// + TournamentFull = xbox::services::tournaments::tournament_registration_reason::tournament_full, + + /// + /// The team has been eliminated from the tournament. + /// + TeamEliminated = xbox::services::tournaments::tournament_registration_reason::team_eliminated, + + /// + /// The tournament has been completed. + /// + TournamentCompleted = xbox::services::tournaments::tournament_registration_reason::tournament_completed +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentRegistrationState_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentRegistrationState_WinRT.h new file mode 100644 index 00000000..e392f4dd --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentRegistrationState_WinRT.h @@ -0,0 +1,50 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Defines values used to indicate the team session registration state for a tournament. +/// +public enum class TournamentRegistrationState +{ + /// + /// The team registration state is unknown. + /// + Unknown = xbox::services::tournaments::tournament_registration_state::unknown, + + /// + /// Registration was successfully received by the Tournament service and will be eventually processed. + /// + Pending = xbox::services::tournaments::tournament_registration_state::pending, + + /// + /// Registration for the team was withdrawn. + /// + Withdrawn = xbox::services::tournaments::tournament_registration_state::withdrawn, + + /// + /// Registration could not be performed for the team. + /// + Rejected = xbox::services::tournaments::tournament_registration_state::rejected, + + /// + /// Registration has been confirmed by the Tournament service. + /// + Registered = xbox::services::tournaments::tournament_registration_state::registered, + + /// + /// The team has completed its participation in the Tournament. + /// + Completed = xbox::services::tournaments::tournament_registration_state::completed +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.cpp b/Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.cpp new file mode 100644 index 00000000..abdde2d7 --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.cpp @@ -0,0 +1,40 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "TournamentTeamResult_WinRT.h" + +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Platform; +using namespace concurrency; +using namespace xbox::services; +using namespace xbox::services::tournaments; +using namespace Microsoft::Xbox::Services::System; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +TournamentTeamResult::TournamentTeamResult() +{ +} + +TournamentTeamResult::TournamentTeamResult( + _In_ tournament_team_result cppObj + ) : + m_cppObj(std::move(cppObj)) +{ +} + +xbox::services::tournaments::tournament_team_result +TournamentTeamResult::GetCppObj() const +{ + return m_cppObj; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END \ No newline at end of file diff --git a/Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.h b/Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.h new file mode 100644 index 00000000..bbcfa5c7 --- /dev/null +++ b/Source/Services/Tournaments/WinRT/TournamentTeamResult_WinRT.h @@ -0,0 +1,45 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#include "xsapi/multiplayer.h" +#include "TournamentGameResultState_WinRT.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_BEGIN + +/// +/// Represents a teams result in a tournament +/// +public ref class TournamentTeamResult sealed +{ +public: + TournamentTeamResult(); + /// + /// The current tournament game's state for a team. + /// + DEFINE_PROP_GETSET_ENUM_OBJ(State, state, Microsoft::Xbox::Services::Tournaments::TournamentGameResultState, xbox::services::tournaments::tournament_game_result_state); + + /// + /// The ranking for the current tournament game's state for a team. + /// + DEFINE_PROP_GETSET_OBJ(Ranking, ranking, uint64); + +internal: + TournamentTeamResult( + _In_ xbox::services::tournaments::tournament_team_result cppObj + ); + + xbox::services::tournaments::tournament_team_result GetCppObj() const; +private: + + xbox::services::tournaments::tournament_team_result m_cppObj; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_END diff --git a/Source/Services/Tournaments/tournament_reference.cpp b/Source/Services/Tournaments/tournament_reference.cpp new file mode 100644 index 00000000..834e2308 --- /dev/null +++ b/Source/Services/Tournaments/tournament_reference.cpp @@ -0,0 +1,81 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "xsapi/multiplayer.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_CPP_BEGIN + +tournament_reference::tournament_reference() +{ +} + +tournament_reference::tournament_reference( + _In_ string_t definitionName, + _In_ string_t tournamentId, + _In_ string_t organizer, + _In_ string_t serviceConfigurationId + ) : + m_definitionName(std::move(definitionName)), + m_tournamentId(std::move(tournamentId)), + m_organizer(std::move(organizer)), + m_serviceConfigurationId(std::move(serviceConfigurationId)) +{ +} + +const string_t& +tournament_reference::service_configuration_id() const +{ + return m_serviceConfigurationId; +} + +const string_t& +tournament_reference::definition_name() const +{ + return m_definitionName; +} + +const string_t& +tournament_reference::tournament_id() const +{ + return m_tournamentId; +} + +const string_t& +tournament_reference::organizer() const +{ + return m_organizer; +} + +bool +tournament_reference::is_null() const +{ + return m_definitionName.empty() || m_tournamentId.empty() || m_organizer.empty() || m_serviceConfigurationId.empty(); +} + +xbox_live_result +tournament_reference::_Deserialize( + _In_ const web::json::value& json + ) +{ + if (json.is_null() || json.size() == 0) return xbox_live_result(); + + std::error_code errc = xbox_live_error_code::no_error; + auto response = tournament_reference( + utils::extract_json_string(json, _T("definitionName"), errc, true), + utils::extract_json_string(json, _T("tournamentId"), errc, true), + utils::extract_json_string(json, _T("organizer"), errc, true), + utils::extract_json_string(json, _T("scid"), errc, true) + ); + + return xbox_live_result(response, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_CPP_END \ No newline at end of file diff --git a/Source/Services/Tournaments/tournament_team_result.cpp b/Source/Services/Tournaments/tournament_team_result.cpp new file mode 100644 index 00000000..a8ef86d9 --- /dev/null +++ b/Source/Services/Tournaments/tournament_team_result.cpp @@ -0,0 +1,78 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "xsapi/multiplayer.h" +using namespace xbox::services::multiplayer; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_CPP_BEGIN + +tournament_team_result::tournament_team_result() : + m_state(tournament_game_result_state::no_contest), + m_ranking(0) +{ + +} + +tournament_team_result::tournament_team_result( + _In_ tournament_game_result_state state, + _In_ uint64_t ranking + ) : + m_state(state), + m_ranking(ranking) +{ + +} + +tournament_game_result_state tournament_team_result::state() const +{ + return m_state; +} + +uint64_t tournament_team_result::ranking() const +{ + return m_ranking; +} + +void tournament_team_result::set_state(_In_ tournament_game_result_state state) +{ + m_state = state; +} + +void tournament_team_result::set_ranking(_In_ uint64_t ranking) +{ + m_state = tournament_game_result_state::rank; + m_ranking = ranking; +} + +xbox_live_result tournament_team_result::_Deserialize( + _In_ const web::json::value& json + ) +{ + tournament_team_result returnObject; + if (json.is_null()) return xbox_live_result(returnObject); + + std::error_code errc = xbox_live_error_code::no_error; + + tournament_game_result_state state = multiplayer_service::_Convert_string_to_game_result_state( + utils::extract_json_string(json, _T("outcome"), errc) + ); + if (state == tournament_game_result_state::rank) + { + returnObject.set_ranking(static_cast(utils::extract_json_int(json, _T("ranking"), errc))); + } + else + { + returnObject.set_state(state); + } + + return xbox_live_result(returnObject, errc); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_TOURNAMENTS_CPP_END \ No newline at end of file diff --git a/Source/Shared/Desktop/local_config_desktop.cpp b/Source/Shared/Desktop/local_config_desktop.cpp new file mode 100644 index 00000000..ff09a50b --- /dev/null +++ b/Source/Shared/Desktop/local_config_desktop.cpp @@ -0,0 +1,177 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#if !TV_API && defined(_WIN32) +#include +#endif +#include "xsapi/system.h" +#include "local_config.h" +#include "xbox_system_factory.h" +#include "Utils.h" + +using namespace std; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +#if !TV_API && defined(_WIN32) + +xbox_live_result local_config::read() +{ + std::lock_guard guard(m_jsonConfigLock); + if (m_jsonConfig.size() > 0) + { + return xbox_live_result(); + } + + WCHAR configPath[MAX_PATH] = { 0 }; + if (0 != GetModuleFileName(0, configPath, MAX_PATH)) + { + WCHAR* lastSlash = wcsrchr(configPath, L'\\'); + if (lastSlash != nullptr) + { + *lastSlash = 0; + } + } + PathCchAppend(configPath, MAX_PATH, L"xboxservices.config"); + + string_t fileData = utils::read_file_to_string(configPath); + if(!fileData.empty()) + { + std::error_code err; + m_jsonConfig = web::json::value::parse(fileData, err); + if( !err ) + { + return xbox_live_result(); + } + else + { + return xbox_live_result( + std::make_error_code(xbox::services::xbox_live_error_code::invalid_config), + "Invalid config file" + ); + } + } + else + { + return xbox_live_result( + std::make_error_code(xbox::services::xbox_live_error_code::invalid_config), + "ERROR: Could not find xboxservices.config" + ); + } +} + +string_t local_config::get_registry_path() +{ + return L"Software\\XSAPI\\" + get_value_from_config(L"ClientId", true, _T("")); +} + +string_t local_config::get_value_from_local_storage( + _In_ const string_t& name + ) +{ + string_t value; + HKEY hKey = nullptr; + string_t regPath = get_registry_path(); + + // if we need to go deeper, we need to parse the path and rewrite from + // path a\\b\\c + subkey d\\e to path a\\b\\c\\d + subkey e. + size_t additionalSubkeysLoc = name.find_last_of(L"\\"); + + string_t finalPath; + string_t finalKey; + + if (additionalSubkeysLoc != string_t::npos) + { + finalPath = regPath.append(L"\\" + name.substr(0, additionalSubkeysLoc)); + finalKey = name.substr(additionalSubkeysLoc + 1); + } + else + { + finalPath = regPath; + finalKey = name; + } + + LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, finalPath.c_str(), 0, KEY_QUERY_VALUE, &hKey); + if (result == ERROR_SUCCESS) + { + value.resize(1024); + LONG keyResult = ERROR_MORE_DATA; // begin "needs more data" + while (keyResult == ERROR_MORE_DATA) + { + DWORD dwLength = static_cast(value.size() * sizeof(WCHAR)); + DWORD dwType = 0; + keyResult = RegQueryValueEx(hKey, finalKey.c_str(), NULL, &dwType, reinterpret_cast(&value[0]), &dwLength); + + if (ERROR_MORE_DATA == keyResult) + { + value.resize(value.length() * 2); + continue; + } + else if (ERROR_SUCCESS == keyResult) + { + value.resize((dwLength / sizeof(WCHAR)) - 1); + } + else + { + value.resize(0); + } + + break; + } + + RegCloseKey(hKey); + } + + return value; +} + +xbox_live_result local_config::write_value_to_local_storage(_In_ const string_t& name, _In_ const string_t& value) +{ + HKEY hKey = nullptr; + string_t regPath = get_registry_path(); + LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, regPath.c_str(), 0, KEY_WRITE, &hKey); + if (result == ERROR_SUCCESS) + { + result = RegSetValueExW(hKey, name.c_str(), 0, REG_SZ, reinterpret_cast(value.c_str()), static_cast(value.length() * sizeof(WORD))); + RegCloseKey(hKey); + } + + if (result == ERROR_SUCCESS) + { + return xbox_live_result(); + } + else + { + xbox_live_error_code err = static_cast(result); + return xbox_live_result(err, "write_value_to_local_storage failed"); + } +} + +xbox_live_result local_config::delete_value_from_local_storage( + _In_ const string_t& name + ) +{ + string_t regPath = get_registry_path(); + LONG result = RegDeleteKeyValue(HKEY_CURRENT_USER, regPath.c_str(), name.c_str()); + + if (result == ERROR_SUCCESS) + { + return xbox_live_result(); + } + else + { + xbox_live_error_code err = static_cast(result); + return xbox_live_result(err, "delete_value_from_local_storage failed"); + } +} + +#endif +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END + diff --git a/Source/Shared/Logger/ERA_ETW.h b/Source/Shared/Logger/ERA_ETW.h new file mode 100644 index 00000000..b7d79bd3 --- /dev/null +++ b/Source/Shared/Logger/ERA_ETW.h @@ -0,0 +1,466 @@ +//**********************************************************************` +//* This is an include file generated by Message Compiler. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#include +#include +#include "evntprov.h" +// +// Initial Defs +// +#if !defined(ETW_INLINE) +#define ETW_INLINE DECLSPEC_NOINLINE __inline +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +// +// Allow disabling of code generation +// +#ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION +#if !defined(McGenDebug) +#define McGenDebug(a,b) +#endif + + +#if !defined(MCGEN_TRACE_CONTEXT_DEF) +#define MCGEN_TRACE_CONTEXT_DEF +typedef struct _MCGEN_TRACE_CONTEXT +{ + TRACEHANDLE RegistrationHandle; + TRACEHANDLE Logger; + ULONGLONG MatchAnyKeyword; + ULONGLONG MatchAllKeyword; + ULONG Flags; + ULONG IsEnabled; + UCHAR Level; + UCHAR Reserve; + USHORT EnableBitsCount; + PULONG EnableBitMask; + const ULONGLONG* EnableKeyWords; + const UCHAR* EnableLevel; +} MCGEN_TRACE_CONTEXT, *PMCGEN_TRACE_CONTEXT; +#endif + +#if !defined(MCGEN_LEVEL_KEYWORD_ENABLED_DEF) +#define MCGEN_LEVEL_KEYWORD_ENABLED_DEF +FORCEINLINE +BOOLEAN +McGenLevelKeywordEnabled( + _In_ PMCGEN_TRACE_CONTEXT EnableInfo, + _In_ UCHAR Level, + _In_ ULONGLONG Keyword + ) +{ + // + // Check if the event Level is lower than the level at which + // the channel is enabled. + // If the event Level is 0 or the channel is enabled at level 0, + // all levels are enabled. + // + + if ((Level <= EnableInfo->Level) || // This also covers the case of Level == 0. + (EnableInfo->Level == 0)) { + + // + // Check if Keyword is enabled + // + + if ((Keyword == (ULONGLONG)0) || + ((Keyword & EnableInfo->MatchAnyKeyword) && + ((Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { + return TRUE; + } + } + + return FALSE; + +} +#endif + +#if !defined(MCGEN_EVENT_ENABLED_DEF) +#define MCGEN_EVENT_ENABLED_DEF +FORCEINLINE +BOOLEAN +McGenEventEnabled( + _In_ PMCGEN_TRACE_CONTEXT EnableInfo, + _In_ PCEVENT_DESCRIPTOR EventDescriptor + ) +{ + + return McGenLevelKeywordEnabled(EnableInfo, EventDescriptor->Level, EventDescriptor->Keyword); + +} +#endif + + +// +// EnableCheckMacro +// +#ifndef MCGEN_ENABLE_CHECK +#define MCGEN_ENABLE_CHECK(Context, Descriptor) (Context.IsEnabled && McGenEventEnabled(&Context, &Descriptor)) +#endif + +#if !defined(MCGEN_CONTROL_CALLBACK) +#define MCGEN_CONTROL_CALLBACK + +DECLSPEC_NOINLINE __inline +VOID +__stdcall +McGenControlCallbackV2( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext + ) +/*++ + +Routine Description: + + This is the notification callback for Windows Vista and later. + +Arguments: + + SourceId - The GUID that identifies the session that enabled the provider. + + ControlCode - The parameter indicates whether the provider + is being enabled or disabled. + + Level - The level at which the event is enabled. + + MatchAnyKeyword - The bitmask of keywords that the provider uses to + determine the category of events that it writes. + + MatchAllKeyword - This bitmask additionally restricts the category + of events that the provider writes. + + FilterData - The provider-defined data. + + CallbackContext - The context of the callback that is defined when the provider + called EtwRegister to register itself. + +Remarks: + + ETW calls this function to notify provider of enable/disable + +--*/ +{ + PMCGEN_TRACE_CONTEXT Ctx = (PMCGEN_TRACE_CONTEXT)CallbackContext; + ULONG Ix; +#ifndef MCGEN_PRIVATE_ENABLE_CALLBACK_V2 + UNREFERENCED_PARAMETER(SourceId); + UNREFERENCED_PARAMETER(FilterData); +#endif + + if (Ctx == NULL) { + return; + } + + switch (ControlCode) { + + case EVENT_CONTROL_CODE_ENABLE_PROVIDER: + Ctx->Level = Level; + Ctx->MatchAnyKeyword = MatchAnyKeyword; + Ctx->MatchAllKeyword = MatchAllKeyword; + Ctx->IsEnabled = EVENT_CONTROL_CODE_ENABLE_PROVIDER; + + for (Ix = 0; Ix < Ctx->EnableBitsCount; Ix += 1) { + if (McGenLevelKeywordEnabled(Ctx, Ctx->EnableLevel[Ix], Ctx->EnableKeyWords[Ix]) != FALSE) { + Ctx->EnableBitMask[Ix >> 5] |= (1 << (Ix % 32)); + } else { + Ctx->EnableBitMask[Ix >> 5] &= ~(1 << (Ix % 32)); + } + } + break; + + case EVENT_CONTROL_CODE_DISABLE_PROVIDER: + Ctx->IsEnabled = EVENT_CONTROL_CODE_DISABLE_PROVIDER; + Ctx->Level = 0; + Ctx->MatchAnyKeyword = 0; + Ctx->MatchAllKeyword = 0; + if (Ctx->EnableBitsCount > 0) { + RtlZeroMemory(Ctx->EnableBitMask, (((Ctx->EnableBitsCount - 1) / 32) + 1) * sizeof(ULONG)); + } + break; + + default: + break; + } + +#ifdef MCGEN_PRIVATE_ENABLE_CALLBACK_V2 + // + // Call user defined callback + // + MCGEN_PRIVATE_ENABLE_CALLBACK_V2( + SourceId, + ControlCode, + Level, + MatchAnyKeyword, + MatchAllKeyword, + FilterData, + CallbackContext + ); +#endif + + return; +} + +#endif +#endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION +//+ +// Provider Microsoft.Xbox.Services.Tracing Event Count 4 +//+ +EXTERN_C __declspec(selectany) const GUID ProviderGuid = {0x9594a560, 0xe985, 0x4ee6, {0xb0, 0xb5, 0x0d, 0xac, 0x4f, 0x92, 0x41, 0x44}}; + +// +// Event Descriptors +// +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR XSAPI_Verbose = {0x1, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0}; +#define XSAPI_Verbose_value 0x1 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR XSAPI_Info = {0x2, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0}; +#define XSAPI_Info_value 0x2 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR XSAPI_Warn = {0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0}; +#define XSAPI_Warn_value 0x3 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR XSAPI_Error = {0x4, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}; +#define XSAPI_Error_value 0x4 + +// +// Note on Generate Code from Manifest for Windows Vista and above +// +//Structures : are handled as a size and pointer pairs. The macro for the event will have an extra +//parameter for the size in bytes of the structure. Make sure that your structures have no extra padding. +// +//Strings: There are several cases that can be described in the manifest. For array of variable length +//strings, the generated code will take the count of characters for the whole array as an input parameter. +// +//SID No support for array of SIDs, the macro will take a pointer to the SID and use appropriate +//GetLengthSid function to get the length. +// + +// +// Allow disabling of code generation +// +#ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +// +// Globals +// + + +// +// Event Enablement Bits +// + +EXTERN_C __declspec(selectany) DECLSPEC_CACHEALIGN ULONG Microsoft_Xbox_Services_TracingEnableBits[1]; +EXTERN_C __declspec(selectany) const ULONGLONG Microsoft_Xbox_Services_TracingKeywords[4] = {0x0, 0x0, 0x0, 0x0}; +EXTERN_C __declspec(selectany) const UCHAR Microsoft_Xbox_Services_TracingLevels[4] = {5, 4, 3, 2}; +EXTERN_C __declspec(selectany) MCGEN_TRACE_CONTEXT ProviderGuid_Context = {0, 0, 0, 0, 0, 0, 0, 0, 4, Microsoft_Xbox_Services_TracingEnableBits, Microsoft_Xbox_Services_TracingKeywords, Microsoft_Xbox_Services_TracingLevels}; + +EXTERN_C __declspec(selectany) REGHANDLE Microsoft_Xbox_Services_TracingHandle = (REGHANDLE)0; + +#if !defined(McGenEventRegisterUnregister) +#define McGenEventRegisterUnregister +#pragma warning(push) +#pragma warning(disable:6103) +DECLSPEC_NOINLINE __inline +ULONG __stdcall +McGenEventRegister( + _In_ LPCGUID ProviderId, + _In_opt_ PENABLECALLBACK EnableCallback, + _In_opt_ PVOID CallbackContext, + _Inout_ PREGHANDLE RegHandle + ) +/*++ + +Routine Description: + + This function registers the provider with ETW USER mode. + +Arguments: + ProviderId - Provider ID to be register with ETW. + + EnableCallback - Callback to be used. + + CallbackContext - Context for this provider. + + RegHandle - Pointer to registration handle. + +Remarks: + + If the handle != NULL will return ERROR_SUCCESS + +--*/ +{ + ULONG Error; + + + if (*RegHandle) { + // + // already registered + // + return ERROR_SUCCESS; + } + + Error = EventRegister( ProviderId, EnableCallback, CallbackContext, RegHandle); + + return Error; +} +#pragma warning(pop) + + +DECLSPEC_NOINLINE __inline +ULONG __stdcall +McGenEventUnregister(_Inout_ PREGHANDLE RegHandle) +/*++ + +Routine Description: + + Unregister from ETW USER mode + +Arguments: + RegHandle this is the pointer to the provider context +Remarks: + If provider has not been registered, RegHandle == NULL, + return ERROR_SUCCESS +--*/ +{ + ULONG Error; + + + if(!(*RegHandle)) { + // + // Provider has not registerd + // + return ERROR_SUCCESS; + } + + Error = EventUnregister(*RegHandle); + *RegHandle = (REGHANDLE)0; + + return Error; +} +#endif +// +// Register with ETW Vista + +// +#ifndef EventRegisterMicrosoft_Xbox_Services_Tracing +#define EventRegisterMicrosoft_Xbox_Services_Tracing() McGenEventRegister(&ProviderGuid, McGenControlCallbackV2, &ProviderGuid_Context, &Microsoft_Xbox_Services_TracingHandle) +#endif + +// +// UnRegister with ETW +// +#ifndef EventUnregisterMicrosoft_Xbox_Services_Tracing +#define EventUnregisterMicrosoft_Xbox_Services_Tracing() McGenEventUnregister(&Microsoft_Xbox_Services_TracingHandle) +#endif + +// +// Enablement check macro for XSAPI_Verbose +// + +#define EventEnabledXSAPI_Verbose() ((Microsoft_Xbox_Services_TracingEnableBits[0] & 0x00000001) != 0) + +// +// Event Macro for XSAPI_Verbose +// +#define EventWriteXSAPI_Verbose(Catalog, Message)\ + EventEnabledXSAPI_Verbose() ?\ + Template_ss(Microsoft_Xbox_Services_TracingHandle, &XSAPI_Verbose, Catalog, Message)\ + : ERROR_SUCCESS\ + +// +// Enablement check macro for XSAPI_Info +// + +#define EventEnabledXSAPI_Info() ((Microsoft_Xbox_Services_TracingEnableBits[0] & 0x00000002) != 0) + +// +// Event Macro for XSAPI_Info +// +#define EventWriteXSAPI_Info(Catalog, Message)\ + EventEnabledXSAPI_Info() ?\ + Template_ss(Microsoft_Xbox_Services_TracingHandle, &XSAPI_Info, Catalog, Message)\ + : ERROR_SUCCESS\ + +// +// Enablement check macro for XSAPI_Warn +// + +#define EventEnabledXSAPI_Warn() ((Microsoft_Xbox_Services_TracingEnableBits[0] & 0x00000004) != 0) + +// +// Event Macro for XSAPI_Warn +// +#define EventWriteXSAPI_Warn(Catalog, Message)\ + EventEnabledXSAPI_Warn() ?\ + Template_ss(Microsoft_Xbox_Services_TracingHandle, &XSAPI_Warn, Catalog, Message)\ + : ERROR_SUCCESS\ + +// +// Enablement check macro for XSAPI_Error +// + +#define EventEnabledXSAPI_Error() ((Microsoft_Xbox_Services_TracingEnableBits[0] & 0x00000008) != 0) + +// +// Event Macro for XSAPI_Error +// +#define EventWriteXSAPI_Error(Catalog, Message)\ + EventEnabledXSAPI_Error() ?\ + Template_ss(Microsoft_Xbox_Services_TracingHandle, &XSAPI_Error, Catalog, Message)\ + : ERROR_SUCCESS\ + +#endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION + + +// +// Allow Diasabling of code generation +// +#ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +// +// Template Functions +// +// +//Template from manifest : tidMessage +// +#ifndef Template_ss_def +#define Template_ss_def +ETW_INLINE +ULONG +Template_ss( + _In_ REGHANDLE RegHandle, + _In_ PCEVENT_DESCRIPTOR Descriptor, + _In_opt_ LPCSTR _Arg0, + _In_opt_ LPCSTR _Arg1 + ) +{ +#define ARGUMENT_COUNT_ss 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ss]; + + EventDataDescCreate(&EventData[0], + (_Arg0 != NULL) ? _Arg0 : "NULL", + (_Arg0 != NULL) ? (ULONG)((strlen(_Arg0) + 1) * sizeof(CHAR)) : (ULONG)sizeof("NULL")); + + EventDataDescCreate(&EventData[1], + (_Arg1 != NULL) ? _Arg1 : "NULL", + (_Arg1 != NULL) ? (ULONG)((strlen(_Arg1) + 1) * sizeof(CHAR)) : (ULONG)sizeof("NULL")); + + return EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_ss, EventData); +} +#endif + +#endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +#if defined(__cplusplus) +}; +#endif + diff --git a/Source/Shared/Logger/ERA_ETW.man b/Source/Shared/Logger/ERA_ETW.man new file mode 100644 index 00000000..2ae8e3fa --- /dev/null +++ b/Source/Shared/Logger/ERA_ETW.man @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Shared/Logger/android/logcat_output.cpp b/Source/Shared/Logger/android/logcat_output.cpp new file mode 100644 index 00000000..091794f7 --- /dev/null +++ b/Source/Shared/Logger/android/logcat_output.cpp @@ -0,0 +1,43 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Logger/android/logcat_output.h" +#include + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +void logcat_output::add_log(_In_ const log_entry& entry) +{ + std::string category = entry.category(); + log_level level = entry.get_log_level(); + std::string tag = (category.empty()) ? "XSAPI.Android" : category; + + switch (level) + { + case log_level::debug: + __android_log_print(ANDROID_LOG_DEBUG, tag.c_str(), entry.msg_stream().str().c_str()); + break; + case log_level::info: + __android_log_print(ANDROID_LOG_INFO, tag.c_str(), entry.msg_stream().str().c_str()); + break; + case log_level::warn: + __android_log_print(ANDROID_LOG_WARN, tag.c_str(), entry.msg_stream().str().c_str()); + break; + case log_level::error: + __android_log_print(ANDROID_LOG_ERROR, tag.c_str(), entry.msg_stream().str().c_str()); + break; + default: + break; + + } + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/android/logcat_output.h b/Source/Shared/Logger/android/logcat_output.h new file mode 100644 index 00000000..d11fb2b7 --- /dev/null +++ b/Source/Shared/Logger/android/logcat_output.h @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "Logger/log.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +class logcat_output : public log_output +{ +public: + logcat_output() : log_output(log_output_level_setting::use_own_setting, log_level::debug) {} + void add_log(_In_ const log_entry& entry) override; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/console_output.cpp b/Source/Shared/Logger/console_output.cpp new file mode 100644 index 00000000..b56721b4 --- /dev/null +++ b/Source/Shared/Logger/console_output.cpp @@ -0,0 +1,22 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include +#include "console_output.h" + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +void console_output::write(_In_ const std::string& msg) +{ + std::cout << msg; +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/console_output.h b/Source/Shared/Logger/console_output.h new file mode 100644 index 00000000..434d4787 --- /dev/null +++ b/Source/Shared/Logger/console_output.h @@ -0,0 +1,23 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "log.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +class console_output: public log_output +{ +public: + console_output() : log_output(log_output_level_setting::use_logger_setting, log_level::off) {} + + void write(_In_ const std::string& msg) override; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/custom_output.cpp b/Source/Shared/Logger/custom_output.cpp new file mode 100644 index 00000000..53de69bf --- /dev/null +++ b/Source/Shared/Logger/custom_output.cpp @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "custom_output.h" +#include "xsapi/system.h" + +using namespace xbox::services::system; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +void custom_output::add_log(_In_ const log_entry& entry) +{ + xbox_services_diagnostics_trace_level logLevel = xbox_services_diagnostics_trace_level::off; + switch (entry.get_log_level()) + { + case log_level::off: logLevel = xbox_services_diagnostics_trace_level::off; break; + case log_level::error: logLevel = xbox_services_diagnostics_trace_level::error; break; + case log_level::warn: logLevel = xbox_services_diagnostics_trace_level::warning; break; + case log_level::info: logLevel = xbox_services_diagnostics_trace_level::info; break; + case log_level::debug: logLevel = xbox_services_diagnostics_trace_level::verbose; break; + } + + xbox_live_services_settings::get_singleton_instance()->_Raise_logging_event(logLevel, entry.category(), entry.msg_stream().str()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/custom_output.h b/Source/Shared/Logger/custom_output.h new file mode 100644 index 00000000..87714f2a --- /dev/null +++ b/Source/Shared/Logger/custom_output.h @@ -0,0 +1,23 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "log.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +class custom_output: public log_output +{ +public: + custom_output() : log_output(log_output_level_setting::use_logger_setting, log_level::off) {} + + void add_log(_In_ const log_entry& entry) override; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/debug_output.cpp b/Source/Shared/Logger/debug_output.cpp new file mode 100644 index 00000000..c07d53a4 --- /dev/null +++ b/Source/Shared/Logger/debug_output.cpp @@ -0,0 +1,21 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "debug_output.h" + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +void debug_output::write(_In_ const std::string& msg) +{ + OutputDebugStringA(msg.c_str()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/debug_output.h b/Source/Shared/Logger/debug_output.h new file mode 100644 index 00000000..f66be65c --- /dev/null +++ b/Source/Shared/Logger/debug_output.h @@ -0,0 +1,23 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "log.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +class debug_output : public log_output +{ +public: + debug_output() : log_output(log_output_level_setting::use_logger_setting, log_level::off) {} + + void write(_In_ const std::string& msg) override; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/era_etw.rc b/Source/Shared/Logger/era_etw.rc new file mode 100644 index 00000000..46cb28d0 --- /dev/null +++ b/Source/Shared/Logger/era_etw.rc @@ -0,0 +1,3 @@ +LANGUAGE 0x9,0x1 +1 11 "era_etw_MSG00001.bin" +1 WEVT_TEMPLATE "era_etwTEMP.BIN" diff --git a/Source/Shared/Logger/era_etwTEMP.BIN b/Source/Shared/Logger/era_etwTEMP.BIN new file mode 100644 index 0000000000000000000000000000000000000000..5908881ab7cfe7d67158dfc3eefadbe01059efae GIT binary patch literal 866 zcmb7CJxc>Y6nvLl5-fs^LJA873ky3%(AdPw6(L`T9v20RM2Inv4@g96sH0{3v7?M?kwiRx~{Ne zV1miEP8o=*FcAf`5E;T&p*oew7lvK`k3Wr*nivJRi|}jka}HcSyg^n=V3oTBHv~cN z9lp8VbBVH+k(FnqOeb}V1%Hpo%VNO41KNrJ^B&ro1`YtDtySO%@HUkZ*&M=aVARn> zBMP6xYZ_3nssw&Q*-L<1_dHcExiWAKsPgL!2Wd2D4ZBS*Ydf}-gv6_)xssFEbTW1q w3z-?m#P^lO|G{&y_*C+g`*_limpN7c-bXJolJ*|`b059TSQ^yxyM6RTUzgi-9{>OV literal 0 HcmV?d00001 diff --git a/Source/Shared/Logger/era_etw_MSG00001.bin b/Source/Shared/Logger/era_etw_MSG00001.bin new file mode 100644 index 0000000000000000000000000000000000000000..9a7565434f3b64fa0655d1d21ab61e04680fa64e GIT binary patch literal 116 zcmZQ%U|?WkU6!!%3 f)4*zTfhtOX^7%j!guXC_RG_{jplC6W1rY}T+qez6 literal 0 HcmV?d00001 diff --git a/Source/Shared/Logger/era_etw_headergen_readme.txt b/Source/Shared/Logger/era_etw_headergen_readme.txt new file mode 100644 index 00000000..29d76074 --- /dev/null +++ b/Source/Shared/Logger/era_etw_headergen_readme.txt @@ -0,0 +1,21 @@ +run command to generate the header: +mc -um ERA_ETW.man -z era_etw + +start tracing for ERA: +Start tracing with system logs: +xbrun /x/title /O tracelog -start CustomSession -f d:\custom03.etl -eflag PROC_THREAD+LOADER+DPC+INTERRUPT+CSWITCH+PROFILE -guid #{9594A560-E985-4EE6-B0B5-0DAC4F924144} -stackwalk PROFILE+CSWITCH + +Start tracing with XSAPI etw only: +xbrun /x/title /O tracelog -start CustomSession -f d:\custom03.etl -guid #{9594A560-E985-4EE6-B0B5-0DAC4F924144} + +Stop tracign for ERA: +xbrun /x/title /O tracelog -stop CustomSession + +Merge if you started with system: +xbrun /x/title /O tracelog -merge d:\custom03.etl d:\custom03_merge.etl + +copy to your local machine: +If you merged with system log: xbcp /x/title xd:\custom03_merge.etl f: +If you didn't merge: xbcp /x/title xd:\custom03.etl f: + + diff --git a/Source/Shared/Logger/etw_output.cpp b/Source/Shared/Logger/etw_output.cpp new file mode 100644 index 00000000..359c3a2e --- /dev/null +++ b/Source/Shared/Logger/etw_output.cpp @@ -0,0 +1,70 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" + +#ifndef _TRACEHANDLE_DEFINED +#define _TRACEHANDLE_DEFINED +typedef ULONG64 TRACEHANDLE, *PTRACEHANDLE; +#endif +#define EVENT_CONTROL_CODE_DISABLE_PROVIDER 0 +#define EVENT_CONTROL_CODE_ENABLE_PROVIDER 1 +#define EVENT_CONTROL_CODE_CAPTURE_STATE 2 + +#include "etw_output.h" +#include "ERA_ETW.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +etw_output::etw_output(): + log_output(log_output_level_setting::use_own_setting, log_level::debug) +{ +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN10 + TraceLoggingRegister(g_hUnitTestTraceLoggingProvider); +#elif TV_API + EventRegisterMicrosoft_Xbox_Services_Tracing(); +#endif +} + +etw_output::~etw_output() +{ +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN10 + TraceLoggingUnregister(g_hUnitTestTraceLoggingProvider); +#elif TV_API + EventUnregisterMicrosoft_Xbox_Services_Tracing(); +#endif +} + +void etw_output::add_log(_In_ const log_entry& entry) +{ +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN10 + switch (entry.get_log_level()) + { + case log_level::error: add_log_t(entry); break; + case log_level::warn: add_log_t(entry); break; + case log_level::info: add_log_t(entry); break; + case log_level::debug: add_log_t(entry); break; + } + + +#elif TV_API + ULONG status = NO_ERROR; + + switch (entry.get_log_level()) + { + case log_level::error: status = EventWriteXSAPI_Error(entry.category().c_str(), entry.msg_stream().str().c_str()); break; + case log_level::warn: status = EventWriteXSAPI_Warn(entry.category().c_str(), entry.msg_stream().str().c_str()); break; + case log_level::info: status = EventWriteXSAPI_Info(entry.category().c_str(), entry.msg_stream().str().c_str()); break; + case log_level::debug: status = EventWriteXSAPI_Verbose(entry.category().c_str(), entry.msg_stream().str().c_str()); break; + } +#endif + +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END \ No newline at end of file diff --git a/Source/Shared/Logger/etw_output.h b/Source/Shared/Logger/etw_output.h new file mode 100644 index 00000000..767c7672 --- /dev/null +++ b/Source/Shared/Logger/etw_output.h @@ -0,0 +1,41 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once +#include "log.h" +#include +#include "telemetry.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +class etw_output : public log_output +{ +public: + etw_output(); + + ~etw_output(); + + void add_log(_In_ const log_entry& entry) override; + +private: + // Use template for LEVEl as _TraceLoggingLevel itself is a template method, cannot use variable on it. + template + void add_log_t(_In_ const log_entry& entry) + { + TraceLoggingWrite( + g_hUnitTestTraceLoggingProvider, + "XSAPI", + TraceLoggingLevel(LEVEL), + TraceLoggingString(entry.category().c_str(), "category"), + TraceLoggingString(entry.msg_stream().str().c_str(), "message") + ); + } +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END \ No newline at end of file diff --git a/Source/Shared/Logger/iOS/debug_output_ios.cpp b/Source/Shared/Logger/iOS/debug_output_ios.cpp new file mode 100644 index 00000000..a47d104c --- /dev/null +++ b/Source/Shared/Logger/iOS/debug_output_ios.cpp @@ -0,0 +1,21 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "debug_output.h" + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +void debug_output::write(_In_ const std::string& msg) +{ + printf("%s\n", msg.c_str()); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/log.cpp b/Source/Shared/Logger/log.cpp new file mode 100644 index 00000000..f8569e31 --- /dev/null +++ b/Source/Shared/Logger/log.cpp @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "log.h" + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +std::shared_ptr logger::s_logger = nullptr; + +void logger::add_log_output(std::shared_ptr output) +{ + m_log_outputs.emplace_back(output); + if (output->level_setting() == log_output_level_setting::use_logger_setting) + { + output->set_log_level(m_logLevel); + } +}; + +void logger::set_log_level(log_level level) +{ + m_logLevel = level; + + for (const auto& output : m_log_outputs) + { + if (output->level_setting() == log_output_level_setting::use_logger_setting) + { + output->set_log_level(level); + } + } +} + +void logger::add_log(const log_entry& logEntry) +{ + for(const auto& output : m_log_outputs) + { + if (output->log_level_enabled(logEntry.get_log_level())) + { + output->add_log(logEntry); + } + } +} + +void logger::operator+=(const log_entry& logEntry) +{ + add_log(logEntry); +} + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/log.h b/Source/Shared/Logger/log.h new file mode 100644 index 00000000..82566d94 --- /dev/null +++ b/Source/Shared/Logger/log.h @@ -0,0 +1,164 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#pragma once + +#define DEFAULT_LOGGER xbox::services::logger::get_logger() +#define IF_LOGGER_ENABLED(logger) if(logger != nullptr) + +#define LOG(logger, level, category, msg) IF_LOGGER_ENABLED(logger) logger->add_log(xbox::services::log_entry(level, category, msg)) +#define LOGS(logger, level, category) IF_LOGGER_ENABLED(logger) *logger += xbox::services::log_entry(level, category) + +// default logging macro +const char defaultCategory[] = ""; +#define IF_LOG_ERROR() IF_LOG_LEVEL_ENABLED(DEFAULT_LOGGER, xbox::services::log_level::error) +#define LOG_ERROR(msg) LOG(DEFAULT_LOGGER, xbox::services::log_level::error, defaultCategory, msg) +#define LOG_ERROR_IF(boolean_expression, msg) if(boolean_expression) LOG_ERROR(msg) +#define LOGS_ERROR LOGS(DEFAULT_LOGGER, xbox::services::log_level::error, defaultCategory) +#define LOGS_ERROR_IF(boolean_expression) if(boolean_expression) LOGS_ERROR + +#define IF_LOG_WARN() IF_LOG_LEVEL_ENABLED(DEFAULT_LOGGER, xbox::services::log_level::warn) +#define LOG_WARN(msg) LOG(DEFAULT_LOGGER, xbox::services::log_level::warn, defaultCategory, msg) +#define LOG_WARN_IF(boolean_expression, msg) if(boolean_expression) LOG_WARN(msg) +#define LOGS_WARN LOGS(DEFAULT_LOGGER, xbox::services::log_level::warn, defaultCategory) +#define LOGS_WARN_IF(boolean_expression) if(boolean_expression) LOGS_WARN + +#define IF_LOG_INFO() IF_LOG_LEVEL_ENABLED(DEFAULT_LOGGER, xbox::services::log_level::info) +#define LOG_INFO(msg) LOG(DEFAULT_LOGGER, xbox::services::log_level::info, defaultCategory, msg) +#define LOG_INFO_IF(boolean_expression, msg) if(boolean_expression) LOG_INFO(msg) +#define LOGS_INFO LOGS(DEFAULT_LOGGER, xbox::services::log_level::info, defaultCategory) +#define LOGS_INFO_IF(boolean_expression) if(boolean_expression) LOGS_INFO + +#define IF_LOG_DEBUG() IF_LOG_LEVEL_ENABLED(DEFAULT_LOGGER, xbox::services::log_level::debug) +#define LOG_DEBUG(msg) LOG(DEFAULT_LOGGER, xbox::services::log_level::debug, defaultCategory, msg) +#define LOG_DEBUG_IF(boolean_expression, msg) if(boolean_expression) LOG_DEBUG(msg) +#define LOGS_DEBUG LOGS(DEFAULT_LOGGER, xbox::services::log_level::debug, defaultCategory) +#define LOGS_DEBUG_IF(boolean_expression) if(boolean_expression) LOGS_DEBUG + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +enum class log_level +{ + off, + error, + warn, + info, + debug +}; + +class log_entry +{ +public: + log_entry(log_level level, std::string category); + + log_entry(log_level level, std::string category, std::string msg); + + std::string level_to_string() const; + + const std::stringstream& msg_stream() const { return m_message; } + + const std::string& category() const { return m_category; } + log_level get_log_level() const { return m_logLevel; } + + log_entry& operator<<(const char* data) + { + m_message << utility::conversions::to_utf8string(data); + return *this; + } + + log_entry& operator<<(const std::string& data) + { + m_message << utility::conversions::to_utf8string(data); + return *this; + } + +#if !XSAPI_U + log_entry& operator<<(const wchar_t* data) + { + m_message << utility::conversions::to_utf8string(data); + return *this; + } + + log_entry& operator<<(const std::wstring& data) + { + m_message << utility::conversions::to_utf8string(data); + return *this; + } +#endif + + template + log_entry& operator<<(const T& data) + { + m_message << data; + return *this; + } + +private: + log_level m_logLevel; + std::string m_category; + std::stringstream m_message; +}; + +enum log_output_level_setting +{ + use_logger_setting, + use_own_setting +}; + +class log_output +{ +public: + // When log_output_type is set to use_logger_setting, the level parameter will be ignored. + log_output(log_output_level_setting type, log_level level); + + virtual void add_log(_In_ const log_entry& entry); + + log_output_level_setting level_setting() const { return m_levelSetting; } + + bool log_level_enabled(log_level level) const { return level <= m_logLevel; } + + void set_log_level(log_level level) { m_logLevel = level; } + +protected: + // This function is to write the string to the final output, don't need to be thread safe. + virtual void write(_In_ const std::string& msg); + + virtual std::string format_log(_In_ const log_entry& entry); + +private: + log_output_level_setting m_levelSetting; + log_level m_logLevel; + mutable std::mutex m_mutex; +}; + +class logger +{ +public: + logger() : m_logLevel(log_level::warn) {} + + static void create_logger() { s_logger = std::make_shared(); } + static void release_logger() { s_logger = nullptr; } + static const std::shared_ptr& get_logger() { return s_logger; } + + void set_log_level(log_level level); + + void add_log_output(std::shared_ptr output); + + void add_log(const log_entry& entry); + void operator+=(const log_entry& record); + + +private: + static std::shared_ptr s_logger; + + std::vector> m_log_outputs; + log_level m_logLevel; +}; + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/log_entry.cpp b/Source/Shared/Logger/log_entry.cpp new file mode 100644 index 00000000..27c0397b --- /dev/null +++ b/Source/Shared/Logger/log_entry.cpp @@ -0,0 +1,47 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "log.h" + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +log_entry::log_entry(log_level level, std::string category) : + m_logLevel(level), + m_category(std::move(category)) +{ + +} + +log_entry::log_entry(log_level level, std::string category, std::string msg) : + m_logLevel(level), + m_category(std::move(category)) +{ + m_message << msg; +} + +std::string log_entry::level_to_string() const +{ + switch (m_logLevel) + { + case log_level::error: + return "error"; + case log_level::warn: + return "warn"; + case log_level::info: + return "info"; + case log_level::debug: + return "debug"; + } + + return ""; +} + + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END diff --git a/Source/Shared/Logger/log_output.cpp b/Source/Shared/Logger/log_output.cpp new file mode 100644 index 00000000..640090cc --- /dev/null +++ b/Source/Shared/Logger/log_output.cpp @@ -0,0 +1,59 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +#include "pch.h" +#include "Logger/Log.h" +#include + +NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN + +log_output::log_output(log_output_level_setting setting, log_level level): + m_levelSetting(setting), + m_logLevel(level) +{ +} + +void log_output::add_log(_In_ const log_entry& entry) +{ + std::string msg = format_log(entry); + { + std::lock_guard lock(m_mutex); + write(msg); + } +} + +void log_output::write(_In_ const std::string& msg) +{ + UNREFERENCED_PARAMETER(msg); +} + +std::string +log_output::format_log(_In_ const log_entry& entry) +{ + std::stringstream stream; + std::time_t t = std::time(nullptr); + std::tm tm_snapshot; +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) + localtime_s(&tm_snapshot, &t); +#else + localtime_r(&t, &tm_snapshot); // POSIX +#endif + + // format : "