メインコンテンツまでスキップ

変数と定数を使ってみる

変数と定数を使って, 冗長な記述を減らしたり, 臨機応変なシナリオを作成しましょう。


概要

このチュートリアルでは, 定数機能変数機能の使い方にを学びます。

これを完了すると, シナリオの作成において冗長な記述を減らして, より効率的に記述できるようになります。
さらに, シナリオの実行時に, 変数の値を変更することで, シナリオの対象を変更したり, 挙動を変更できるようになります。

定数機能を使ってみる

定数機能 を使うと, 自分で自由に定義した定数をシナリオ内の任意の場所で参照でできます。 同じ記述を複数回書く必要がある場合に, 効果的に使えます。

シチュエーションの例

私のプラグイン「More Rewards」 について考えます。
このプラグインは, プレイヤが敵を倒したときに, 特別な木の棒「One Punch Stick」がドロップします。 この棒で敵をヒットすると, 敵を一撃で倒せます。

この機能テストのために, 後述の前提となるシナリオを作成しました。 このシナリオ内では, 木の棒に関する同じような記述が複数回登場します。
これらのような冗長なコードを減らすために, 定数機能を使ってみましょう。

ステップ1. 前提となるシナリオを作成する

まずは, 前提となるかんたんなシナリオを作成しましょう。

これについての実践的なチュートリアルは, 以下のドキュメントを参照してください。

今回はあらかじめ用意しておいたシナリオを使います。

giving-more-reward-on-kill-test.yml
# このシナリオでは, プレイヤが敵を倒したときに, 特別な木の棒「One Punch Stick」を与えられるかどうかをテストします。
scenamatica: "0.0.1"
name: "give-more-reward-on-kill-test"

on:
# プラグインが読み込まれたときに実行する。
- type: on_load

context:
actors:
- name: Actor001
- name: Actor002

scenario:
# プレイヤに敵を倒させる。
- type: execute
action: player_death
with:
target: Actor002
killer: Actor001
# プレイヤが One Punch Stick を拾うまで待つ。
- type: expect
action: entity_pickup_item
with:
target: Actor001
item:
type: stick
name: One Punch Stick
lores:
- "You can kill everyone with one punch!"
timeout: 100
# プレイヤに One Punch Stick を持たせる。
- type: execute
action: player_hotbar
with:
target: Actor001
item:
type: stick
name: One Punch Stick
lores:
- "You can kill everyone with one punch!"
# プレイヤが敵を殴る。
- type: execute
action: entity_damage_by_entity
with:
target: Actor002
damager:
name: Actor001
inventory:
mainHandItem:
type: stick
name: One Punch Stick
lores:
- "You can kill everyone with one punch!"
# プレイヤが敵を倒す。
- type: expect
action: entity_death
with:
target: Actor002

ステップ2. 定数にする項目を考える

このシナリオでは, 以下のような全く同じ記述が複数回登場します。

type: stick
name: One Punch Stick
lores:
- "You can kill everyone with one punch!"

これはどのようなアイテムであるかを説明するものであり, つまるところ同一のアイテムを指しています。
このような冗長な記述は極力減らされるべきでありますので, これを定数にしましょう。

ステップ3. 定数を定義する

定数を定義するには, まず definitions というキーをシナリオのルートに追加します。
その中に, 任意の名前の定数キーを追加し, その値として任意の型の値(今回はオブジェクト型のアイテム)を指定します。

以下の例では, one_punch_stick という名前の定数を定義しています。

giving-more-reward-on-kill-test.yml
# このシナリオでは, プレイヤが敵を倒したときに, 特別な木の棒「One Punch Stick」を与えられるかどうかをテストします。
scenamatica: "0.0.1"
name: "give-more-reward-on-kill-test"

on:
# プラグインが読み込まれたときに実行する。
- type: on_load

context:
actors:
- name: Actor001
- name: Actor002

definitions:
# 定数を定義する。
# アイテム「One Punch Stick」を定数する。
one_punch_stick:
type: stick
name: One Punch Stick
lores:
- "You can kill everyone with one punch!"

scenario:
# ...

ステップ4. 定数を参照する

変数を定義しただけでは, まだ何も変わりません。変数を参照して, 冗長な記述を減らしましょう。

変数を参照するには, 参照したいオブジェクトの同じ階層に $ref キーを追加します。 値には定義名(今回の場合は one_punch_stick)を指定します。

これを行うと, 以下のように定数が参照されます。

giving-more-reward-on-kill-test.yml
# ...
scenario:
# プレイヤに敵を倒させる。
- type: execute
action: player_death
with:
target: Actor002
killer: Actor001
# プレイヤが One Punch Stick を拾うまで待つ。
- type: expect
action: entity_pickup_item
with:
target: Actor001
item:
$ref: one_punch_stick
timeout: 100
# プレイヤに One Punch Stick を持たせる。
- type: execute
action: player_hotbar
with:
target: Actor001
item:
$ref: one_punch_stick
# プレイヤが敵を殴る。
- type: execute
action: entity_damage_by_entity
with:
target: Actor002
damager:
name: Actor001
inventory:
mainHandItem:
$ref: one_punch_stick
# プレイヤが敵を倒す。
- type: expect
action: entity_death
with:
target: Actor002

ステップ5. 動作を確認する

実際にシナリオを実行してみましょう。
プラグインをビルドし, サーバを再起動します。

