って検索した人がこれを見つけますように。
Java Edition 1.21.3時点のお話です。
問題
say reloaded
scoreboard players add $login BOARD 1
/reload
コマンドを打つときは実行されるのに、ワールドを出て入りなおしたときには実行されない!
解決策
function namespace:detect
execute if entity @e[type=!player] run function namespace:enter
execute unless entity @e[type=!player] run schedule function namespace:detect 1t
say reloaded
scoreboard players add $login BOARD 1
これらの関数を作りましょう。namespace
は自身のデータパックフォルダの名前を入れてください。data
フォルダの下にある、minecraft
と同じ場所にあるやつです。
以上で実装は終了です。お疲れ様でした。
挨拶
どうもおはしあ。けいらぎっていいます。今回は最近自分が陥った問題について。reload.
に入れたコマンドのうち、動くものと動かないものがあって困っていました。それについてちょっと考察してみましょう。
原因
あくまで検証と予測の範疇ですが、ワールドを開いた時のコンテンツの配置に順序があると思われます。
順番:ブロック ⇒ reload.mcfunction
⇒ プレイヤー ⇒ その他のエンティティ
世界に入る前、ゲームがエンティティを配置する前にreload.
が実行されています。これはMinecraftのログ(game output)を見るとわかりますが、プレイヤーが世界へ入る前にコマンドが実行されたというログが流れていました。
これ、/scoreboard
の仮想エンティティ($入りの名前)も反応しないのでちょっと面倒です。
対策
つまりはエンティティが読み込まれるまで繰り返し検知させましょう。
... unless entity @e[type=!player] run ...
ifの逆であるunlessを用いて、「エンティティがいなければ実行」という条件を付けてループさせます。検知対象が@e[type=!player]
なのは、他のエンティティよりプレイヤーの読み込みの方がちょっと早いからですね。「プレイヤーだけ検知できれば良い」というときは@a
で良いと思います。
... run schedule function namespace:detect 1t
以降の文で、この関数を1tick後に予約しておきましょう。これでエンティティが読み込まれるまで検知され続けます。
/schedule
について
/schedule function <関数のファイル> <時間> [append|replace]
指定した時間に、関数を予約しておくことができるコマンドです。<時間>
の数字と文字から、実行したい時間を細かく指定できます。
単位 | 意味 | 時間 |
---|---|---|
1t | tick | 1/20秒 |
1s | second | 1秒 |
1d | day | 20分 |
[append|replace]
は、同じ関数を複数予約したときの挙動が変わります。append
は予約した分だけ順番に実行されますが、replace
は最後に予約した一回で他の予約が上書きされます。何も入力しなければreplace
となります。
注意点
予約した関数は、ワールド全体として実行されます。つまり@p
を使うと違う方向からの指定になり、~ ~ ~
を使えば実行座標は行方不明です。どこなんだよここは...
なので予約した関数の中では、execute at
やpositioned
を使って実行場所を指定してあげましょう。
また、ワールドを出ると予約していた関数は消滅します。reload
で再予約する必要がありますね。
追記:/reload
や/schedule
の実行位置は初期スポーン地点とのことでした。情報ありがとうございます!
終わり
てことで今回はreload
とエンティティの関係についてでした。
質問や改善点などあればお気軽にどうぞ!できれば優しく、フランクな感じで。
自分の苦労が誰かの助けになれば幸いです。
それでは、ご覧いただきありがとうございました。
おつなも!