【マインクラフト】多分めっちゃスマートなアイテム検知【データパック】(1.20.2)

データパック作る時にめちゃめちゃよく書くコマンドが「アイテム検知」ですよね。みんなこんな書き方してませんか?

execute as @a if @s[nbt={SelectedItem:{tag:{display:{Name:"\"つよい剣\"",Lore:["\"つよい\""]}}}}] run ~

これ、すごい負荷もかかるし、ごちゃっとしてるし、何よりスマートじゃありません!

今回は、後から名前など変更を加える際にも役立つNBTの書き方と、それを応用したアイテム識別についてまとめます。

ちなみに中級者以上向けです!




おおまかな仕組みの解説

今回使用するバージョンは1.20.2です。

仕組みをざっくり説明すると、"アイテムに識別IDを持たせて、それをpredicateファイルと比較し、一致したらコマンドを実行する"という形です。
本当にこれだけで結構汎用も効くし、後からの変更もしやすいのでとても良い…。


アイテム識別の作り方

今回は「プレイヤーがオリジナルアイテムを持っていたらジャンプ力を上げる」というケースを書きますが、汎用は効くので似たような事をしたい人も是非!

実際につくってみよう~~~

1. ストレージに識別ID (UID) を入れておく

dataコマンドに存在する「ストレージ」という機能を使っていきます。

今回はストレージ "test" に "UID" という変数を作成、変数"UID"に「1」を代入していきます。

data modify storage test UID set value [1]

この数値が後にアイテムに持たせたりする数値です。リスト型である理由は後ほど。


2. オリジナルアイテムにUIDをコピーする

アイテムにデータを持たせる方法は複数ありますが、個人的オススメは「アイテムを与えるfunctionファイルを作っておき、その中でnbtを付与していく」タイプです。
今回は鉄の剣を使ってコマンドを書いていきます。

では実際にアイテムを与えるfunctionファイルの例を~~~

# generatorを設置
summon armor_stand ~ ~ ~ {Tags:["item_generator"],Invisible:true,NoGravity:true,Marker:true}

# アイテムを持たせる
item replace entity @e[tag=item_generator] weapon.mainhand with iron_sword

# 使用するUIDをセット
data modify storage test UID_setter set from storage test UID[0]

# UIDを付与する
item modify entity @e[tag=item_generator] weapon.mainhand main:uid_set

# 受け取り用アイテムを召喚
summon item ~ ~ ~ {PickupDelay:1,Item:{id:"minecraft:iron_sword",Count:1b}}

# データのコピー
data modify entity @e[type=item,nbt={Item:{id:"minecraft:iron_sword"}},sort=nearest,limit=1] Item.tag set from entity @e[tag=item_generator,limit=1] HandItems[].tag

# generatorをキル
kill @e[tag=item_generator]

透明で当たり判定のないアーマースタンドを召喚して、そのアーマースタンドにアイテムを持たせてデータを書き込んでいくスタイルです。
こうしないとitem modifyを使ってNBTのコピーができないので、確実だけど力技な感じです。

コマンドを実行したプレイヤーが受け取るアイテムは、「アーマースタンドが構築したアイテムのデータをコピーしたアイテムを拾っている」状態になります。

ここで、タグ "UID" の中身を一度 "UID_setter" へコピーしているのは、複数のアイテムを作成する際に設定したい数値を取り出し、同じモディファイヤーファイルを使いまわして設定するためです。
そのためにタグ "UID" はリスト型になっています。

もう一つ大事なのが、コード内にある"UIDを付与する"の部分にある「main:uid_set」のファイル作成。こちらはjsonファイル。
こちらはほぼコピペでOK。

[
    {
      "function": "minecraft:copy_nbt",
      "source": {
        "type": "minecraft:storage",
        "source": "minecraft:test"
      },
      "ops": [
        {
          "source": "UID_setter",
          "target": "ItemUID",
          "op": "replace"
        }
      ]
    }
  ]
  

ストレージ "test" の "UID_setter"のデータを、ItemUIDという名前でコピーしています。
行先はアイテムの"tag"の中です。(ここはプログラムの"データのコピー部分"で、Item.tagとかHandItems[].tagで指定してる部分)

ここまで完成すれば、後はfunctionを実行するだけで、ユニークID付きのアイテムを生成できます。


3. 検知してみよう

ここからはアイテムを持っている人検知のパート。
今回は手に持ったアイテムの識別IDを照合していくコマンドで解説していきます。

まずpredicateファイルを一つ作成!

{
    "condition": "minecraft:entity_properties",
    "entity": "this",
    "predicate": {
      "equipment": {
        "mainhand": {
          "nbt": "{ItemUID:1}"
        }
      }
    }
  }

中身は「メインハンドに "ItemUIDが1"のアイテムを持っている」ことを検知するjsonファイルです。
残念ながら僕の知る限りではItemUIDの数値をストレージから参照する方法はないので、数値を指定してあげる必要があります。


これを実行するTickファイルも作成します

# アイテム検知
execute as @a at @s if predicate main:1_uid run function main:effect/effect_1

内容は立ったこれだけ!しかも軽い!

あとはエフェクト付与するファイルを作成するだけ。

# エフェクト付与
summon area_effect_cloud ~ ~0.5 ~ {Duration:6,Age:4,effects:[{id:"minecraft:jump_boost",amplifier:3b,duration:6,show_particles:0b}]}

これでアイテム検知コマンドの完成です。


このアイテム検知方法のメリット

最後にこんな事を書く事ではないと思いますが、このアイテム検知方法には複数のメリットがあります。

  1. あとからアイテムに変更を加えたい場合の作業量が少ない
    ターゲットセレクタにnbtを書く場合、なぜか完全一致でしか検知されない仕様とは違く、今回のコマンド方法では“ItemUID”というタグが一致していれば、「名前や説明文、アイテム名などは変更しても検知される」のです!

  2. 軽い
    負荷かとにかく軽い!Tickファイルなどで常時実行する場合はこの書き方が本当におすすめです。

  3. 汎用性の高さ
    アイテム名や名前が違っていても、同じタグさえ持っていれば同じアイテムとして扱えることや、同じアイテムでも、タグさえ違っていれば別のアイテムとして検知できるなど、ポテンシャルがとても高いこともメリットの1つです。


最後に & サンプル配布!

初note投稿で慣れていなく、見やすい記事ではないかもしれません…。
今後もコマンド関連の備忘録などを投稿する予定なので、よかったらフォローお願いします~~~

今回解説したコマンドを含んだサンプルデータパックを配布しておきます!ぜひご活用を!
ダウンロードした際は、同梱されている "readme.md" をご確認ください。

ではまた!


いいなと思ったら応援しよう!