다음을 통해 공유


XGameSaveCreateUpdate

XGameSaveSubmitUpdate를 호출하여 나중에 제출되는 업데이트를 생성합니다.

구문

HRESULT XGameSaveCreateUpdate(  
         XGameSaveContainerHandle container,  
         const char* containerDisplayName,  
         XGameSaveUpdateHandle* updateContext  
)  

매개 변수

container _In_
형식: XGameSaveContainerHandle

업데이트할 XGameSaveContainer에 대한 핸들입니다.

containerDisplayName _In_z_
형식: char*

업데이트할 컨테이너의 표시 이름입니다.

updateContext _Outptr_result_nullonfailure_
형식: XGameSaveUpdateHandle*

생성할 XGameSaveUpdate에 대한 핸들입니다.

반환 값

형식: HRESULT

함수 결과입니다.

비고

참고 항목

이 함수는 시간에 민감한 스레드에서 호출하는 것이 안전하지 않습니다. 자세한 내용은 시간에 민감한 스레드를 참조하세요.

이 API의 저장소 부분은 게임 데이터를 영구 저장소로 안전하고, 신뢰할 수 있는 트랜잭션 방식으로 쉽게 전송할 수 있도록 디자인되었습니다. 컨테이너의 지원 데이터를 항상 일관된 상태로 유지하여 전체 작업이 하나의 단위로 성공하거나 실패하도록 해야 합니다. 일부 Blob 데이터가 컨테이너에 있는 다른 데이터와 일치하지 않는 부분 업데이트는 필요하지 않습니다. 이를 위해 blob 쓰기 및 삭제가 제출되는 업데이트 컨텍스트가 제공되며, 완료되었을 때 전체 컨텍스트가 제출됩니다. 실제로는 다음과 같이 표시됩니다.

XGameSaveUpdate에는 XGameSaveSubmitBlobWriteXGameSaveSubmitBlobDelete로 컨테이너 내의 blob에서 수행되는 쓰기 및 삭제 작업이 채워집니다. 업데이트는 XGameSaveSubmitUpdate를 호출하여 완료됩니다.

XGameSaveUpdate가 완료되었으면 XGameSaveCloseUpdate로 닫습니다.

다음 C++ 샘플은 동기 XGameSave 업데이트를 보여 줍니다.

// SYNC Write - should not be called on a time sensitive thread 
//              as this will block until the operation is complete 
void Sample::_SaveDataSync(const char* containerName, const char* containerDisplayName) 
{ 
    HRESULT hr; 
    XGameSaveContainerHandle containerContext; 
    XGameSaveUpdateHandle updateContext; 
  
    hr = XGameSaveCreateContainer(_provider, containerName, &containerContext); 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveCreateUpdate(containerContext, containerDisplayName, &updateContext); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitBlobWrite(updateContext, "WorldState", _worldState.data(), _worldState.size()); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitBlobWrite(updateContext, "PlayerState", _playerState.data(), _playerState.size()); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitBlobWrite(updateContext, "PlayerInventory", _playerInventory.data(), _playerInventory.size()); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        if (_clearLevelProgress) 
        { 
            hr = XGameSaveSubmitBlobDelete(updateContext, "LevelProgress"); 
        } 
    } 
  
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitUpdate(updateContext); 
    } 
  
    if (updateContext) 
    { 
        XGameSaveCloseUpdate(updateContext); 
    } 
    if (containerContext) 
    { 
        XGameSaveCloseContainer(containerContext); 
    } 
  
    _HandleContainerUpdateErrors(hr); 
} 
  
  
void Sample::_HandleContainerUpdateErrors(HRESULT hr) 
{ 
    switch (hr) 
    { 
    case E_GS_INVALID_CONTAINER_NAME: 
        // tried to access a container with an invalid name 
        break; 
    case E_GS_OUT_OF_LOCAL_STORAGE: 
        // storage location is full, let the user know that saves won't work till this is fixed 
        break; 
    case E_GS_UPDATE_TOO_BIG: 
        // the blob that we provided was too big, can't be larger than GS_MAX_BLOB_SIZE 
        break; 
    case E_GS_QUOTA_EXCEEDED: 
        // the update we did was larger than our overall quota, need to track that! (see XGameSaveQueryRemainingQuota & XGameSaveQueryRemainingQuotaAsync) 
        break; 
    case E_GS_CONTAINER_NOT_IN_SYNC: 
    case E_GS_CONTAINER_SYNC_FAILED: 
        // need to sync and we are offline ? 
        break; 
    case E_GS_HANDLE_EXPIRED: 
        // need to re-initialize since another device has taken 
        // ownership while we were suspended and/or busy 
        break; 
    } 
}

