GS2-StateMachine SDK for Game Engine API リファレンス
モデル
EzStatus
ステートマシンの状態
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| statusId | string | ✓ | ~ 1024文字 | ステートマシンの状態GRN | ||||||||||||
| name | string | ✓ | UUID | ~ 36文字 | ステータス名 | |||||||||||
| enableSpeculativeExecution | 文字列列挙型 enum { “enable”, “disable” } | ✓ | “disable” | ~ 128文字 | 投機的実行を有効にするか 
 | |||||||||||
| stateMachineDefinition | string | {enableSpeculativeExecution} == “enable” | ~ 16777216文字 | ステートマシン定義 enableSpeculativeExecution が “enable” であれば 有効 | ||||||||||||
| randomStatus | EzRandomStatus | {enableSpeculativeExecution} == “enable” | 乱数状態 enableSpeculativeExecution が “enable” であれば 有効 | |||||||||||||
| stacks | List<EzStackEntry> | [] | 0 ~ 1024 items | スタック | ||||||||||||
| variables | List<EzVariable> | [] | 0 ~ 1000 items | ステートマシンごとの状態変数 | ||||||||||||
| status | 文字列列挙型 enum { “Running”, “Wait”, “Pass”, “Error” } | ✓ | “Running” | ~ 128文字 | ステータス 
 | |||||||||||
| lastError | string | ~ 1024文字 | 最後のエラー | |||||||||||||
| transitionCount | int | ✓ | 0 | 0 ~ 2147483645 | 遷移回数 | 
EzStackEntry
スタック
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| stateMachineName | string | ✓ | ~ 128文字 | ステートマシン名 | ||
| taskName | string | ✓ | ~ 128文字 | タスク名 | 
EzVariable
ステートマシンごとの状態変数
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| stateMachineName | string | ✓ | ~ 128文字 | ステートマシン名 | ||
| value | string | ✓ | ~ 1048576文字 | 値 | 
EzChangeStateEvent
ステートの変更イベント
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| taskName | string | ✓ | ~ 128文字 | タスク名 | ||
| hash | string | ✓ | ~ 64文字 | ハッシュ | ||
| timestamp | long | ✓ | タイムスタンプ (UNIX時間 単位:ミリ秒) | 
EzEmitEvent
メッセージの送信イベント
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| event | string | ✓ | ~ 128文字 | イベント名 | ||
| parameters | string | ✓ | ~ 1024文字 | パラメータ | ||
| timestamp | long | ✓ | タイムスタンプ (UNIX時間 単位:ミリ秒) | 
EzEvent
イベント
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| eventType | 文字列列挙型 enum { “change_state”, “emit” } | ✓ | ~ 128文字 | イベントの種類 
 | ||||||||
| changeStateEvent | EzChangeStateEvent | {eventType} == “change_state” | ✓ | ステートの変更 eventType が “change_state” であれば 必須 | ||||||||
| emitEvent | EzEmitEvent | {eventType} == “emit” | ✓ | メッセージの送信 eventType が “emit” であれば 必須 | 
EzRandomStatus
乱数の状態
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| seed | long | ✓ | 0 ~ 4294967294 | 乱数シード | ||
| used | List<EzRandomUsed> | 0 ~ 1000 items | 使用済み乱数リスト | 
EzRandomUsed
使用済み乱数
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| category | long | ✓ | 0 ~ 4294967294 | カテゴリ | ||
| used | long | ✓ | 0 ~ 4294967294 | 使用済み乱数 | 
EzVerifyActionResult
検証アクションの実行結果
EzConsumeActionResult
消費アクションの実行結果
EzAcquireActionResult
入手アクションの実行結果
EzTransactionResult
トランザクション実行結果
サーバーサイドでのトランザクションの自動実行機能を利用して実行されたトランザクションの実行結果
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| transactionId | string | ✓ | 36 ~ 36文字 | トランザクションID | ||
| verifyResults | List<EzVerifyActionResult> | 0 ~ 10 items | 検証アクションの実行結果リスト | |||
| consumeResults | List<EzConsumeActionResult> | [] | 0 ~ 10 items | 消費アクションの実行結果リスト | ||
| acquireResults | List<EzAcquireActionResult> | [] | 0 ~ 100 items | 入手アクションの実行結果リスト | 
メソッド
emit
ステートマシンにイベントを送信
Request
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | ||
| accessToken | string | ✓ | ~ 128文字 | アクセストークン | ||
| statusName | string | ✓ | ~ 36文字 | ステータス名 | ||
| eventName | string | ✓ | ~ 36文字 | イベントの名前 | ||
| args | string | ✓ | “{}” | ~ 4096文字 | ステートマシンに渡す引数 | 
Result
| 型 | 説明 | |
|---|---|---|
| item | EzStatus | ステートマシンの状態 | 
実装例
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var result = await domain.EmitAsync(
        eventName: "event-0001",
        args: "{\"value1\": \"value1\", \"value2\": 2.0, \"value3\": 3}"
    );
    var item = await result.ModelAsync();    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.EmitFuture(
        eventName: "event-0001",
        args: "{\"value1\": \"value1\", \"value2\": 2.0, \"value3\": 3}"
    );
    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->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Emit(
        "event-0001", // eventName
        "{\"value1\": \"value1\", \"value2\": 2.0, \"value3\": 3}" // args
    );
    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();exit
