導入
貴方はMinecraftというゲームをご存じでしょうか。まぁあの神ゲーを知らないという方、そうそういないと思います。
さて、この記事では、特定のアイテムを持った状態で右クリックしたこと(アイテム使用したこと)を検知する方法と、そこからFormを表示する方法を記していきたいと思います。
特定のアイテムを持って右クリックしたことを検知する
なにかしらアイテムを持った状態で右クリックしたことは、world.events.beforeItemUseを使うことによって検知できます。beforeItemUseという部分からわかる通り、アイテム使用から右クリックを検知しているので、PEの場合は画面長押しによってイベントが発生します。使用したアイテムの種類は、beforeItemUseEvent Classのitemから、typeIdやnameTag,dataを用いて条件分岐することで調べます。
import { world } from "@minecraft/server";
//リンゴを持った状態で右クリックするとキルされる
world.events.beforeItemUse.subscribe((ev)=>{
if(ev.item.typeId != "minecraft:apple") return;
ev.source.kill();
});
右クリックしたプレイヤーにformを表示する
上記のサンプルコードの通り、右クリックしたプレイヤーはsourceで取得することができます。form.show()の実引数にsourceを指定すれば、右クリックしたプレイヤーにformを表示させることが可能です。
import { world } from "@minecraft/server";
import { ActionFormData } form "@minecraft/server-ui";
const form = new ActionFormData().title("a").body("b").button("c");
world.events.beforeItemUse((ev)=>{
form.show(ev.source);
});
注意すべきなのは、sourceで取得したインスタンスがEntity型だということです。そのため、Player.tell()など、Player型なら使えるいくつかのメゾットが使用できません。もしPlayer型でしか実装されていないメゾットを使いたい場合、Entity型からPlayer型に変換する必要があります。しかし、Javascriptではオブジェクト型のキャストはできないため、変換する機構を自分で実装する必要があります。
具体的には、world.getPlayers()で得たプレイヤー一覧から、sourceと同一人物を探します。
function entityToPlayer(source){
for(let player of world.getPlayers({"nameTag":source.nameTag})){
return player;
}
}
最後に
この記事を書こうと思ったとき、一番書きたかったのは「form.show()の実引数がEnittyだと表示されないから、アイテム使用検知からのform表示の際には、sourceの型に注意してね。」ということだったのですが、記事の内容が正しいかどうかを調べるために検証していたら、アップデートだかなんだかでEntity型のままでも正しく表示されるようになっていたため、情報の鮮度は大事だなと改めて思った次第です。アンテナしっかり張らないとですね。