GS2 States Language フォーマット

はじめに

GS2 States Language(GSL) は独自の構造を持つステートマシン定義言語です。 ステートマシンは一般的に複数の状態を表す Task と、タスク間の遷移を表す Transition によって構成されます。 外部からのメッセージを送信すると、Transition によって定められたルールに基づいて、「実行中の Task」が遷移することで状態管理を行います。

ステートマシンは 「実行中の Task」以外に「状態変数」を持ちます。 Task にはいくつか種類がありますが、一般的には GS2-Script の実行によって処理を記述できます。 GS2-Script は「状態変数」を参照でき、またスクリプトの実行結果として、「状態変数」を書き換えることができます。

(C) Game Server Services Inc. and affiliates.

GSL の仕様の実装および派生仕様は無償で許可します。 ただし、上記コピーライトを派生物に含んでください。 本仕様の派生物をサブライセンスおよび販売を行うことはできません。

本仕様は「現状のまま」提供され、本仕様によって他社の著作権などを侵害していないことを保証するものではありません。 本使用によって生じるあらゆる請求、損害、その他責任についても Game Server Services, Inc. は責任を負わないものとします。

本仕様書に含まれるサンプルコードは特に指定がない限り Apache License, Version 2.0 の下でライセンスされます。

GSL の例

StateMachine MainStateMachine {
  Variables {
    int counter;
  }

  EntryPoint Task1;

  Task Task1(int initCounter) {
    Event StartLoop();
    Event Error(string Reason);

    Payload {
      args.variables.counter = args.params.initCounter
      result = {
          event="StartLoop",
          params={},
          updatedVariables=args.variables
      }
    }
  }

  SubStateMachineTask Task2 {
    using SubStateMachine;
    in (initCounter <- counter);
    out (loopCounter -> counter);
  }

  WaitTask WaitForExternalEvent {
    Event ExternalEvent(int newCounter);
  }

  Task Task3(int newCounter) {
    Event Pass();

    Payload {
      print(args.variables.counter)
      print(args.params.newCounter)
      result = {
          event="Pass",
          params={},
          updatedVariables=args.variables
      }
    }
  }

  PassTask Pass;

  ErrorTask Error(string reason);

  Transition Task1 handling StartLoop -> Task2;
  Transition Task2 handling Pass -> WaitForExternalEvent;
  Transition Task2 handling Error -> Error;
  Transition WaitForExternalEvent handling ExternalEvent -> Task3;
  Transition Task3 handling Pass -> Pass;
}

StateMachine SubStateMachine {
  Variables {
    int currentCounter;
    int loopCounter;
  }

  EntryPoint SubTask1;

  Task SubTask1(int initCounter) {
    Event Pass();
    Event Error(string reason);

    Script grn:gs2:{region}:{ownerId}:script:state-machine-0001:script:SubTask1
  }

  Task SubTask2(int currentCounter) {
    Event IncrementCounter();
    Event Pass();
    Event Error(string reason);

    Script grn:gs2:{region}:{ownerId}:script:state-machine-0001:script:SubTask2
  }

  PassTask Pass;
  ErrorTask Error(string reason);

  Transition SubTask1 handling Pass -> SubTask2;
  Transition SubTask1 handling Error -> Error;
  Transition SubTask2 handling IncrementCounter -> SubTask2;
  Transition SubTask2 handling Pass -> Pass;
  Transition SubTask2 handling Error -> Error;
}

サンプルに対応する GS2-Script 例

SubTask1

args.variables.currentCounter = args.params.initCounter
args.variables.loopCounter = 0
result = {
	event="Pass",
	params={},
	updatedVariables=args.variables
}

SubTask2

args.variables.loopCounter = args.variables.loopCounter + 1
if args.variables.currentCounter < 5 then
	args.variables.currentCounter = args.variables.currentCounter + 1
	result = {
		event="IncrementCounter",
		params={},
		updatedVariables=args.variables
	}
else
	result = {
		event="Pass",
		params={},
		updatedVariables=args.variables
	}
end

言語仕様

StateMachine

StateMachine ${name} {

}

StateMachine ブロックはステートマシンを定義するために使用し、ファイル内に複数記述することができます。 StateMachine は名前をつけることができ、ファイル内で一意である必要があります。

Variables

Variables {
  string ${variableName};
  int ${variableName};
  float ${variableName};
  bool ${variableName};
}

Variables ブロックはステートマシンが持つ状態変数を指定できます。 状態変数は「データ型」と「変数名」によって構成されます。

データ型には以下の種類を指定できます。

名前データ型
string文字列
int64bit符号付き整数値
float64bit浮動小数点数
bool真偽値

EntryPoint

EntryPoint ${taskName};

EntryPoint にはステートマシンを起動した時に最初に遷移するタスクを指定します。

Task

Task は状態を表すノードを定義します。 ノードには用途ごとにいくつかの種類が存在します。

Task

Task ${taskName}(sting ${argumentName}, int ${argumentName}) {
  Event ${eventName}();
  Event Error(string Reason);

  Script ${scriptId}
}

Task ブロックは最も一般的なノードで、GS2-Script のスクリプトを実行します。 Task は名前をつけることができますが、StateMachine 内で一意である必要があります。 ここで定義した名前はタスク間の Transition の指定に使用します。

Task ${taskName}(sting ${argumentName}, int ${argumentName})

Task は引数を受け取ることができます。 引数は なし、または単数、または複数 の指定が可能です。 引数の宣言には「データ型 変数名」を使用し、複数の引数を使用する場合はカンマで区切ります。

Event ${eventName}();

Event はタスクを実行中に受け取るイベントの種類を定義します。Event は複数定義が可能です。 イベントには名前をつけることができ、さらにイベントに付加するパラメーターを指定できます。

Event Error(string Reason);

注意点として、Error(string Reason) というイベントは宣言が必須です。 これはスクリプト内でエラーが発生した時にメッセージを送出することも可能ですが、スクリプトの実行に失敗するなど内部処理でも送出される可能性があります。

Script ${scriptId}

Script はタスクに遷移した時に実行する GS2-Script のスクリプトGRN を指定します。

Payload {
  result = {
      event="Event",
      params={},
      updatedVariables=args.variables
  }
}

Payload はタスクに遷移した時に実行する GS2-Script を直接指定します。

Task は Script または Payload のどちらか片方を実装する必要があります。 同時に記述した場合は Script が採用されます。

SubStateMachineTask

SubStateMachineTask ${taskName} {
  using ${nextStateMachine};
  in (${inputArgumentName} <- ${variableName});
  out (${outputVariableName} -> ${variableName});
}

SubStateMachineTask は別のステートマシンに処理を移す処理を定義します。 nextStateMachine には遷移先のステートマシンの名前を指定します。

in (${inputArgumentName} <- ${variableName});

in には遷移先のステートマシンのエントリーポイントへ渡す引数を指定します。 inputArgumentName にはエントリーポイントで指定したタスクが受け取る引数の名前を指定し、variableName には引数に渡す値を遷移元のステートマシンが持つ状態変数名で指定します。

out (${outputVariableName} -> ${variableName});

out には遷移先のステートマシンが PassTask に遷移した時に受け取るパラメーターを指定します。 outputVariableName には遷移先のステートマシンが持つ状態変数の名前を指定し、variableName には戻ってきた結果を受け取る現在のステートマシンの状態変数の名前を指定します。

WaitTask

WaitTask ${taskName} {
  Event ${eventName}(sting ${argumentName}, int ${argumentName});
}

WaitTask は特に何もしないタスクです。 ただ、外部からのメッセージの送出を待ち受けます。一般的にクライアントで進行するゲームの結果を待つのに使用します。

Event ${eventName}(sting ${argumentName}, int ${argumentName});

Event はタスクを実行中に受け取るイベントの種類を定義します。Event は複数定義が可能です。 イベントには送出を受け付ける名前をつけることができ、さらにイベントに付加するパラメーターを指定できます。

PassTask

PassTask Pass;

PassTask は必須ノードでステートマシンの完了を示すタスクです。 PassTask の名前は Pass である必要があります。

ErrorTask
ErrorTask Error(string reason);

ErrorTask は必須ノードでステートマシンの異常終了を示すタスクです。 ErrorTask の名前は Error である必要があります。

Transition

Transition ${taskName} handling ${eventName} -> ${nextTaskName};

Transition はノード間の遷移を表します。 taskName に遷移元のタスク名を、eventName には受け取ったイベントの種類を、nextTaskName に遷移先のタスク名を指定します。