# サーバを再起動する場合
$ java -jar <サーバのjarファイル名>.jar

# 再読込する場合
$ reload confirm

シナリオが実行され正常に終了したことを確認したら, 定数機能に関するチュートリアルは終了です。お疲れ様でした。

他の応用的なチュートリアルを読むにはこちらを参照してください。
シナリオファイルの完全な構文についてはこちらを参照してください。

変数を使ってみる

変数機能 を使うと, シナリオの実行結果や状態に応じた臨機応変なシナリオを作成できます。

シチュエーションの例

前章で例示したシチュエーションをさらに複雑にしてみましょう。

上長からの仕様変更の依頼が発生しました。
プレイヤが敵を倒したときに, 追加でプレイヤの位置のブロックを溶岩ブロックに置換するように変更してほしいとのことです。 また, ブロックの設置にはBlockPlaceEvent を発火させる必要があるそうです。

さて, この仕様変更事項をひとまず実装してみました。
この変更のテストのために, 追加のシナリオを作成しましょう。

この機能テストのために, 後述の前提となるシナリオを作成しました。 このシナリオ内では, プレイヤの位置とブロックの位置を固定化して指定しています。 しかし, このままでは, プレイヤの位置とブロックの位置が常に同じになってしまい, 柔軟性がありません。

これを解決するために, 変数機能を使ってブロックの位置を動的に指定してみましょう。

ステップ1. 前提となるシナリオを作成する

まずは, 前提となるかんたんなシナリオを作成しましょう。

これについての実践的なチュートリアルは, 以下のドキュメントを参照してください。

今回はあらかじめ用意しておいたシナリオを使います。

placing-diamond-block-on-kill-test.yml
# このシナリオでは, プレイヤが敵を倒したときに, プレイヤの真下のブロックを溶岩ブロックに置換されるかどうかをテストします。
scenamatica: "0.0.1"
name: "placing-lava-block-on-kill-test"

context:
actors:
- name: Actor001
- name: Actor002
location:
x: 0
y: 4
z: 0
stage:
type: FLAT

scenario:
# プレイヤに敵を倒させる。
- type: execute
action: player_death
with:
target: Actor002
killer: Actor001
- type: expect
action: block_place
with:
# プレイヤの位置のブロックが溶岩ブロックに置換されることを期待する。
location:
# プレイヤの座標を指定する。
x: 0
y: 3
z: 0
block:
type: lava

ステップ2. 変数を使う項目を考える

このシナリオでは, 溶岩の場所である {x: 0, y: 3, z: 0} をハードコーディングしています。 しかしこのままでは, プレイヤの位置が変わったときに, ブロックの位置を手動で変更する必要があります。

これでは柔軟性がありません。ここで, 変数機能の出番です!
変数機能を利用して, プレイヤの位置を動的に指定してみましょう。

ステップ3. 使う変数を探す

このドキュメントには, 使用できるすべての変数が記載されています。
これを参考に, 仕様すべき変数を探しましょう。

今回は, 前のシナリオからキルされたプレイヤを取得する必要があります。
そのため。 scenario.scenario.0.output.target.location という変数を使うことにします。

変数の階層説明
scenario自分自身を含むシナリオ(ファイル)を表す変数
scenario.scenarioシナリオファイル内のシナリオを表す変数
scenario.scenario.0シナリオファイル内のシナリオのうち, インデックス 0 のシナリオを表す変数
scenario.scenario.0.outputシナリオの出力を表す変数
scenario.scenario.0.output.targetシナリオの出力のうち, target を表す変数
ヒント

各シナリオの出力は, そのアクションの出力と同じです。

ステップ4. 変数を参照する

変数を参照するには, 参照したいオブジェクトの値として ${変数名} を指定します。 今回の場合では, scenario.scenario.0.output.target.location を参照するために, with.location の値として ${scenario.scenario.0.output.target.location} を指定します。

placing-lava-block-on-kill-test.yml
# ...
scenario:
# プレイヤに敵を倒させる。
- type: execute
action: player_death
with:
target: Actor002
killer: Actor001
- type: expect
action: block_place
with:
# プレイヤの位置のブロックが溶岩ブロックに置換されることを期待する。
location: "${scenario.scenario.0.output.target.location}"
block:
type: lava
インデックスを使用せずに出力を参照する

シナリオの指定にインデックスを使用する代わりに, シナリオに一意な名前をつけられます。
以下のようにしてシナリオに名前をつけましょう。参照するときはインデックスの代わりに名前を使います。

placing-lava-block-on-kill-test.yml
# ...
scenario:
# プレイヤに敵を倒させる。
- type: execute
action: player_death
with:
target: Actor002
killer: Actor001
name: "kill_actor002"
- type: expect
action: block_place
with:
# プレイヤの位置のブロックが溶岩ブロックに置換されることを期待する。
location: "${scenario.scenario.kill_actor002.output.target.location}"
block:
type: lava

ステップ5. 動作を確認する

実際にシナリオを実行してみましょう。

# サーバを再起動する場合
$ java -jar <サーバのjarファイル名>.jar

# 再読込する場合
$ reload confirm

シナリオが実行され正常に終了したことを確認したら, 変数機能に関するチュートリアルは終了です。お疲れ様でした。

他の応用的なチュートリアルを読むにはこちらを参照してください。 シナリオファイルの完全な構文についてはこちらを参照してください。