はじめに
mcfunctionでの条件分岐は主にexecute ifを用います。
特にエンティティに関する条件分岐として、エンティティの状態を条件として用いるexecute if entity、スコアボードの値を条件として用いるexecute if socreがあり、両方比較的カジュアルに使える条件式です。
また条件分岐ではありませんが、execute as @e[...]を用いてコマンドの実行者をfilterすることでelseのない条件分岐のような振る舞いをすることが出来ます。
この記事ではexecute if entity @s[type=...]を用いて、特定のfunctionを実行したのは誰かで条件分岐を記述する方法について紹介します。
この記事で紹介する方法はver 1.21.4で実装/検証済みです
最新版(ver 1.21.11)では未検証ですがコマンドの中でも比較的ロバストな要素を使用していると思うので問題なく動作すると思います
背景
プレイヤーが自由に召喚/削除できるGUIを構築したいと思ったときに、あらゆるケースでプレイヤーが召喚したGUIを削除出来ずワールドに残り続ける可能性が懸念されました。
そのためGUIから一定距離プレイヤーが離れれば自動的に削除される方針で実装しました。
実装
GUIの具体的な実装が主題ではないのである程度文脈が伝わる程度に省略しています。
GUIの構成
今回はカスタムフォントを用いてデザインに自由度を持たせたかったのでテキストディスプレイを用いています。クリック検知はインタラクションです。
基本的な機能としてプレイヤーが最後まで操作を完了するとGUI本来の機能の処理が走ると同時にGUIの削除が実行されます。
またGUIの削除の処理はkill_display.mcfunctionにまとめて記述します。
## 【実行者:player】execute on targetで実行者をプレイヤーに移して実行
execute as @e[type=interaction,tag=gui_interaction] store success entity @s interaction.player[] int 0 on target run function gui:kill_display
一方でGUIからプレイヤーが離れたときに自動的に削除されるようにするためには実行者をテキストディスプレイにしtickで検知することになります。
## 【実行者:text_display】GUIの半径10以内にプレイヤーがいない場合に実行
execute as @e[type=text_display,tag=gui_textdisplay] at @s unless entity @p[distance=..10] run function gui:kill_display
このようにkill_display.mcfunctionをプレイヤーが実行する場合とテキストディスプレイが実行する場合が存在します。
実行者が複数パターンある場合でもセレクターの書き方を工夫すればkill_display.mcfunctionの実行者を検知する必要はないですが、今回は明確に特定の実行者がmcfunctionを実行した場合実行させたくないコマンドが存在するため実行者の検知を行う必要があります。
mcfunctionの実行者で分岐させる
mcfunctionの実行者は@sで検知することが出来ます。
また実行者はエンティティであるためexecute if entityを用いた条件分岐を使用することができ、セレクターと組み合わせることで実行者@sのtypeが〇〇ならという条件を指定することが出来ます。
## @s[type=player]なら実行しない
execute if entity @s[type=!player] run tellraw @n[type=player] [{"text": "[!] 処理は完了していません"}]
これでkill_display.mcfunctionの実行者がプレイヤーなら実行されず、プレイヤー以外なら(つまり処理が最後まで完了しない状態でプレイヤーが半径10以内から出た場合)実行される処理を記述することが出来ました。
さいごに
やっていること自体はかなりシンプルですが、@s[type=...]でfilterしexecute if entityと組み合わせることで条件分岐に組み込めるというのが個人的に面白かったので記事にしました。
@e[type=...]や@n[type=...]はよく見るけど意外と@s[...]にtypeの指定をすることは少ないのではないでしょうか。是非活用してみてください。
参考
制作にあたり多くの記事からアイデアを頂戴しました
偉大な先人達に感謝