終了したステートマシンを削除
Request
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | ||
| accessToken | string | ✓ | ~ 128文字 | アクセストークン | ||
| statusName | string | ✓ | ~ 36文字 | ステータス名 | 
Result
| 型 | 説明 | |
|---|---|---|
| item | EzStatus | 終了したステートマシンの状態 | 
実装例
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var result = await domain.ExitAsync(
    );    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ExitFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Exit(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();getStatus
ステートマシンの現在の状態を取得
Request
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | ||
| accessToken | string | ✓ | ~ 128文字 | アクセストークン | ||
| statusName | string | ✓ | ~ 36文字 | ステータス名 | 
Result
| 型 | 説明 | |
|---|---|---|
| item | EzStatus | ステートマシンの状態 | 
実装例
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var item = await domain.ModelAsync();    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }値の変更イベントハンドリング
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );
    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::StateMachine::Model::FStatus> value) {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );
    // イベントハンドリングを停止
    Domain->Unsubscribe(CallbackId);Warning
このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。
ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。
そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
listStatuses
ステートマシンの現在の状態の一覧を取得
Request
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | ||||||||||||
| accessToken | string | ✓ | ~ 128文字 | アクセストークン | ||||||||||||
| status | 文字列列挙型 enum { “Running”, “Wait”, “Pass”, “Error” } | ~ 128文字 | ステータス 
 | |||||||||||||
| pageToken | string | ~ 1024文字 | データの取得を開始する位置を指定するトークン | |||||||||||||
| limit | int | ✓ | 30 | 1 ~ 1000 | データの取得件数 | 
Result
| 型 | 説明 | |
|---|---|---|
| items | List<EzStatus> | ステートマシンの状態のリスト | 
| nextPageToken | string | リストの続きを取得するためのページトークン | 
実装例
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.StatusesAsync(
        status: "Running"
    ).ToListAsync();    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Statuses(
        status: "Running"
    );
    List<EzStatus> items = new List<EzStatus>();
    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->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Statuses(
        "Running" // status
    );
    TArray<Gs2::UE5::StateMachine::Model::FEzStatusPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }値の変更イベントハンドリング
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeStatuses(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );
    // イベントハンドリングを停止
    domain.UnsubscribeStatuses(callbackId);    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Statuses(
        status: "Running"
    );
    List<EzStatus> items = new List<EzStatus>();
    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->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->SubscribeStatuses(
        []() {
            // リストの要素が変化した時に呼び出される
        }
    );
    // イベントハンドリングを停止
    Domain->UnsubscribeStatuses(CallbackId);Warning
このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。
ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。
そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
report
ステートマシンの投機的実行結果を送信
Request
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | ||
| accessToken | string | ✓ | ~ 128文字 | アクセストークン | ||
| statusName | string | ✓ | ~ 36文字 | ステータス名 | ||
| events | List<EzEvent> | 0 ~ 1000 items | イベントのリスト | 
Result
| 型 | 説明 | |
|---|---|---|
| item | EzStatus | ステートマシンの状態 | 
Error
このAPIには特別な例外が定義されています。
GS2-SDK for GameEngine ではゲーム内でハンドリングが必要そうなエラーは一般的な例外から派生した特殊化した例外を用意することでハンドリングしやすくしています。
一般的なエラーの種類や、ハンドリング方法は こちら のドキュメントを参考にしてください。
| 型 | 基底クラス | 説明 | 
|---|---|---|
| StateMismatchException | BadRequestException | レポートの検証の結果状態が不一致となりました | 
実装例
try {
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var result = await domain.ReportAsync(
        events: new List<Gs2.Unity.Gs2StateMachine.Model.EzEvent> {
            new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                EventType = "emit",
                EmitEvent = 
                new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                    Event = "message",
                    Parameters = "{\"payload\": \"Hello World\"}",
                    Timestamp = 1000,
                },
            },
        }
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2StateMachine.Exception.StateMismatch e) {
    // State of the verification result of the report is inconsistent.
}    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ReportFuture(
        events: new List<Gs2.Unity.Gs2StateMachine.Model.EzEvent> {
            new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                EventType = "emit",
                EmitEvent = 
                new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                    Event = "message",
                    Parameters = "{\"payload\": \"Hello World\"}",
                    Timestamp = 1000,
                },
            },
        }
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2StateMachine.Exception.StateMismatchException)
        {
            // State of the verification result of the report is inconsistent.
        }
        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->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Report(
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::StateMachine::Model::FEzEvent>>>();
            v->Add(
                MakeShared<Gs2::UE5::StateMachine::Model::FEzEvent>()
                ->WithEventType(TOptional<FString>("emit"))
                ->WithEmitEvent(MakeShared<Gs2::UE5::StateMachine::Model::FEzEmitEvent>() 
                    ->WithEvent(TOptional<FString>("message"))
                    ->WithParameters(TOptional<FString>("{\"payload\": \"Hello World\"}"))
                    ->WithTimestamp(TOptional<int32>(1000))
                );
            );
            return v;
        }() // events
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::StateMachine::Error::FStateMismatchError::Class))
        {
            // State of the verification result of the report is inconsistent.
        }
        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();