Родитель
525786e8de
Коммит
f1a347b91f
|
@ -1 +1 @@
|
|||
Subproject commit b8e335836e0c6bc6b83f943b1c9ad3c815c1aab0
|
||||
Subproject commit 41e4e73cc1dce236e0c9d674cd7096121493b48e
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#if !defined(__cplusplus)
|
||||
#error C++11 required
|
||||
#endif
|
||||
|
||||
// Attention: This file is intended for internal uses only.
|
||||
// Its use is not recommended and not supported.
|
||||
|
||||
#include <Xal/xal_types.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
// Marketing State
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Enum defining the various marketing states.
|
||||
/// </summary>
|
||||
typedef enum XalMarketingState
|
||||
{
|
||||
/// <summary>Existing user</summary>
|
||||
XalMarketingState_ExistingUser = 0,
|
||||
/// <summary>User went through account creation</summary>
|
||||
XalMarketingState_NewUser = 1,
|
||||
/// <summary>User went through account creation and saw the first party marketing notice</summary>
|
||||
XalMarketingState_NewUserFirstPartyNotice = 2,
|
||||
} XalMarketingState;
|
||||
|
||||
STDAPI XalUserGetMarketingState(
|
||||
_In_ XalUserHandle user,
|
||||
_Out_ XalMarketingState* marketingState
|
||||
) noexcept;
|
||||
|
||||
}
|
|
@ -20,6 +20,6 @@ extern "C"
|
|||
/// YYYYMMDD Date string describing the date the build was created
|
||||
/// rrr QFE number (000 indicates base release)
|
||||
/// </summary>
|
||||
#define XAL_VERSION "2022.08.20220825.000"
|
||||
#define XAL_VERSION "2022.10.20221205.000"
|
||||
|
||||
}
|
||||
|
|
|
@ -463,7 +463,7 @@ STDAPI_(bool) XblSocialManagerPresenceRecordIsUserPlayingTitle(
|
|||
/// <remarks>
|
||||
/// Call this API after calling either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// The XblSocialManagerUserGroupHandle is returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// event in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerUserGroupGetType(
|
||||
|
@ -482,7 +482,7 @@ STDAPI XblSocialManagerUserGroupGetType(
|
|||
/// <remarks>
|
||||
/// Call this API after calling either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event
|
||||
/// The XblSocialManagerUserGroupHandle is returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event
|
||||
/// in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerUserGroupGetLocalUser(
|
||||
|
@ -501,7 +501,7 @@ STDAPI XblSocialManagerUserGroupGetLocalUser(
|
|||
/// If the group is not a filter group, E_UNEXPECTED will be returned.
|
||||
/// Call this API after either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// The XblSocialManagerUserGroupHandle is returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// event in <see cref="XblSocialManagerDoWork"/>.<br/>
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerUserGroupGetFilters(
|
||||
|
@ -533,8 +533,7 @@ typedef const XblSocialManagerUser* const* XblSocialManagerUserPtrArray;
|
|||
/// they are statically sized and trivially copyable.
|
||||
/// Call this API after calling either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// event in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// Wait for <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event in <see cref="XblSocialManagerDoWork"/>. Prior to this the group will be empty.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerUserGroupGetUsers(
|
||||
_In_ XblSocialManagerUserGroupHandle group,
|
||||
|
@ -555,8 +554,7 @@ STDAPI XblSocialManagerUserGroupGetUsers(
|
|||
/// but for filter-based groups, the set tracked users changes as the local user's relationships change.
|
||||
/// Call this API after calling either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event
|
||||
/// in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// Wait for <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event in <see cref="XblSocialManagerDoWork"/>. Prior to this the group will be empty.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerUserGroupGetUsersTrackedByGroup(
|
||||
_In_ XblSocialManagerUserGroupHandle group,
|
||||
|
@ -630,8 +628,7 @@ STDAPI XblSocialManagerDoWork(
|
|||
/// (invalidating the returned handle) if the associated user is removed from Social Manager.</param>
|
||||
/// <returns>HRESULT return code for this API operation.</returns>
|
||||
/// <remarks>
|
||||
/// The result of a user group being loaded will be triggered through
|
||||
/// the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// Wait for <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event in <see cref="XblSocialManagerDoWork"/>. Prior to this the group will be empty.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerCreateSocialUserGroupFromFilters(
|
||||
_In_ XblUserHandle user,
|
||||
|
@ -652,8 +649,7 @@ STDAPI XblSocialManagerCreateSocialUserGroupFromFilters(
|
|||
/// (invalidating the returned handle) if the associated user is removed from Social Manager.</param>
|
||||
/// <returns>HRESULT return code for this API operation.</returns>
|
||||
/// <remarks>
|
||||
/// The result of a user group being loaded will be triggered through
|
||||
/// the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// Wait for <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event in <see cref="XblSocialManagerDoWork"/>. Prior to this the group will be empty.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerCreateSocialUserGroupFromList(
|
||||
_In_ XblUserHandle user,
|
||||
|
@ -671,7 +667,7 @@ STDAPI XblSocialManagerCreateSocialUserGroupFromList(
|
|||
/// This will stop updaing the Xbox Social User Group and remove tracking for any users the XblSocialManagerUserGroup holds.
|
||||
/// Call this API after calling either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event
|
||||
/// The XblSocialManagerUserGroupHandle is returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded event
|
||||
/// in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerDestroySocialUserGroup(
|
||||
|
@ -722,7 +718,7 @@ STDAPI XblSocialManagerGetLocalUsers(
|
|||
/// <see cref="XblSocialManagerEventType"/>::SocialUserGroupUpdated event in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// Call this API after calling either <see cref="XblSocialManagerCreateSocialUserGroupFromFilters"/>
|
||||
/// or <see cref="XblSocialManagerCreateSocialUserGroupFromList"/> to create an XblSocialManagerUserGroup.
|
||||
/// Have the XblSocialManagerUserGroupHandle returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// The XblSocialManagerUserGroupHandle is returned by the <see cref="XblSocialManagerEventType"/>::SocialUserGroupLoaded
|
||||
/// event in <see cref="XblSocialManagerDoWork"/>.
|
||||
/// </remarks>
|
||||
STDAPI XblSocialManagerUpdateSocialUserGroup(
|
||||
|
|
|
@ -501,7 +501,7 @@ private:
|
|||
_In_ AsyncContext<Result<void>> async
|
||||
) noexcept;
|
||||
|
||||
HRESULT SubscribeToRta() noexcept;
|
||||
HRESULT SubscribeToRta(std::unique_lock<std::mutex> lock) noexcept;
|
||||
HRESULT UnsubscribeFromRta() noexcept;
|
||||
|
||||
HRESULT WriteSessionUsingSubpath(
|
||||
|
|
|
@ -1157,7 +1157,7 @@ HRESULT MultiplayerService::SetRtaConnectionId(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT MultiplayerService::SubscribeToRta() noexcept
|
||||
HRESULT MultiplayerService::SubscribeToRta(std::unique_lock<std::mutex> lock) noexcept
|
||||
{
|
||||
if (m_subscription == nullptr)
|
||||
{
|
||||
|
@ -1223,6 +1223,8 @@ HRESULT MultiplayerService::SubscribeToRta() noexcept
|
|||
}
|
||||
});
|
||||
|
||||
// Unlock before adding subscription as it can synchronously call back into our ConnectionIdChanged handler
|
||||
lock.unlock();
|
||||
return m_rtaManager->AddSubscription(m_user, m_subscription);
|
||||
}
|
||||
return S_OK;
|
||||
|
@ -1248,9 +1250,9 @@ HRESULT MultiplayerService::UnsubscribeFromRta() noexcept
|
|||
|
||||
HRESULT MultiplayerService::EnableMultiplayerSubscriptions() noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutexMultiplayerService };
|
||||
std::unique_lock<std::mutex> lock{ m_mutexMultiplayerService };
|
||||
m_forceEnableRtaSubscription = true;
|
||||
return SubscribeToRta();
|
||||
return SubscribeToRta(std::move(lock));
|
||||
}
|
||||
|
||||
HRESULT MultiplayerService::DisableMultiplayerSubscriptions() noexcept
|
||||
|
@ -1281,11 +1283,21 @@ XblFunctionContext MultiplayerService::AddMultiplayerSessionChangedHandler(
|
|||
_In_ MultiplayerSubscription::SessionChangedHandler handler
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutexMultiplayerService };
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutexMultiplayerService };
|
||||
SubscribeToRta(std::move(lock));
|
||||
}
|
||||
|
||||
SubscribeToRta();
|
||||
assert(m_subscription);
|
||||
return m_subscription->AddSessionChangedHandler(std::move(handler));
|
||||
XblFunctionContext token{};
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutexMultiplayerService };
|
||||
if (m_subscription)
|
||||
{
|
||||
token = m_subscription->AddSessionChangedHandler(std::move(handler));
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
void MultiplayerService::RemoveMultiplayerSessionChangedHandler(
|
||||
|
|
|
@ -235,7 +235,7 @@ private:
|
|||
Map<uint32_t, size_t> m_trackedTitles;
|
||||
uint32_t const m_titleId;
|
||||
|
||||
mutable std::mutex m_mutex;
|
||||
mutable std::recursive_mutex m_mutex;
|
||||
|
||||
friend class DevicePresenceChangeSubscription;
|
||||
friend class TitlePresenceChangeSubscription;
|
||||
|
|
|
@ -54,7 +54,10 @@ XblFunctionContext PresenceService::AddTitlePresenceChangedHandler(
|
|||
TitlePresenceChangedHandler handler
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
m_titlePresenceChangedHandlers[m_nextHandlerToken] = std::move(handler);
|
||||
auto token = m_nextHandlerToken++;
|
||||
|
||||
// Add subs to RTA manager if needed
|
||||
if (m_titlePresenceChangedHandlers.empty())
|
||||
|
@ -70,15 +73,14 @@ XblFunctionContext PresenceService::AddTitlePresenceChangedHandler(
|
|||
}
|
||||
}
|
||||
|
||||
m_titlePresenceChangedHandlers[m_nextHandlerToken] = std::move(handler);
|
||||
return m_nextHandlerToken++;
|
||||
return token;
|
||||
}
|
||||
|
||||
void PresenceService::RemoveTitlePresenceChangedHandler(
|
||||
_In_ XblFunctionContext context
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
auto removed{ m_titlePresenceChangedHandlers.erase(context) };
|
||||
if (removed && m_titlePresenceChangedHandlers.empty())
|
||||
|
@ -98,7 +100,7 @@ XblFunctionContext PresenceService::AddDevicePresenceChangedHandler(
|
|||
DevicePresenceChangedHandler handler
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
// Add subs to RTA manager if needed
|
||||
if (m_devicePresenceChangedHandlers.empty())
|
||||
|
@ -118,7 +120,7 @@ void PresenceService::RemoveDevicePresenceChangedHandler(
|
|||
_In_ XblFunctionContext context
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
auto removed{ m_devicePresenceChangedHandlers.erase(context) };
|
||||
if (removed && m_devicePresenceChangedHandlers.empty())
|
||||
|
@ -135,7 +137,7 @@ HRESULT PresenceService::TrackUsers(
|
|||
const Vector<uint64_t>& xuids
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
if (!m_resyncHandlerToken)
|
||||
{
|
||||
|
@ -188,7 +190,7 @@ HRESULT PresenceService::StopTrackingUsers(
|
|||
const Vector<uint64_t>& xuids
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
for (auto& xuid : xuids)
|
||||
{
|
||||
|
@ -217,7 +219,7 @@ HRESULT PresenceService::TrackAdditionalTitles(
|
|||
const Vector<uint32_t>& titleIds
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
for (auto& titleId : titleIds)
|
||||
{
|
||||
|
@ -251,7 +253,7 @@ HRESULT PresenceService::StopTrackingAdditionalTitles(
|
|||
const Vector<uint32_t>& titleIds
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
List<uint32_t> removedTitles{};
|
||||
for (auto& titleId : titleIds)
|
||||
|
@ -415,7 +417,7 @@ void PresenceService::HandleDevicePresenceChanged(
|
|||
_In_ bool isUserLoggedOnDevice
|
||||
) const noexcept
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
auto handlers{ m_devicePresenceChangedHandlers };
|
||||
lock.unlock();
|
||||
|
||||
|
@ -431,7 +433,7 @@ void PresenceService::HandleTitlePresenceChanged(
|
|||
_In_ XblPresenceTitleState state
|
||||
) const noexcept
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
auto handlers{ m_titlePresenceChangedHandlers };
|
||||
lock.unlock();
|
||||
|
||||
|
@ -443,7 +445,7 @@ void PresenceService::HandleTitlePresenceChanged(
|
|||
|
||||
void PresenceService::HandleRTAResync()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
LOGS_DEBUG << "Resyncing " << m_trackedXuids.size() << " Presence Subscriptions";
|
||||
|
||||
|
@ -456,7 +458,7 @@ void PresenceService::HandleRTAResync()
|
|||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
if(Succeeded(result))
|
||||
{
|
||||
|
|
|
@ -48,6 +48,9 @@ struct ServiceSubscription
|
|||
Set<std::shared_ptr<Subscription>> clientSubscriptions;
|
||||
List<AsyncContext<Result<void>>> subscribeAsyncContexts;
|
||||
List<AsyncContext<Result<void>>> unsubscribeAsyncContexts;
|
||||
|
||||
// OnSubscribe data payload
|
||||
JsonDocument onSubscribeData{ rapidjson::kNullType };
|
||||
};
|
||||
|
||||
// RTA message types and error codes define by service here http://xboxwiki/wiki/Real_Time_Activity
|
||||
|
@ -229,6 +232,8 @@ HRESULT Connection::AddSubscription(
|
|||
{
|
||||
// Subscription is already active, trivially complete
|
||||
lock.unlock();
|
||||
// Pass along original OnSubscribe payload for this subscription
|
||||
sub->OnSubscribe(serviceSub->onSubscribeData);
|
||||
async.Complete(S_OK);
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -431,7 +436,7 @@ void Connection::SubscribeResponseHandler(_In_ const JsonValue& message) noexcep
|
|||
case ErrorCode::Success:
|
||||
{
|
||||
serviceSub->serviceId = message[3].GetInt();
|
||||
const auto& data = message[4];
|
||||
serviceSub->onSubscribeData.CopyFrom(message[4], serviceSub->onSubscribeData.GetAllocator());
|
||||
|
||||
m_subsByServiceId[serviceSub->serviceId] = serviceSub;
|
||||
List<AsyncContext<Result<void>>> subscribeAsyncContexts{ std::move(serviceSub->subscribeAsyncContexts) };
|
||||
|
@ -470,7 +475,7 @@ void Connection::SubscribeResponseHandler(_In_ const JsonValue& message) noexcep
|
|||
}
|
||||
for (auto& clientSub : clientSubs)
|
||||
{
|
||||
clientSub->OnSubscribe(data);
|
||||
clientSub->OnSubscribe(serviceSub->onSubscribeData);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -144,12 +144,15 @@ try
|
|||
auto group{ socialManager.GetUserGroup(groupHandle) };
|
||||
if (!group)
|
||||
{
|
||||
*users = nullptr;
|
||||
*usersCount = 0;
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
*users = group->Users().data();
|
||||
*usersCount = group->Users().size();
|
||||
auto& groupUsers = group->Users();
|
||||
*users = groupUsers.data();
|
||||
*usersCount = groupUsers.size();
|
||||
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
@ -170,12 +173,15 @@ try
|
|||
auto group{ socialManager.GetUserGroup(groupHandle) };
|
||||
if (!group)
|
||||
{
|
||||
*trackedUsers = nullptr;
|
||||
*trackedUsersCount = 0;
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
*trackedUsers = group->TrackedUsers().data();
|
||||
*trackedUsersCount = group->TrackedUsers().size();
|
||||
const auto& groupTrackedUsers = group->TrackedUsers();
|
||||
*trackedUsers = groupTrackedUsers.data();
|
||||
*trackedUsersCount = groupTrackedUsers.size();
|
||||
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -203,10 +203,13 @@ const Vector<const XblSocialManagerUser*>& XblSocialManagerUserGroup::Users() no
|
|||
PERF_START();
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
m_usersView.clear();
|
||||
std::transform(m_users.begin(), m_users.end(), std::back_inserter(m_usersView), [](const auto& pair)
|
||||
if (m_loaded)
|
||||
{
|
||||
return pair.second;
|
||||
});
|
||||
std::transform(m_users.begin(), m_users.end(), std::back_inserter(m_usersView), [](const auto& pair)
|
||||
{
|
||||
return pair.second;
|
||||
});
|
||||
}
|
||||
PERF_STOP();
|
||||
return m_usersView;
|
||||
}
|
||||
|
@ -215,22 +218,29 @@ const Vector<uint64_t>& XblSocialManagerUserGroup::TrackedUsers() noexcept
|
|||
{
|
||||
PERF_START();
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
switch (type)
|
||||
if (m_loaded)
|
||||
{
|
||||
case XblSocialUserGroupType::FilterType:
|
||||
switch (type)
|
||||
{
|
||||
case XblSocialUserGroupType::FilterType:
|
||||
{
|
||||
m_trackedUsersView.clear();
|
||||
std::transform(m_users.begin(), m_users.end(), std::back_inserter(m_trackedUsersView), [](const auto& pair)
|
||||
{
|
||||
return pair.first;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case XblSocialUserGroupType::UserListType:
|
||||
{
|
||||
// Tracked users view is static
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackedUsersView.clear();
|
||||
std::transform(m_users.begin(), m_users.end(), std::back_inserter(m_trackedUsersView), [](const auto& pair)
|
||||
{
|
||||
return pair.first;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case XblSocialUserGroupType::UserListType:
|
||||
{
|
||||
// Tracked users view is static
|
||||
break;
|
||||
}
|
||||
}
|
||||
PERF_STOP();
|
||||
return m_trackedUsersView;
|
||||
|
|
|
@ -257,7 +257,7 @@ private:
|
|||
// Tracked stats by scid. Needed to perform RTA resync
|
||||
Map<String, Vector<String>> m_trackedStatsByScid;
|
||||
|
||||
mutable std::mutex m_mutex;
|
||||
mutable std::recursive_mutex m_mutex;
|
||||
|
||||
friend class StatisticChangeSubscription;
|
||||
};
|
||||
|
|
|
@ -216,7 +216,7 @@ XblFunctionContext UserStatisticsService::AddStatisticChangedHandler(
|
|||
StatisticChangeHandler handler
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
if (!m_resyncHandlerToken)
|
||||
{
|
||||
|
@ -251,7 +251,7 @@ void UserStatisticsService::RemoveStatisticChangedHandler(
|
|||
XblFunctionContext token
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
auto removed{ m_statisticChangeHandlers.erase(token) };
|
||||
|
||||
|
@ -275,7 +275,7 @@ HRESULT UserStatisticsService::TrackStatistics(
|
|||
_In_ const Vector<String>& statNames
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
for (auto& xuid : xuids)
|
||||
{
|
||||
|
@ -310,7 +310,7 @@ HRESULT UserStatisticsService::StopTrackingStatistics(
|
|||
_In_ const Vector<String>& statNames
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
for (auto& xuid : xuids)
|
||||
{
|
||||
|
@ -336,7 +336,7 @@ HRESULT UserStatisticsService::StopTrackingUsers(
|
|||
_In_ const Vector<uint64_t>& xuids
|
||||
) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{ m_mutex };
|
||||
std::lock_guard<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
for (auto& xuid : xuids)
|
||||
{
|
||||
|
@ -361,7 +361,7 @@ void UserStatisticsService::HandleStatisticChanged(
|
|||
const StatisticChangeEventArgs& args
|
||||
) const noexcept
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
auto handlers{ m_statisticChangeHandlers };
|
||||
lock.unlock();
|
||||
|
||||
|
@ -373,7 +373,7 @@ void UserStatisticsService::HandleStatisticChanged(
|
|||
|
||||
void UserStatisticsService::HandleRTAResync()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
// Get all stats tracked stats for all tracked users so that we can resync in a single request.
|
||||
// In the request callback, we will only invoke the stat changed handlers for the tracked users/stats
|
||||
|
@ -398,7 +398,7 @@ void UserStatisticsService::HandleRTAResync()
|
|||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock{ m_mutex };
|
||||
std::unique_lock<std::recursive_mutex> lock{ m_mutex };
|
||||
|
||||
if (Succeeded(result))
|
||||
{
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#define XBOX_SERVICES_API_VERSION_STRING "2022.10.20220915.0"
|
||||
#define XBOX_SERVICES_API_VERSION_STRING "2022.10.20221025.1"
|
||||
|
|
|
@ -353,6 +353,9 @@
|
|||
<None Include="$(MSBuildThisFileDirectory)Tests\mp\MP_JoinLobbyViaActivity.lua">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Tests\mp\mp_multiple_contexts.lua">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Tests\mp\mp_partial_invite_flow.lua">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
|
|
|
@ -822,5 +822,8 @@
|
|||
<None Include="$(MSBuildThisFileDirectory)Tests\notification\multiple_notification_subscriptions.lua">
|
||||
<Filter>Tests\notification</Filter>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Tests\mp\mp_multiple_contexts.lua">
|
||||
<Filter>Tests\mp</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -154,10 +154,24 @@ int XblGetErrorCondition_Lua(lua_State *L)
|
|||
int XblContextCreateHandle_Lua(lua_State *L)
|
||||
{
|
||||
// CODE SNIPPET START: XblContextCreateHandle
|
||||
HRESULT hr = XblContextCreateHandle(Data()->xalUser, &Data()->xboxLiveContext);
|
||||
XblContextHandle contextHandle{ nullptr };
|
||||
HRESULT hr = XblContextCreateHandle(Data()->xalUser, &contextHandle);
|
||||
// CODE SNIPPET END
|
||||
|
||||
// Cache the created handle for use in other APIs if we don't have one already
|
||||
if (Data()->xboxLiveContext == nullptr)
|
||||
{
|
||||
Data()->xboxLiveContext = contextHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogToFile("XblContextCreateHandle called but an existing handle was cached");
|
||||
}
|
||||
|
||||
lua_pushinteger(L, (int64_t)contextHandle);
|
||||
|
||||
LogToFile("XblContextCreateHandle: %s", ConvertHR(hr).c_str());
|
||||
return LuaReturnHR(L, hr);
|
||||
return LuaReturnHR(L, hr, 1);
|
||||
}
|
||||
|
||||
int XblContextDuplicateHandle_Lua(lua_State *L)
|
||||
|
@ -185,14 +199,21 @@ int XblContextCloseHandle_Lua(lua_State *L)
|
|||
StopSocialManagerDoWorkHelperCpp();
|
||||
#endif
|
||||
|
||||
// CODE SNIPPET START: XblContextCreateHandle
|
||||
if (Data()->xboxLiveContext)
|
||||
// Get the XblContextHandle
|
||||
XblContextHandle handleToClose = (XblContextHandle)GetUint64FromLua(L, 1, (uint64_t)Data()->xboxLiveContext);
|
||||
|
||||
// CODE SNIPPET START: XblContextCloseHandle
|
||||
if (handleToClose != nullptr)
|
||||
{
|
||||
XblContextCloseHandle(Data()->xboxLiveContext);
|
||||
Data()->xboxLiveContext = nullptr;
|
||||
XblContextCloseHandle(handleToClose);
|
||||
}
|
||||
// CODE SNIPPET END
|
||||
|
||||
if (handleToClose == Data()->xboxLiveContext)
|
||||
{
|
||||
Data()->xboxLiveContext = nullptr;
|
||||
}
|
||||
|
||||
LogToFile("OnXblContextCloseHandle called.");
|
||||
return LuaReturnHR(L, S_OK);
|
||||
}
|
||||
|
|
|
@ -136,12 +136,14 @@ int XblMultiplayerWriteSessionAsync_Lua(lua_State *L)
|
|||
{
|
||||
// Params:
|
||||
// 1) Session handle id returned when the session was created
|
||||
// 2) write mode (as string)
|
||||
// 2) XblContextHandle to use. Defaults to Data()->xboxLiveContextse
|
||||
|
||||
CreateQueueIfNeeded();
|
||||
auto sessionIndex{ GetUint64FromLua(L, 1, 0) };
|
||||
assert(MPState()->sessionHandles.size() > sessionIndex);
|
||||
|
||||
XblContextHandle xboxLiveContext = (XblContextHandle)GetUint64FromLua(L, 2, (uint64_t)Data()->xboxLiveContext);
|
||||
|
||||
ENSURE_IS_TRUE(MPState()->sessionHandles[static_cast<uint32_t>(sessionIndex)] != nullptr, "No valid multiplayer session.");
|
||||
|
||||
XblMultiplayerSessionWriteMode writeMode = ConvertStringToXblMultiplayerSessionWriteMode(GetStringFromLua(L, 2, "XblMultiplayerSessionWriteMode::UpdateOrCreateNew").c_str());
|
||||
|
@ -180,7 +182,7 @@ int XblMultiplayerWriteSessionAsync_Lua(lua_State *L)
|
|||
CallLuaFunctionWithHr(hr, "OnXblMultiplayerWriteSessionAsync"); // CODE SNIP SKIP
|
||||
};
|
||||
|
||||
auto hr = XblMultiplayerWriteSessionAsync(Data()->xboxLiveContext, MPState()->sessionHandles[static_cast<uint32_t>(sessionIndex)], writeMode, asyncBlock.get());
|
||||
auto hr = XblMultiplayerWriteSessionAsync(xboxLiveContext, MPState()->sessionHandles[static_cast<uint32_t>(sessionIndex)], writeMode, asyncBlock.get());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* since the callback will take over ownership.
|
||||
|
@ -1940,9 +1942,12 @@ int XblMultiplayerGetActivitiesWithPropertiesForUsersAsync_Lua(lua_State *L)
|
|||
|
||||
int XblMultiplayerSetSubscriptionsEnabled_Lua(lua_State *L)
|
||||
{
|
||||
|
||||
bool enabled = GetBoolFromLua(L, 1, true);
|
||||
XblContextHandle xboxLiveContext = (XblContextHandle)GetUint64FromLua(L, 2, (uint64_t)Data()->xboxLiveContext);
|
||||
|
||||
// CODE SNIPPET START: XblMultiplayerSetSubscriptionsEnabled
|
||||
HRESULT hr = XblMultiplayerSetSubscriptionsEnabled(Data()->xboxLiveContext, enabled);
|
||||
HRESULT hr = XblMultiplayerSetSubscriptionsEnabled(xboxLiveContext, enabled);
|
||||
// CODE SNIPPET END
|
||||
|
||||
LogToFile("XblMultiplayerSetSubscriptionsEnabled: hr=%s", ConvertHR(hr).c_str());
|
||||
|
|
|
@ -20,9 +20,12 @@ end
|
|||
|
||||
function common.OnXalTryAddFirstUserSilentlyAsync()
|
||||
local hr = GetLastError()
|
||||
local handle = 0
|
||||
if hr == 0 then
|
||||
print("SignInSilently Succeeded. Creating XblContext")
|
||||
hr = XblContextCreateHandle()
|
||||
handle, hr = XblContextCreateHandle()
|
||||
print("hr " .. hr)
|
||||
print("handle " .. handle)
|
||||
if hr == 0 then
|
||||
XalUserGetGamertag()
|
||||
XalUserGetId()
|
||||
|
|
|
@ -14,9 +14,9 @@ function TestMP_Handler()
|
|||
XblMultiplayerSessionDuplicateHandle()
|
||||
XblMultiplayerSessionCloseHandle()
|
||||
|
||||
XblRealTimeActivityActivate()
|
||||
--XblRealTimeActivityActivate()
|
||||
XblMultiplayerSubscriptionsEnabled()
|
||||
XblMultiplayerSetSubscriptionsEnabled()
|
||||
--XblMultiplayerSetSubscriptionsEnabled()
|
||||
XblMultiplayerSubscriptionsEnabled()
|
||||
|
||||
XblMultiplayerSessionCreateHandle()
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
local xblContext = 0
|
||||
|
||||
function TestFunc()
|
||||
XblMultiplayerSetSubscriptionsEnabled(1)
|
||||
XblMultiplayerSessionReferenceCreate()
|
||||
XblMultiplayerSessionCreateHandle()
|
||||
XblMultiplayerSessionJoin()
|
||||
XblMultiplayerWriteSessionAsync()
|
||||
end
|
||||
|
||||
local writeCount = 0;
|
||||
|
||||
function OnXblMultiplayerWriteSessionAsync()
|
||||
writeCount = writeCount + 1
|
||||
if writeCount == 1 then
|
||||
print("OnXblMultiplayerWriteSessionAsync 1")
|
||||
-- first write made using default XblContext should complete successfully
|
||||
-- change the session and attempt to write with second XblContext
|
||||
xblContext = XblContextCreateHandle()
|
||||
XblMultiplayerSetSubscriptionsEnabled(1, xblContext)
|
||||
XblMultiplayerSessionCurrentUserSetStatus()
|
||||
XblMultiplayerWriteSessionAsync(0, xblContext)
|
||||
elseif writeCount == 2 then
|
||||
print("OnXblMultiplayerWriteSessionAsync 2")
|
||||
XblMultiplayerSessionCloseHandle()
|
||||
XblContextCloseHandle(xblContext)
|
||||
test.stopTest();
|
||||
end
|
||||
end
|
||||
|
||||
test.TestMPMultipleContexts = function()
|
||||
common.init(TestFunc)
|
||||
end
|
|
@ -14,6 +14,7 @@ function OnXblSocialManagerDoWork_LocalUserAddedEvent()
|
|||
XblSocialManagerGetLocalUsers()
|
||||
XblSocialManagerSetRichPresencePollingStatus()
|
||||
group, hr = XblSocialManagerCreateSocialUserGroupFromFilters()
|
||||
XblSocialManagerUserGroupGetUsers()
|
||||
print("group " .. group)
|
||||
end
|
||||
|
||||
|
|
|
@ -455,6 +455,15 @@
|
|||
<CopyFileToFolders>
|
||||
<DestinationFolders>$(OutDir)Assets</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Xbox.XboxOne.x64'">xcopy /Y /I /E "$(ProjectDir)Assets\*.*" "$(TargetDir)Assets" & xcopy /Y /I /E "$(ProjectDir)Media\*.*" "$(TargetDir)Media" & xcopy /Y /I /E "$(ProjectDir)Media\Fonts\*.*" "$(TargetDir)" & xcopy /Y /I /E "$(ProjectDir)Media\Textures\*.*" "$(TargetDir)"</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Profile|Gaming.Xbox.XboxOne.x64'">xcopy /Y /I /E "$(ProjectDir)Assets\*.*" "$(TargetDir)Assets" & xcopy /Y /I /E "$(ProjectDir)Media\*.*" "$(TargetDir)Media" & xcopy /Y /I /E "$(ProjectDir)Media\Fonts\*.*" "$(TargetDir)" & xcopy /Y /I /E "$(ProjectDir)Media\Textures\*.*" "$(TargetDir)"</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.XboxOne.x64'">xcopy /Y /I /E "$(ProjectDir)Assets\*.*" "$(TargetDir)Assets" & xcopy /Y /I /E "$(ProjectDir)Media\*.*" "$(TargetDir)Media" & xcopy /Y /I /E "$(ProjectDir)Media\Fonts\*.*" "$(TargetDir)" & xcopy /Y /I /E "$(ProjectDir)Media\Textures\*.*" "$(TargetDir)"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\APIRunner.GDK\Kits\ATGTK\ControllerFont.h" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче