はじめに
先日公開した GS2-StateMachine のステートマシン定義言語である GSL を各種プログラミング言語から生成する仕組みが CDK に組み込まれました。
機能追加の背景
GSL を設計するにあたって、記述性や可読性が高くなるように設計してきましたが、それでも慣れ親しんだプログラミング言語でステートマシンが定義可能な状況と比較すると大きく開発体験は劣ります。
できるだけ開発者の皆様が慣れ親しんだプログラミング言語で、体験を損なうことなくGSLを記述できるようにすることをコンセプトとして CDK に GSL 定義構文が追加されました。
追加された機能の詳細
ここでは、C# を例に解説しますが、他のプログラミング言語についてもほぼ同じ構文を採用しています。
ステートマシン定義
public class TestStateMachine : Gs2Cdk.Gs2StateMachine.Integration.StateMachineDefinition { public TestStateMachine() { // ここにステート定義を記述 } }
CDK の中に新しく StateMachineDefinition というクラスが追加されており、そのコンストラクタ内でステートマシンを定義します。
StateMachine( "MainStateMachine", // ステートマシンの名前 new IVariable[] { IntType("turn") } // ステートマシンが受け取るパラメーター ) .EntryPoint(task1.Name) // ステートマシンの最初のステート名 .Task( task1, task2, error // ステートの種類 );
新しくステートマシンを定義する構文はこちらです。
ステートマシンの名前や、引数、ステートマシンが管理するステートの一覧とエントリーポイントを指定しています。
ステートには GSL で定義可能な Task, SubStateMachineTask, WaitTask, PassTask, ErrorTask それぞれの定義構文があります。
Task
var task1 = ScriptTask( "Task1", // ステート名 new IVariable[0], // ステートが受け取るパラメーターリスト @" result = 'Pass' " // ステートに遷移したときに実行する Lua スクリプト ) .Result( "Pass", // スクリプトが発行する結果(Pass) new Dictionary<IVariable, string>(), // 次のステートに渡すパラメーター task2.Name // Pass が発行された場合に遷移するステート名 ) .Result( "Error", // スクリプトが発行する結果(Error) new Dictionary<IVariable, string> { { new StringType("reason"), // 次のステートに渡すパラメーターの名前と型 "reason" // パラメーターに渡す Lua 変数名 } }, error.Name // Error が発行された場合に遷移するステート名 );
Task の定義では、ステート名や、ステートに遷移した際に実行するLuaスクリプト、Luaスクリプトが取る引数を指定し
メソッドチェインで、次に遷移するステートに関する情報を Result で指定します。
SubStateMachineTask
var task3 = SubStateMachineTask( "ChoiceSkill", // ステート名 "ChoiceSkill", // 遷移するサブステートマシン名 new InParam[] { InParam( IntType("turn"), // 現在実行中のステートマシンの状態変数名 IntType("turn") // サブステートマシンの最初のステートにパラメーターとして渡す引数名 ) }, new OutParam[] { OutParam( IntType("choiceSkill"), // サブステートマシンから結果として受け取る状態変数名 IntType("choiceSkill") // ブステートマシンから戻ってきたあとのステートにパラメーターとして渡す引数名 ) }, "InGame" // サブステートマシンから戻ってきたあとで遷移するステート名 )
SubStateMachineTask は別のステートマシンに遷移するステートです。関数呼び出しのようなものと思ってください。
サブステートマシンに渡すパラメーターと、サブステートマシンの実行完了後に取り出すパラメーターを指定します。
WaitTask
var task4 = this.WaitTask( "WaitChoiceSkill" // ステート名 ).Result( "ChoiceSkill", // 待ち受けるイベントの名前 new Dictionary<IVariable, string>{{ // 待ち受けるイベントのパラメーター StringType("skill"), // 遷移先のステートに渡すパラメーターの型と名前 "skill" // イベントで受け取るパラメーターの名前 }}, "ChoiceSkill" // このイベントを受け取ったときに遷移するステート名 ).Result( "ReLotterySkill", // 待ち受けるイベントの名前 new Dictionary<IVariable, string>(), // 待ち受けるイベントのパラメーター "ReLotterySkill" // このイベントを受け取ったときに遷移するステート名 )
WaitTask はクライアントからのイベントを待ち受けるステートです。
受け取るイベントの一覧と、イベントから受け取るパラメーター、遷移先のステートを指定します。
PassTask
var task2 = PassTask( "Task2" // ステート名 );
PassTask はステートマシンの正常終了を表すステートです。
ErrorTask
var error = ErrorTask( "Error" // ステート名 );
ErrorTask はステートマシンの異常終了を表すステートです。
CDK の Stack への反映
public class TestStateMachineStack : Stack { public TestStateMachineStack() { new Gs2Cdk.Gs2StateMachine.Model.Namespace( this, "state-machine-0001" ) .StateMachine( new Gs2Cdk.Gs2Script.Model.Namespace( this, "script-0001" ), new TestStateMachine() ); } }
Cdk の Stack 宣言の中で、GS2-StateMachine のネームスペース宣言に StateMachine というメソッドが用意されています。
ここに、ステートマシン宣言で定義した Lua スクリプト をデプロイする GS2-Script のネームスペースと、StateMachineDefinition を渡すことで、GS2-Deploy テンプレートに GS2-StateMachine の StateMachineMaster の宣言と GS2-Script の Script 宣言が追加されます。