Übersicht über die Xbox Live-Hilfsbibliothek
Die Xbox Live-Hilfsbibliothek für playFab Party ist so konzipiert, dass Spiele, die PlayFab Party verwenden, die Xbox Live-Richtlinien im Zusammenhang mit der Kommunikation (XR-015 und XR-045) erfüllen. Die Xbox Live-Hilfsbibliothek ist auf Nuget.org verfügbar.
Kompatibilität mit der PlayFab Party-Bibliothek
Während wir versuchen, Breaking Changes in unseren APIs zu minimieren, können einige Änderungen an der PlayFab-Party-API dazu führen, dass die Xbox Live Helper-Bibliothek fehlerhafte Werte zurückgibt. In der folgenden Tabelle können Sie sicherstellen, dass die Version Ihrer Bibliotheken kompatibel ist.
Xbox Live-Hilfsbibliothek Version |
PlayFab Party-Version 1.0.1 |
PlayFab Party-Version 1.3.0+ |
---|---|---|
1.0.1 | ✔ | |
1.1.0 | ✔ | |
1.2.0 | ✔ | |
1.2.5 | ✔ |
Nachverfolgen von Xbox Live-Benutzern
Die Xbox Live Helper-Bibliothek der PlayFab-Party muss explizit über die Xbox Live-Benutzer informiert werden, die derzeit an der Partysitzung teilnehmen. Es wird empfohlen, dass Titel die Bibliothek informieren, indem sie auf Änderungen an ihrem Multiplayer-Sitzungsdokument lauschen und diese Liste in der Xbox Live-Hilfsbibliothek über PartyXblManager::CreateLocalChatUser
und PartyXblManager::CreateRemoteChatUser
widerspiegeln.
Für lokale Benutzer:
void
OnLocalXboxUserAddedToMPSD(
uint64_t xboxUserId
)
{
PartyXblLocalChatUser* localChatUser;
PartyError err = PartyXblManager::GetSingleton().CreateLocalChatUser(xboxUserId, nullptr, &localChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateLocalChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
}
Wenn an diesem Punkt bereits ein PartyLocalChatControl für den entsprechenden lokalen Xbox-Benutzer vorhanden ist, können Sie es diesem PartyXblLocalChatUser über die SetCustomContext-Methoden zuordnen.
localChatControl->SetCustomContext(localChatUser);
localChatUser->SetCustomContext(localChatControl);
Andernfalls können Sie diesen neuen PartyXblLocalChatUser verwenden, um das Chat-Steuerelement zu generieren und es dann zuzuordnen. Weitere Informationen finden Sie unter Erstellen von PartyLocalChatControls aus PartyXblLocalChatUsers .
Für Remotebenutzer:
void
OnRemoteXboxUserAddedToMPSD(
uint64_t xboxUserId
)
{
PartyXblChatUser* remoteChatUser;
PartyError err = PartyXblManager::GetSingleton().CreateRemoteChatUser(remoteXboxUserId, &remoteChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateRemoteChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
Wenn an diesem Punkt bereits ein PartyChatControl für den entsprechenden Xbox-Remotebenutzer vorhanden ist, können Sie es diesem PartyXblChatUser über die SetCustomContext-Methoden zuordnen.
remoteChatControl->SetCustomContext(remoteChatUser);
remoteChatUser->SetCustomContext(remoteChatControl);
Beachten Sie, dass Aktualisierungen des Sitzungsdokuments und Aktualisierungen der Liste der Remotechatsteuerungen möglicherweise nicht sortiert werden und Sie möglicherweise eine ähnliche Zuordnungslogik benötigen, wenn Sie Updates für Remotechatsteuerungen verarbeiten PartyChatControlCreatedStateChange
.
Für lokale und Remotechatbenutzer ist es wichtig zu beachten, dass die Kern-Partybibliothek Benutzer und Chatsteuerelemente über PlayFab-Entitäts-IDs identifiziert, wobei die Xbox Live-Hilfsbibliothek Chatbenutzer mit Xbox-Benutzer-IDs identifiziert. Daher ist häufig eine Übersetzung zwischen den beiden notwendig. Weitere Informationen finden Sie unter Zuordnung zwischen Xbox Live-Benutzer-IDs und PlayFab-Entitäts-IDs .
Erstellen von PartyLocalChatControls aus PartyXblLocalChatUsers
PartyXblLocalChatUser
-Objekte sind häufig nur nützlich, wenn sie -Objekten und PartyLocalChatControl
-Objekten in der Parteibibliothek zugeordnet PartyLocalUser
sind. Zum Generieren von PartyLocalUser
- und PartyLocalChatControl
-Objekten sind Titel erforderlich, um ihre Benutzer bei PlayFab anzumelden und ihre Benutzer entityId
und titlePlayerEntityToken
abzurufen. Die Anmeldung kann über das PlayFab CPP SDK erfolgen, aber wenn ein Titel xbox Live-Anmeldeinformationen für die Anmeldung bei PlayFab verwenden möchte, kann er verwenden PartyXblManager::LoginToPlayFab
, um zu vermeiden, dass eine zusätzliche Abhängigkeit abgerufen wird.
Das folgende Beispiel zeigt, wie die Xbox Live Helper-Bibliothek Ihnen beim Erstellen PartyLocalUser
von Objekten und PartyLocalChatControl
von PartyXblLocalChatUser
Objekten helfen kann. Weitere Informationen zum Erstellen von PartyXblLocalChatUser
Objekten finden Sie unter Nachverfolgen von Xbox Live-Benutzern.
err = PartyXblManager::GetSingleton().LoginToPlayFab(localChatUser, nullptr);
if (PARTY_FAILED(err))
{
DEBUGLOG("LoginToPlayFab failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
Kurz nach dem Aufruf PartyXblManager::LoginToPlayFab
erhalten Sie eine PartyXblLoginToPlayFabCompletedStateChange
mit dem Ergebnis des Anmeldevorgangs.
PartyLocalUser* partyLocalUser;
if (stateChange->stateChangeType == PartyXblStateChangeType::LoginToPlayFabCompleted)
{
auto loginToPlayFabCompleted = static_cast<PartyXblLoginToPlayFabCompletedStateChange*>(stateChange);
if (loginToPlayFabCompleted->result == PartyXblStateChangeResult::Succeeded)
{
err = PartyManager::GetSingleton().CreateLocalUser(
loginToPlayFabCompleted->entityId,
loginToPlayFabCompleted->titlePlayerEntityToken,
partyLocalUser));
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateLocalUser failed: %s\n", PartyManager::GetErrorMessage(err));
return;
}
}
}
PartyLocalDevice* localDevice;
err = PartyManager::GetSingleton().GetLocalDevice(&localDevice);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetLocalDevice failed: %s\n", PartyManager::GetErrorMessage(err));
return;
}
PartyLocalChatControl* localChatControl;
err = localDevice->CreateChatControl(partyLocalUser, nullptr, nullptr, &localChatControl);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateChatControl failed: %s\n", PartyManager::GetErrorMessage(err));
return;
}
// We can use the custom context on the PartyXblLocalChatUser to store the PartyLocalChatControl for easy access
// in the future.
localChatUser->SetCustomContext(localChatControl);
Berücksichtigen der Barrierefreiheitseinstellungen eines Xbox Live-Benutzers
Das PartyXblLocalChatUser
-Objekt macht einige der Barrierefreiheitseinstellungen des Xbox Live-Benutzers verfügbar, die für Partychatsitzungen relevant sind. Titel können diese Informationen verwenden, um ihren Spielern eine bessere Erfahrung zu bieten, indem sie einige der Barrierefreiheitsfunktionen der Partei sofort aktivieren.
PartyXblAccessibilitySettings accessibilitySettings;
err = localChatUser->GetAccessibilitySettings(&accessibilitySettings);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetAccessibilitySettings failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
if (accessibilitySettings.speechToTextEnabled)
{
PartyVoiceChatTranscriptionOptions option = PartyVoiceChatTranscriptionOptions::TranscribeOtherChatControlsWithMatchingLanguages;
m_localChatControl->SetTranscriptionOptions(option, nullptr);
}
Respektieren der Datenschutzeinstellungen und -berechtigungen eines Xbox Live-Benutzers
Gemäß Xbox Live-Richtlinien dürfen Titel keine Kommunikation über Xbox Live zulassen, wenn der Datenschutz oder die Berechtigungen des Benutzers dies nicht zulassen. Die Xbox Live-Hilfsbibliothek hilft Ihnen dabei, dies zu erreichen, indem Sie die restriktivsten PartyChatPermissionOptions
Abfragen zwischen zwei Benutzern ermöglichen, die von Xbox Live-Richtlinien zugelassen werden. Jedes Mal, wenn sich dieser Wert ändert, wird von PartyXblRequiredChatPermissionInfoChangedStateChange
der Bibliothek generiert. Die aktualisierte PartyChatPermissionOptions
kann durch einen Aufruf PartyXblLocalChatUser::GetRequiredChatPermissionInfo()
von abgerufen werden.
PartyXblChatUser* remoteChatUser;
PartyError err = PartyXblManager::GetSingleton().CreateRemoteChatUser(remoteXboxUserId, &remoteChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateRemoteChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
// Once the chat control representing this remote Xbox Live user joins a network, we can use the custom context
// on the PartyXblChatUser to store the chat control object for quick access in the future.
remoteChatUser->SetCustomContext(m_remotePartyChatControl);
Die Xbox Live-Hilfsbibliothek verfolgt die Datenschutz- und Berechtigungseinstellungen für jeden Remotechatbenutzer in Bezug auf jeden lokalen Chatbenutzer durch Kommunikation mit Xbox Live-Datenschutzdiensten nach. Darüber hinaus lauscht die Bibliothek auf Änderungen an diesen Einstellungen, indem sie Aktualisierungen der Echtzeitaktivität abonniert. Wenn neue Remotechatbenutzer hinzugefügt werden oder sich die Beziehung zwischen einem lokalen Chatbenutzer und einem vorhandenen Remotechatbenutzer ändert, wird eine PartyXblRequiredChatPermissionInfoChangedStateChange
generiert, um Sie zu benachrichtigen, dass jetzt ein aktualisierter PartyChatPermissionOptions
Wert verfügbar ist.
// Wait for PartyXblRequiredChatPermissionInfoChangedStateChange
if (stateChange->stateChangeType == PartyXblStateChangeType::RequiredChatPermissionInfoChanged)
{
auto chatPermissionChanged = static_cast<PartyXblRequiredChatPermissionInfoChangedStateChange*>(stateChange);
PartyXblLocalChatUser* localChatUser = chatPermissionChanged->localChatUser;
PartyXblChatUser* targetChatUser = chatPermissionChanged->targetChatUser;
PartyXblChatPermissionInfo chatPermissionInfo;
PartyError err = localChatUser->GetRequiredChatPermissionInfo(targetChatUser, &chatPermissionInfo);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetRequiredChatPermissionInfo failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
PartyLocalChatControl* localChatControl;
localChatUser->GetCustomContext(reinterpret_cast<void**>(&localChatControl));
if (PARTY_FAILED(err))
{
DEBUGLOG("GetCustomContext failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
PartyChatControl* targetChatControl;
targetChatUser->GetCustomContext(reinterpret_cast<void**>(&targetChatControl));
if (PARTY_FAILED(err))
{
DEBUGLOG("GetCustomContext failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
localChatControl->SetPermission(targetChatControl, chatPermissionInfo.chatPermissionMask);
if (PARTY_FAILED(err))
{
DEBUGLOG("SetPermission failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
}
Die PartyXblChatPermissionInfo
-Struktur enthält zwei Informationen:
- Eine
PartyChatPermissionOptions
Maske, die entweder unverändert an übergeben werden kann oder die als binäre Maske verwendet werden kann, wenn Sie bereits über einenPartyChatPermissionOptions
Wert verfügen, den Sie verwenden möchten, aber sicherstellen möchten, dass Sie xbox Live-RichtlinienPartyLocalChatControl::SetPermission()
einhalten. - Ein
PartyXblChatPermissionMaskReason
-Wert, der zusätzliche Informationen zum Wert von bereitstellt.PartyXblChatPermissionInfo::chatPermissionMask
PartyXblChatPermissionMaskReason | Erläuterung |
---|---|
NoRestriction | Für diese Chatberechtigung gilt derzeit keine Einschränkung. |
Bestimmung | Die Kommunikation ist eingeschränkt, während die Kommunikationsberechtigung und die Datenschutzeinstellungen des lokalen Benutzers festgelegt werden. |
Privileg | Die Kommunikation ist aufgrund der Kommunikationsberechtigung des lokalen Benutzers eingeschränkt. |
Datenschutz | Die Kommunikation ist aufgrund der Datenschutzeinstellungen des lokalen Benutzers in Bezug auf den Zielchatbenutzer eingeschränkt. |
InvalidTargetUser | Die Kommunikation ist eingeschränkt, da der Zielbenutzer von Xbox Live-Diensten nicht als gültig erkannt wurde. |
XboxLiveServiceError | Die erforderliche Chatberechtigung konnte aufgrund von Problemen mit Xbox Live-Diensten nicht erfolgreich ermittelt werden. |
UnknownError | Die erforderliche Chatberechtigung konnte aufgrund eines unbekannten internen Fehlers nicht erfolgreich ermittelt werden. |
Berücksichtigen von Berechtigungen für die netzwerkübergreifende Kommunikation
Titel, die netzwerkübergreifende Wiedergabe und Kommunikation zwischen Xbox Live und Nicht-Xbox Live-Spielern unterstützen, müssen die Kommunikationsberechtigungen überprüfen, bevor sie die Kommunikation zwischen diesen Spielern zulassen. Die Xbox Live-Hilfsbibliothek stellt diese Informationen über PartyXblLocalChatUser::GetCrossNetworkCommunicationPrivacySetting()
bereit. Diese Methode gibt eine PartyXblCrossNetworkCommunicationPrivacySetting
Enumeration mit drei möglichen Werten zurück:
PartyXblCrossNetworkCommunicationPrivacySetting | Erläuterung |
---|---|
Erlaubt | Die Berechtigungen dieses Xbox Live-Benutzers sind so festgelegt, dass die Kommunikation mit allen netzwerkübergreifenden Spielern möglich ist. |
FriendsOnly | Die Berechtigungen dieses Xbox Live-Benutzers sind so festgelegt, dass nur die Kommunikation mit einem netzwerkübergreifenden Freund zulässig ist. |
Unzulässige | Die Berechtigungen dieses Xbox Live-Benutzers erlauben keine Kommunikation mit netzwerkübergreifenden Spielern. |
PartyXblCrossNetworkCommunicationPrivacySetting crossNetworkSetting;
localChatUser->GetCrossNetworkCommunicationPrivacySetting(&crossNetworkSetting);
if (crossNetworkSetting == PartyXblCrossNetworkCommunicationPrivacySetting::Disallowed)
{
m_localChatControl->SetPermissions(crossNetworkChatControl, PartyChatPermissionOptions::None);
}
Weitere Informationen zu XR-015 und zur netzwerkübergreifenden Kommunikation finden Sie hier.
Zuordnung zwischen Xbox Live-Benutzer-IDs und PlayFab-Entitäts-IDs
Viele Xbox Live-Titel, die PlayFab Party verwenden, müssen zwischen Xbox Live-Benutzer-IDs (die im gesamten Xbox Live-Ökosystem verwendet werden) und PlayFab-Entitäts-IDs (von PlayFab Party verwendet) übersetzt werden. Mit PartyXblManager::GetEntityIdsFromXboxLiveUserIds
können Titel eine Liste der PlayFab-Entitäts-IDs abrufen, die einer bestimmten Liste von Xbox Live-Benutzer-IDs entsprechen. Es wird erwartet, dass Titel bereits über eine Liste von Xbox Live-Benutzer-IDs verfügen, indem ein externer Listendienst wie das Multiplayer-Sitzungsverzeichnis verwendet wird. Durch Zuordnen der Xbox Live-Benutzer-IDs aus der Liste zu ihren PlayFab-Entitäts-IDs können wir eine Zuordnung aller PlayFab-Entitäts-IDs erstellen, die der Liste Ihrer Spielsitzung entsprechen. Diese Zuordnung kann dann verwendet werden, um - und PartyChatControl
-Objekte den entsprechenden Xbox Live-Benutzern zuzuordnenPartyEndpoint
.
Notiz
Jede Xbox Live-Benutzer-ID wird nur einer PlayFab-Entitäts-ID zugeordnet, wenn dieser Xbox Live-Benutzer bereits mit einem PlayFab-Konto verknüpft wurde. Beim ersten PartyXblManager::LoginToPlayFab
Aufruf eines bestimmten Xbox-Benutzers wird automatisch ein PlayFab-Konto erstellt und verknüpft. Alternativ können Consumer des PlayFab SDK die LoginWithXbox-API verwenden, um die gleichen Ergebnisse zu erzielen.
Die lokale PartyXblLocalChatUser
wird für die Authentifizierung mit PlayFab verwendet. Wenn der Benutzer zuvor nicht mit einem Aufruf von PartyXblManager::LoginToPlayFab
bei PlayFab angemeldet war, muss die Xbox Live-Hilfsbibliothek den Benutzer im Hintergrund authentifizieren.
uint32_t userCount;
PartyXblChatUserArray chatUsers;
PartyError err = PartyXblManager::GetSingleton().GetChatUsers(&userCount, &users);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetChatUsers failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
// The list of remote Xbox Live User IDs. This can be populated with arbitrary IDs
// std::vector<uint64_t> remoteXboxLiveUserIds = {2533274792693551, 2814659110958830};
//
// but can also be pulled from the list of remote chat users
std::vector<uint64_t> remoteXboxLiveUserIds;
for (uint32_t i = 0; i < userCount; ++i)
{
PartyXblChatUser* chatUser = users[i];
PartyXblLocalChatUser* localChatUser;
err = chatUser->GetLocal(&localChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("PartyChatUser(0x%p)::GetLocal failed: %s\n", chatUser, PartyXblManager::GetErrorMessage(err));
return;
}
if (localChatUser != nullptr)
{
continue; // ignore local users
}
uint64_t userId;
err = chatUser->GetXboxUserId(&userId);
if (PARTY_FAILED(err))
{
DEBUGLOG("PartyChatUser(0x%p)::GetXboxUserId failed: %s\n", chatUser, PartyXblManager::GetErrorMessage(err));
return;
}
remoteXboxLiveUserIds.push_back(userId);
}
err = PartyXblManager::GetSingleton().GetEntityIdsFromXboxLiveUserIds(
remoteXboxLiveUserIds.size(),
remoteXboxLiveUserIds.data(),
localChatUser,
nullptr);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetEntityIdsFromXboxLiveUserIds failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
Kurz nach dem Aufruf PartyXblManager::GetEntityIdsFromXboxLiveUserIds
erhalten Sie eine PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
mit dem Ergebnis des Vorgangs. Dieses Ergebnis kann verwendet werden, um Ihre Zuordnungen zu erstellen oder zu aktualisieren.
// Wait for PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
if (stateChange->stateChangeType == PartyXblStateChangeType::GetEntityIdsFromXboxLiveUserIdsCompleted)
{
std::vector<std::pair<uint64_t, std::string>> cachedXboxUserIdToPlayFabEntityIdMap;
auto getEntityIdsFromXboxLiveUserIdsResult = static_cast<PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange*>(stateChange);
for (uint32_t i = 0; i < getEntityIdsFromXboxLiveUserIdsResult.entityIdMappingCount; ++i)
{
const PartyXblXboxUserIdToPlayFabEntityIdMapping& idMapping = getEntityIdsFromXboxLiveUserIdsResult.entityIdMappings[i];
Log(" Xbox Live User ID: %llu", idMapping.xboxLiveUserId);
if (strlen(idMapping.playfabEntityId)) != 0)
{
Log(" PlayFab Entity ID: %s", idMapping.playfabEntityId);
cachedXboxUserIdToPlayFabEntityIdMap.emplace_back(idMapping.xboxLiveUserId, idMapping.playfabEntityId);
}
else
{
// This Xbox Live User did not have a linked PlayFab Account.
Log(" PlayFab Entity ID: NOT FOUND");
}
}
m_cachedXboxUserIdToPlayFabEntityIdMap = std::move(cachedXboxUserIdToPlayFabEntityIdMap);
Mit einer solchen Zuordnung können Titel erkennen, wann ein Party-Objekt einen Xbox Live-Benutzer darstellt.
uint64_t
GetXboxUserIdFromPlayFabEntityId(
PartyString entityId
)
{
for (const std::pair<uint64_t, std::string>& idMapping : m_cachedXboxUserIdToPlayFabEntityIdMap)
{
const std::string& entityIdForXboxUserId = idMapping.second;
if (entityIdForXboxUserId == entityId)
{
return idMapping.first;
}
}
// Failed to find a matching Xbox User ID. This Entity ID does not represent an Xbox Live user.
return 0;
}
Besondere Überlegungen für Windows
Unter Windows benötigt die Xbox Live Helper-Bibliothek Hilfe aus dem Titel, um Xbox Live-Token zu erhalten. Die Bibliothek fordert Token an, indem generiert wird PartyXblTokenAndSignatureRequestedStateChange
. Der Titel kann die Xbox Authentication Library (XAL) verwenden, um diese Anforderungen zu erfüllen. Durch das Auslagern dieser Arbeit auf den Titel wird sichergestellt, dass sie die vollständige Kontrolle über alle Benutzeroberflächenbehandlungen und Zustimmungsaufforderungen hat, die normalerweise der Benutzerauthentifizierung zugeordnet sind.
if (stateChange->stateChangeType == PartyXblStateChangeType::TokenAndSignatureRequested)
{
auto tokenAndSignatureRequested = static_cast<PartyXblTokenAndSignatureRequestedStateChange*>(stateChange);
// Convert the headers to the format XAL expect
std::vector<XalHttpHeader> xalHeaders;
for (uint32_t i = 0; i < stateChange.headerCount; ++i)
{
xalHeaders.push_back({stateChange.headers[i].name, stateChange.headers[i].value});
}
XalUserGetTokenAndSignatureArgs args = {};
args.method = stateChange.method;
args.url = stateChange.url;
args.headerCount = static_cast<uint32_t>(xalHeaders.size());
args.headers = xalHeaders.data();
args.bodySize = stateChange.bodySize;
args.body = static_cast<const uint8_t*>(stateChange.body);
args.forceRefresh = stateChange.forceRefresh != 0;
args.allUsers = stateChange.allUsers != 0;
XAsyncBlock* asyncBlock = new XAsyncBlock;
asyncBlock->queue = m_queue;
HRESULT hr = XalUserGetTokenAndSignatureSilentlyAsync(m_userHandle, &args, asyncBlock);
}
Weitere Anleitungen zum Abrufen von Token und Signaturen mithilfe von XAL finden Sie in der Dokumentation zur Xbox-Authentifizierungsbibliothek.
Sobald Sie über das Token und die Signatur verfügen, können sie der Xbox Live Helper-Bibliothek zur Verfügung gestellt werden, indem Sie mit der gleichen correlationId
aufrufenPartyXblManager::CompleteGetTokenAndSignatureRequest()
, die für den Titel durch die Statusänderung bereitgestellt wurde.