GS2-Datastore SDK for Game Engine API Reference

Specifications of models and API references for GS2-Datastore SDK for Game Engine

Model

EzDataObject

Data Object

Data objects are data uploaded by game players. Data is generation managed, with 30 days of historical data stored.

Access permissions can be set for the data. There are three types of scopes:

  • public: Accessible to anyone
  • protected: Accessible only to game players with specified user IDs
  • private: Accessible only to yourself
TypeConditionRequiredDefaultValue LimitsDescription
dataObjectIdstring
*
~ 1024 charsData object GRN
* Set automatically by the server
namestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.
userIdstring
~ 128 charsUser ID
scopeString Enum
enum {
  “public”,
  “protected”,
  “private”
}
“private”File access permission
Controls who can access this data object. public allows anyone to access, protected restricts access to specified user IDs listed in allowUserIds, and private limits access to the owner only.
DefinitionDescription
“public”Public
“protected”Only to specified users
“private”Private
allowUserIdsList<string>{scope} == “protected”
*
[]0 ~ 100 itemsList of user IDs to be published
Specifies which users can access this data object when the scope is set to protected. Only users whose IDs are included in this list will be granted read access.

* Applicable only if scope is “protected”
statusString Enum
enum {
  “ACTIVE”,
  “UPLOADING”,
  “DELETED”
}
Status
The current lifecycle state of the data object. ACTIVE indicates the data is available for access, UPLOADING indicates a new version is being uploaded, and DELETED indicates the object has been marked for deletion (actual removal occurs 30 days later).
DefinitionDescription
“ACTIVE”Active
“UPLOADING”Uploading
“DELETED”Deleted (Actual deletion 30 days after the deletion process)
generationstring~ 128 charsData Generation
An identifier representing the current version of the uploaded data. Each time data is re-uploaded, a new generation ID is assigned.
createdAtlong
*
NowDatetime of creation
Unix time, milliseconds
* Set automatically by the server
updatedAtlong
*
NowDatetime of last update
Unix time, milliseconds
* Set automatically by the server

EzDataObjectHistory

Data Object History

You can check the update history of Data Objects. Each time a data object is re-uploaded, a history record is created containing the generation ID and file size. Historical data is retained for 30 days, allowing rollback and audit of previous versions.

TypeConditionRequiredDefaultValue LimitsDescription
dataObjectHistoryIdstring
*
~ 1024 charsData Object History GRN
* Set automatically by the server
generationstring
~ 128 charsGeneration ID
A unique identifier for the specific version of the data object at the time of upload. Corresponds to the generation field in the DataObject and can be used with PrepareDownloadByGeneration to download this specific version.
contentLengthlong
0 ~ 10485760File size
The size of the uploaded data in bytes for this generation. Maximum file size is 10 MB (10,485,760 bytes).
createdAtlong
*
NowDatetime of creation
Unix time, milliseconds
* Set automatically by the server

Methods

deleteDataObject

Delete an uploaded file

Marks the specified data object for deletion. The actual file is removed after 30 days. Use this when the player wants to delete save data or other uploaded content they no longer need.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.

Result

TypeDescription
itemEzDataObjectData object

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
InvalidStatusExceptionBadRequestExceptionDataObject is not in operable state.

Implementation Example

