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文字 | ステートマシン定義 | |
randomStatus | EzRandomStatus | {enableSpeculativeExecution} == “enable” | 乱数状態 | ||
stacks | List<EzStackEntry> | ~ 1024 items | スタック | ||
variables | List<EzVariable> | ~ 1000 items | ステートマシンごとの状態変数 | ||
status | enum { “Running”, “Wait”, “Pass”, “Error” } | ✓ | “Running” | ~ 128文字 | ステータス |
lastError | string | ~ 1024文字 | 最後のエラー | ||
transitionCount | int | ✓ | 0 | ~ 2147483645 | 遷移回数 |
enableSpeculativeExecution に指定する列挙型の定義
定義 | 説明 |
---|---|
enable | 有効 |
disable | 無効 |
status に指定する列挙型の定義
定義 | 説明 |
---|---|
Running | 実行中 |
Wait | 待機中 |
Pass | 終了 |
Error | エラー |
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” | ステートの変更 | ||
emitEvent | EzEmitEvent | {eventType} == “emit” | メッセージの送信 |
eventType に指定する列挙型の定義
定義 | 説明 |
---|---|
change_state | ステートの変更 |
emit | メッセージの送信 |
EzRandomStatus
乱数の状態
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
seed | long | ✓ | ~ 4294967294 | 乱数シード | |
used | List<EzRandomUsed> | ~ 1000 items | 使用済み乱数リスト |
EzRandomUsed
使用済み乱数
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
category | long | ✓ | ~ 4294967294 | カテゴリ | |
used | long | ✓ | ~ 4294967294 | 使用済み乱数 |
メソッド
emit
ステートマシンにイベントを送信
Request
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | |
accessToken | string | ✓ | ~ 128文字 | ユーザーID | |
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: "$status1.name"
);
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: "$status1.name"
);
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.Model();
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(
"$status1.name" // 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文字 | ユーザーID | |
statusName | string | ✓ | ~ 36文字 | ステータス名 |
Result
型 | 説明 | |
---|---|---|
item | EzStatus | 終了したステートマシンの状態 |
実装例
var domain = gs2.StateMachine.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
statusName: "$status1.name"
);
var result = await domain.ExitAsync(
);
var domain = gs2.StateMachine.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
statusName: "$status1.name"
);
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(
"$status1.name" // 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文字 | ユーザーID | |
statusName | string | ✓ | ~ 36文字 | ステータス名 |
Result
型 | 説明 | |
---|---|---|
item | EzStatus | ステートマシンの状態 |
実装例
var domain = gs2.StateMachine.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
statusName: "$status1.name"
);
var item = await domain.ModelAsync();
var domain = gs2.StateMachine.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
statusName: "$status1.name"
);
var future = domain.Model();
yield return future;
var item = future.Result;
const auto Domain = Gs2->StateMachine->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Status(
"$status1.name" // 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: "$status1.name"
);
// イベントハンドリングを開始
var callbackId = domain.Subscribe(
value => {
// 値が変化した時に呼び出される
// value には変更後の値が渡ってくる
}
);
// イベントハンドリングを停止
domain.Unsubscribe(callbackId);
var domain = gs2.StateMachine.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
statusName: "$status1.name"
);
var future = domain.Model();
yield return future;
var item = future.Result;
const auto Domain = Gs2->StateMachine->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Status(
"$status1.name" // 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文字 | ユーザーID | |
status | enum { “Running”, “Wait”, “Pass”, “Error” } | ~ 128文字 | ステータス | ||
pageToken | string | ~ 1024文字 | データの取得を開始する位置を指定するトークン | ||
limit | int | ✓ | 30 | 1 ~ 1000 | データの取得件数 |
status に指定する列挙型の定義
定義 | 説明 |
---|---|
Running | 実行中 |
Wait | 待機中 |
Pass | 終了 |
Error | エラー |
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文字 | ユーザーID | |
statusName | string | ✓ | ~ 36文字 | ステータス名 | |
events | List<EzEvent> | ~ 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: "$status1.name"
);
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: "$status1.name"
);
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.Model();
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(
"$status1.name" // 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();