다음 C++ 샘플은 비동기 XGameSave 업데이트를 보여 줍니다.

// ASYNC Write - can be kicked off from a time sensitive thread 
//               actual work and completion will be scheduled base upon 
//               the configuration of the async_queue tied to the XAsyncBlock. 
void Sample::_SaveDataAsync(const char* containerName, const char* containerDisplayName) 
{ 
    struct SaveContext 
    { 
        SaveContext(Sample* s) : self(s), containerContext(nullptr), updateContext(nullptr) {} 
        ~SaveContext() 
        { 
            if (updateContext) 
            { 
                XGameSaveCloseUpdate(updateContext); 
            } 
            if (containerContext) 
            { 
                XGameSaveCloseContainer(containerContext); 
            } 
        } 
  
        XAsyncBlock async; 
        XGameSaveContainerHandle containerContext; 
        XGameSaveUpdateHandle updateContext; 
        Sample* self; 
    }; 
  
    HRESULT hr; 
    SaveContext* saveContext = new SaveContext(this); 
    if (saveContext == nullptr) 
    { 
        hr = E_OUTOFMEMORY; 
    } 
    if (SUCCEEDED(hr)) 
    { 
        saveContext->async.context = saveContext; 
        saveContext->async.callback = [](XAsyncBlock* async) 
        { 
            auto ctx = reinterpret_cast<SaveContext*>(async->context); 
            auto self = ctx->self; 
            HRESULT hr = XGameSaveSubmitUpdateResult(async); 
            self->_HandleContainerUpdateErrors(hr); 
            delete ctx; 
        }; 
    } 
  
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveCreateContainer(_provider, containerName, &saveContext->containerContext); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveCreateUpdate(saveContext->containerContext, containerDisplayName, &saveContext->updateContext); 
    } 
  
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitBlobWrite(saveContext->updateContext, "WorldState", _worldState.data(), _worldState.size()); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitBlobWrite(saveContext->updateContext, "PlayerState", _playerState.data(), _playerState.size()); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitBlobWrite(saveContext->updateContext, "PlayerInventory", _playerInventory.data(), _playerInventory.size()); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        if (_clearLevelProgress) 
        { 
            hr = XGameSaveSubmitBlobDelete(saveContext->updateContext, "LevelProgress"); 
        } 
    } 
    if (SUCCEEDED(hr)) 
    { 
        hr = XGameSaveSubmitUpdateAsync(saveContext->updateContext, &saveContext->async); 
    } 
    if (SUCCEEDED(hr)) 
    { 
        // context is now owned by the async 
        saveContext = nullptr; 
    } 
  
    // if there was any error we need to cleanup the saveContext 
    if (saveContext) 
    { 
        delete saveContext; 
    } 
  
} 

요구 사항

헤더: XGameSave.h

라이브러리: xgameruntime.lib

지원되는 플랫폼: Windows, Xbox One 패밀리 콘솔 및 Xbox Series 콘솔

참고 항목

XGameSave
XGameSaveSubmitBlobWrite
XGameSaveSubmitBlobDelete
XGameSaveSubmitUpdate
XGameSaveCloseUpdate게임 저장 오류