try {
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.DeleteDataObjectAsync(
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Datastore.Exception.InvalidStatusException e) {
    // DataObject is not in operable state.
}
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.DeleteDataObjectFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Datastore.Exception.InvalidStatusException)
        {
            // DataObject is not in operable state.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->DeleteDataObject(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Datastore::Error::FInvalidStatusError::Class))
        {
            // DataObject is not in operable state.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

doneUpload

Finalize a file upload

Call this after you have finished uploading the file to the URL returned by PrepareUpload or PrepareReUpload. This confirms the upload and makes the data object available for download (status changes to ACTIVE). If you skip this step, the data object remains in UPLOADING status and cannot be downloaded.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.

Result

TypeDescription
itemEzDataObjectData object

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
InvalidStatusExceptionBadRequestExceptionDataObject is not in operable state.
NotUploadedExceptionBadRequestExceptionDataObject is not uploaded.

Implementation Example

try {
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.DoneUploadAsync(
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Datastore.Exception.InvalidStatusException e) {
    // DataObject is not in operable state.
} catch(Gs2.Gs2Datastore.Exception.NotUploadedException e) {
    // DataObject is not uploaded.
}
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.DoneUploadFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Datastore.Exception.InvalidStatusException)
        {
            // DataObject is not in operable state.
        }
        if (future.Error is Gs2.Gs2Datastore.Exception.NotUploadedException)
        {
            // DataObject is not uploaded.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->DoneUpload(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Datastore::Error::FInvalidStatusError::Class))
        {
            // DataObject is not in operable state.
        }
        if (e->IsChildOf(Gs2::Datastore::Error::FNotUploadedError::Class))
        {
            // DataObject is not uploaded.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

listMyDataObjects

Get a list of the player’s uploaded data

Retrieves a list of data objects (files) that the player has uploaded. You can filter by status: ACTIVE (available for download), UPLOADING (upload in progress), or DELETED (scheduled for deletion). Use this to show a save-data list screen or to check what files the player currently has stored.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
statusStatus
DefinitionDescription
“ACTIVE”Active
“UPLOADING”Uploading
“DELETED”Deleted(Actual deletion 30 days after the deletion process)
pageTokenstring~ 1024 charsToken specifying the position from which to start acquiring data
limitint301 ~ 1000Number of data items to retrieve

Result

TypeDescription
itemsList<EzDataObject>List of Data object
nextPageTokenstringPage token to retrieve the rest of the listing

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.DataObjectsAsync(
        status: "ACTIVE"
    ).ToListAsync();
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.DataObjects(
        status: "ACTIVE"
    );
    List<EzDataObject> items = new List<EzDataObject>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->DataObjects(
        "ACTIVE" // status
    );
    TArray<Gs2::UE5::Datastore::Model::FEzDataObjectPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // Start event handling
    var callbackId = domain.SubscribeDataObjects(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeDataObjects(callbackId);
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // Start event handling
    var callbackId = domain.SubscribeDataObjects(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeDataObjects(callbackId);
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeDataObjects(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeDataObjects(CallbackId);

prepareDownload

Get a download URL for a file (by data object ID)

Returns a temporary download URL for the specified data object. The data object is identified by its ID (GRN). Access control is applied — only the file owner or users in the allow-list can download. Use the returned URL to download the file with an HTTP GET request.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
dataObjectIdstring
~ 1024 charsData object GRN
gameSessionGameSession
GameSession

Result

TypeDescription
itemEzDataObjectData object
fileUrlstringURL to download the file
contentLengthlongFile size

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.PrepareDownloadAsync(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    var item = await result.ModelAsync();
    var fileUrl = result.FileUrl;
    var contentLength = result.ContentLength;
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.PrepareDownloadFuture(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var fileUrl = future.Result.FileUrl;
    var contentLength = future.Result.ContentLength;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->PrepareDownload(
        "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001" // dataObjectId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto FileUrl = Result->FileUrl;
    const auto ContentLength = Result->ContentLength;

prepareDownloadByUserIdAndDataObjectName

Get a download URL for another player’s file (by user ID and name)

Downloads another player’s data by specifying their user ID and the data object name. Access control is applied — the data must be public, or the requesting player must be in the owner’s allow-list. Use this when players share data with each other, such as custom levels or replays.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
userIdstring
~ 128 charsUser ID
dataObjectNamestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.

Result

TypeDescription
itemEzDataObjectData object
fileUrlstringURL to download the file
contentLengthlongFile size

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.PrepareDownloadByUserIdAndDataObjectNameAsync(
    );
    var item = await result.ModelAsync();
    var fileUrl = result.FileUrl;
    var contentLength = result.ContentLength;
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.PrepareDownloadByUserIdAndDataObjectNameFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var fileUrl = future.Result.FileUrl;
    var contentLength = future.Result.ContentLength;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->PrepareDownloadByUserIdAndDataObjectName(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto FileUrl = Result->FileUrl;
    const auto ContentLength = Result->ContentLength;

prepareDownloadOwnData

Get a download URL for the player’s own file (by name)

A convenient way to download the player’s own data by specifying the data object name instead of its ID. Use this when the player wants to load their own save data or uploaded content. Returns a temporary download URL and the file size.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
dataObjectNamestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.
gameSessionGameSession
GameSession

Result

TypeDescription
itemEzDataObjectData object
fileUrlstringURL to download the file
contentLengthlongFile size

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.PrepareDownloadOwnDataAsync(
    );
    var item = await result.ModelAsync();
    var fileUrl = result.FileUrl;
    var contentLength = result.ContentLength;
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.PrepareDownloadOwnDataFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var fileUrl = future.Result.FileUrl;
    var contentLength = future.Result.ContentLength;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->PrepareDownloadOwnData(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto FileUrl = Result->FileUrl;
    const auto ContentLength = Result->ContentLength;

Download

Download Data

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name

Result

TypeDescription
itembyte arraybinary data

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.DownloadAsync(
        dataObjectName: "dataObject-0001"
    );
</div>
<div class="tab-pane fade"
    id="tabs-01-02" role="tabpanel" aria-labelled-by="tabs-01-02-tab" tabindex="1"><div class="highlight"><pre class="chroma"><code class="language-cs" data-lang="cs">    var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace-0001"
).Me(
    gameSession: GameSession
).DataObject(
    dataObjectName: "dataObject-0001"
);
var future = domain.DownloadFuture();
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;</code></pre></div>
      
</div>
<div class="tab-pane fade"
    id="tabs-01-03" role="tabpanel" aria-labelled-by="tabs-01-03-tab" tabindex="1"><div class="highlight"><pre class="chroma"><code class="language-cpp" data-lang="cpp">    const auto Domain = Gs2-&gt;Datastore-&gt;Namespace(
    "namespace-0001" // namespaceName
)-&gt;Me(
    GameSession
)-&gt;DataObject(
    "dataObject-0001" // dataObjectName
);
const auto Future = Domain-&gt;Download();
Future-&gt;StartSynchronousTask();
if (Future-&gt;GetTask().IsError())
{
    return false;
}

// obtain changed values / result values
const auto Future2 = Future-&gt;GetTask().Result()-&gt;Model();
Future2-&gt;StartSynchronousTask();
if (Future2-&gt;GetTask().IsError())
{
    return Future2-&gt;GetTask().Error();
}
const auto Result = Future2-&gt;GetTask().Result();</code></pre></div>
      
</div>

DownloadByUserIdAndDataObjectName

Download data by specifying user ID and data name

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
userIdstring
~ 128 charsUser ID
dataObjectNamestring
UUID~ 128 charsData Object Name

Result

TypeDescription
itembyte arraybinary data

Implementation Example

var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace-0001"
).User(
    userId: "user-0001"
).DataObject(
    dataObjectName: "dataObject-0001"
);
var result = await domain.DownloadByUserIdAndDataObjectNameAsync(
);
</div>
<div class="tab-pane fade"
    id="tabs-02-02" role="tabpanel" aria-labelled-by="tabs-02-02-tab" tabindex="2"><div class="highlight"><pre class="chroma"><code class="language-cs" data-lang="cs">    var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace-0001"
).User(
    userId: "user-0001"
).DataObject(
    dataObjectName: "dataObject-0001"
);
var future = domain.DownloadByUserIdAndDataObjectNameFuture(
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;</code></pre></div>
      
</div>
<div class="tab-pane fade"
    id="tabs-02-03" role="tabpanel" aria-labelled-by="tabs-02-03-tab" tabindex="2"><div class="highlight"><pre class="chroma"><code class="language-cpp" data-lang="cpp">    const auto Domain = Gs2-&gt;Datastore-&gt;Namespace(
    "namespace-0001" // namespaceName
)-&gt;User(
    "user-0001" // userId
)-&gt;DataObject(
    "dataObject-0001" // dataObjectName
);
const auto Future = Domain-&gt;DownloadByUserIdAndDataObjectName(
);
Future-&gt;StartSynchronousTask();
if (Future-&gt;GetTask().IsError())
{
    return false;
}

// obtain changed values / result values
const auto Future2 = Future-&gt;GetTask().Result()-&gt;Model();
Future2-&gt;StartSynchronousTask();
if (Future2-&gt;GetTask().IsError())
{
    return Future2-&gt;GetTask().Error();
}
const auto Result = Future2-&gt;GetTask().Result();</code></pre></div>
      
</div>

DownloadOwn

Download own data

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name

Result

TypeDescription
itembyte arraybinary data

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.DownloadOwnAsync();
</div>
<div class="tab-pane fade"
    id="tabs-04-02" role="tabpanel" aria-labelled-by="tabs-04-02-tab" tabindex="4"><div class="highlight"><pre class="chroma"><code class="language-cs" data-lang="cs">    var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace-0001"
).Me(
    gameSession: GameSession
).DataObject(
    dataObjectName: "dataObject-0001"
);
var future = domain.DownloadOwnFuture();
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;</code></pre></div>
      
</div>
<div class="tab-pane fade"
    id="tabs-04-03" role="tabpanel" aria-labelled-by="tabs-04-03-tab" tabindex="4"><div class="highlight"><pre class="chroma"><code class="language-cpp" data-lang="cpp">    const auto Domain = Gs2-&gt;Datastore-&gt;Namespace(
    "namespace-0001" // namespaceName
)-&gt;Me(
    GameSession
)-&gt;DataObject(
    "dataObject-0001" // dataObjectName
);
const auto Future = Domain-&gt;DownloadOwn(
);
Future-&gt;StartSynchronousTask();
if (Future-&gt;GetTask().IsError())
{
    return false;
}

// obtain changed values / result values
const auto Future2 = Future-&gt;GetTask().Result()-&gt;Model();
Future2-&gt;StartSynchronousTask();
if (Future2-&gt;GetTask().IsError())
{
    return Future2-&gt;GetTask().Error();
}
const auto Result = Future2-&gt;GetTask().Result();</code></pre></div>
      
</div>

ReUpload

Re-upload

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name
databyte arraybinary data

Result

TypeDescription
itemEzDataObjectData object
uploadUrlstringURL used to execute the upload process

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.ReUploadAsync(
        data: binary
    );
    var item = await result.ModelAsync();
</div>
<div class="tab-pane fade"
    id="tabs-06-02" role="tabpanel" aria-labelled-by="tabs-06-02-tab" tabindex="6"><div class="highlight"><pre class="chroma"><code class="language-cs" data-lang="cs">    var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace-0001"
).Me(
    gameSession: GameSession
).DataObject(
    dataObjectName: "dataObject-0001"
);
var future = domain.ReUploadFuture(
    data: binary
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.ModelFuture();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;</code></pre></div>
      
</div>
<div class="tab-pane fade"
    id="tabs-06-03" role="tabpanel" aria-labelled-by="tabs-06-03-tab" tabindex="6"><div class="highlight"><pre class="chroma"><code class="language-cpp" data-lang="cpp">    const auto Domain = Gs2-&gt;Datastore-&gt;Namespace(
    "namespace-0001" // namespaceName
)-&gt;Me(
    GameSession
)-&gt;DataObject(
    "dataObject-0001" // dataObjectName
);
const auto Future = Domain-&gt;ReUpload(
    binary // Binary
);
Future-&gt;StartSynchronousTask();
if (Future-&gt;GetTask().IsError())
{
    return false;
}

// obtain changed values / result values
const auto Future2 = Future-&gt;GetTask().Result()-&gt;Model();
Future2-&gt;StartSynchronousTask();
if (Future2-&gt;GetTask().IsError())
{
    return Future2-&gt;GetTask().Error();
}
const auto Result = Future2-&gt;GetTask().Result();</code></pre></div>
      
</div>

prepareReUpload

Prepare to re-upload (overwrite) an existing file

Returns a new upload URL for replacing the content of an existing data object. The previous version of the file is kept in the history, so you can still download older versions by generation number. After uploading the new file to the returned URL, call DoneUpload to finalize it.

Re-upload flow: PrepareReUpload → PUT file to returned URL → DoneUpload

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.
contentTypestring“application/octet-stream”~ 256 charsMIME-Type of the data to be uploaded

Result

TypeDescription
itemEzDataObjectData object
uploadUrlstringURL used to execute the upload process

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.PrepareReUploadAsync(
        contentType: "application/octet-stream"
    );
    var item = await result.ModelAsync();
    var uploadUrl = result.UploadUrl;
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.PrepareReUploadFuture(
        contentType: "application/octet-stream"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var uploadUrl = future.Result.UploadUrl;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->PrepareReUpload(
        "application/octet-stream" // contentType
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto UploadUrl = Result->UploadUrl;

prepareUpload

Prepare to upload a new file

Creates a new data object and returns an upload URL. After calling this API, upload the file to the returned URL using an HTTP PUT request, then call DoneUpload to finalize it. You can set the access scope (public or protected) and specify which users are allowed to download the file. If updateIfExists is true, uploading a file with the same name will update the existing one instead of returning an error.

Upload flow: PrepareUpload → PUT file to returned URL → DoneUpload

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
namestring~ 128 charsData Object Name
If not specified, a UUID is automatically assigned.
scope“private”File access permission
Controls who can access this data object. public allows anyone to access, protected restricts access to specified user IDs listed in allowUserIds, and private limits access to the owner only.
DefinitionDescription
“public”Public
“protected”Only to specified users
“private”Private
contentTypestring“application/octet-stream”~ 256 charsMIME-Type of the data to be uploaded
allowUserIdsList<string>{scope} == “protected”[]0 ~ 100 itemsList of user IDs to be published
Specifies which users can access this data object when the scope is set to protected. Only users whose IDs are included in this list will be granted read access.

* Applicable only if scope is “protected”
updateIfExistsboolfalseWhether to raise an error if data already exists or to update the data

Result

TypeDescription
itemEzDataObjectData object
uploadUrlstringURL used to execute the upload process

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.PrepareUploadAsync(
        name: "dataObject-0001",
        scope: "public",
        contentType: "application/octet-stream",
        allowUserIds: null,
        updateIfExists: null
    );
    var item = await result.ModelAsync();
    var uploadUrl = result.UploadUrl;
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.PrepareUploadFuture(
        name: "dataObject-0001",
        scope: "public",
        contentType: "application/octet-stream",
        allowUserIds: null,
        updateIfExists: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var uploadUrl = future.Result.UploadUrl;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->PrepareUpload(
        "dataObject-0001", // name
        "public", // scope
        "application/octet-stream" // contentType
        // allowUserIds
        // updateIfExists
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto UploadUrl = Result->UploadUrl;

restoreDataObject

Repair a data object’s management information

Fixes inconsistencies between a data object’s metadata and its actual file. If the recorded file size or version number does not match the real file (e.g., due to an interrupted upload), this API corrects the metadata. You normally do not need to call this — it is only needed for recovery when something goes wrong during an upload.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
dataObjectIdstring
~ 1024 charsData object GRN

Result

TypeDescription
itemEzDataObjectData object

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
InvalidStatusExceptionBadRequestExceptionDataObject is not in operable state.

Implementation Example

try {
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    );
    var result = await domain.RestoreDataObjectAsync(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Datastore.Exception.InvalidStatusException e) {
    // DataObject is not in operable state.
}
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    );
    var future = domain.RestoreDataObjectFuture(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Datastore.Exception.InvalidStatusException)
        {
            // DataObject is not in operable state.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto Future = Domain->RestoreDataObject(
        "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001" // dataObjectId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Datastore::Error::FInvalidStatusError::Class))
        {
            // DataObject is not in operable state.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

updateDataObject

Update access settings of a data object

Changes who can access an uploaded data object. You can switch the scope between public (anyone can download) and protected (only specified users can download), and update the list of allowed user IDs. This does not change the file content itself — to update the file, use PrepareReUpload instead.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
scope“private”File access permission
Controls who can access this data object. public allows anyone to access, protected restricts access to specified user IDs listed in allowUserIds, and private limits access to the owner only.
DefinitionDescription
“public”Public
“protected”Only to specified users
“private”Private
allowUserIdsList<string>{scope} == “protected”[]0 ~ 100 itemsList of user IDs to be published
Specifies which users can access this data object when the scope is set to protected. Only users whose IDs are included in this list will be granted read access.

* Applicable only if scope is “protected”

Result

TypeDescription
itemEzDataObjectData object

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.UpdateDataObjectAsync(
        scope: "public",
        allowUserIds: null
    );
    var item = await result.ModelAsync();
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.UpdateDataObjectFuture(
        scope: "public",
        allowUserIds: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->UpdateDataObject(
        "public" // scope
        // allowUserIds
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

listDataObjectHistories

Get the version history of a data object

Retrieves the list of past versions (generations) of a data object. Every time you re-upload a file with PrepareReUpload, the previous version is saved in the history. Each entry shows the file size and when it was created, so you can check what changed and when. Use this to build a version history screen or to let the player revert to an older save.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
dataObjectNamestring
UUID~ 128 charsData Object Name
A unique name identifying the data object. Automatically generated in UUID format by default. Used to reference and manage the uploaded data within the namespace.
pageTokenstring~ 1024 charsToken specifying the position from which to start acquiring data
limitint301 ~ 1000Number of data items to retrieve

Result

TypeDescription
itemsList<EzDataObjectHistory>List of Data Object Histories
nextPageTokenstringPage token to retrieve the rest of the listing

Implementation Example

    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var items = await domain.DataObjectHistoriesAsync(
    ).ToListAsync();
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var it = domain.DataObjectHistories(
    );
    List<EzDataObjectHistory> items = new List<EzDataObjectHistory>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto It = Domain->DataObjectHistories(
    );
    TArray<Gs2::UE5::Datastore::Model::FEzDataObjectHistoryPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    
    // Start event handling
    var callbackId = domain.SubscribeDataObjectHistories(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeDataObjectHistories(callbackId);
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    
    // Start event handling
    var callbackId = domain.SubscribeDataObjectHistories(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeDataObjectHistories(callbackId);
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeDataObjectHistories(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeDataObjectHistories(CallbackId);