右クリックしたブロックの座標を知りたい！！！！！(前編: item_used_on_block)

# これは何？
この記事は Minecraft Command Advent Calendar 2023 11 日目の記事です。

他にも素晴らしい記事がたくさんあるので、是非是非

https://qiita.com/advent-calendar/2023/mccmd

# はじめに
皆さんは、minecraftでプレイヤーがブロックに対して右クリックした時に、ブロックの座標位置を知りたくありませんか？


この記事は、コマンド初心者なりにブロックの座標位置を取得する方法を調べ、色々試した記録です。
きっと素晴らしいクラフターの方々が「こうするといいよ」とコメントをくれると信じています。

# 何をしたいか
「プレイヤーが `#{ブロック}` に対して、`#{右クリック}` した時、そのされた `#{ブロック}` の座標を取得し、処理を走らせる」

例えば、

「プレイヤーが `#{オークの木材}` に対して、`#{茶色の染料を持って右クリック}` した時、その `#{オークの木材}` の座標を取得しダークオークの木材に変える。」

と言ったものですね。

実際はチェストに対して行い、チェストに追加機能を設ける機能を作成したいのですが、今回の記事はこちらを目標に据えて色々試していきたいと思います。

## もっと問題を整理する
「プレイヤーが#{オークの木材}に対して、#{茶色の染料を持って右クリック}した時、その#{オークの木材}の座標を取得しダークオークの木材に変える。」

これはコマンドの視点だと、

1. プレイヤーが茶色の染料をメインハンドに持っていることを判定
1. プレイヤーがオークの木材に手の届く範囲の時、右クリックをおこなう。
1. 2の右クリックを検知し、目の前にあるオークの木材の座標を取得する

という3つの段階に分かれていると思います。

今回の記事は前編ということで、1, 2について整理していきましょう。

# 方針

~~茶色の染料は右クリックに処理のないアイテムだから、透明な村人の右クリック検知して、プレイヤーの向いている方向にアーマースタンドtpさせて……~~


あれ、これ`advancement`の`item_used_on_block`でできないかな？


# `advancement`の`item_used_on_block`って？

minecraft内の言葉の`進捗`のことです。
その進捗をカスタマイズするためのトリガーはたくさんあり、例えば「アイテムを消費した`minecraft:consume_item`」「ブロックを設置した`minecraft:placed_block`」と言ったものがあります。

今回はその中でも、「プレイヤーが手かアイテムをブロックに使用したときにトリガーされる`minecraft:item_used_on_block`」を試してみましょう。

# やること
やることは
1. データパックを作成する
1. 進捗の情報をカスタマイズしてjsonにする
1. 進捗を達成した時に動かすfunctionを作成する

## データパックを作成する。
説明は省略しますが、下記のファイル構成で作成していきます。

```
./ # データパック名
├── README.md
├── data
│   └── test
│       ├── advancements
│       │   └── used_item.json # カスタム進捗の情報
│       └── functions
│           └── used_item.mcfunction # カスタム進捗達成した時に呼び出すfunction
└── pack.mcmeta
```

## 進捗の情報をカスタマイズしてjsonにする
`data/test/advanvements/used_item.json`を作成し、進捗の情報を記入します。

カスタム進捗は、下記のジェネレーターで作成した方が楽でした。
作者さんに感謝です :pray:

https://misode.github.io/advancement/

作成したjsonファイルがこちらです。

`minecraft:item_used_on_block`は
- 使用する`item`: `location`の`minecraft:match_tool`コンディション
- 対象の`block`: `location`の`minecraft:block_state_property`コンディション

で指定するようでした。

まずは確実に動くものを見たいので、`item`を`豚の生肉`に、`block`を焚き火にしています。

```js:used_item.json
{
  "criteria": {
    "requirement": {
      "trigger": "minecraft:item_used_on_block",
      "conditions": {
        "player": [],
        "location": [
          {
            "condition": "minecraft:match_tool",
            "predicate": {
              "items": [
                "minecraft:porkchop"
              ]
            }
          },
          {
            "condition": "minecraft:block_state_property",
            "block": "minecraft:campfire",
            "properties": {}
          }
        ]
      }
    }
  },
  "rewards": {
    "function": "test:used_item"
  }
}

```

`item_used_on_block`の`item`, `block`の指定方法はは1.20くらいで変わっているのでお気をつけください。
参考にしたサイト

https://minecraft.fandom.com/ja/wiki/Java_Edition_23w18a

# 進捗を達成した時に動かすfunctionを作成する
進捗を達成した時に呼び出すコマンドを作成しましょう。

先ほど作成した`used_item.json`の`rewards`で指定しているfunctionのことですね。

```
title @s title "アイテムを使った"
advancement revoke @s only test:used_item
```

進捗を達成した後すぐrevokeすることで、再度進捗を達成できます。
フラグ管理をまとめられるadvancementのいいところですよね

# 動かしてみよう
先のコードをコピペすると下記になります。
右クリックをトリガーにtitleが呼び出されていますね。

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357479/f556b6ca-1e66-8eb7-1996-d8f84330a7c4.gif)

# では右クリックできないものに対しては…？
「オークの木材に茶色の染料」や、「シフト押しながらチェストを右クリック」などが当てはまります。


## 進捗のjsonを変更する
生の豚肉を茶色の染料に、焚き火をオークの木材に変更します
 
 ```js:used_item.json
{
  "criteria": {
    "requirement": {
      "trigger": "minecraft:item_used_on_block",
      "conditions": {
        "player": [],
        "location": [
          {
            "condition": "minecraft:match_tool",
            "predicate": {
              "items": [
                "minecraft:brown_dye" // 変更
              ]
            }
          },
          {
            "condition": "minecraft:block_state_property",
            "block": "minecraft:oak_planks",   // 変更
            "properties": {}
          }
        ]
      }
    }
  },
  "rewards": {
    "function": "test:used_item"
  }
}

```
## 結果
ﾄﾞｷﾄﾞｷ……

![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357479/acf6545a-52b5-f384-30e1-d3d7f2615066.gif)

無理でした

# 結論
頑張って右クリック検知して、アーマスタンドを投げて対象のブロックに当たるまで進ませた方が良さそうです。

## 副産物

色々試していて気づいたのですが。オークの木材もitemとして検知できるようですね。

どういうことかというと、
オークの木材にオークの木材を使う。つまり、隣接してブロックを置くことも検知できるようでした。

![ezgif.com-video-to-gif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357479/2b9246f1-1c49-238a-c673-67ae8208cbe5.gif)

これは何かで使えそうですね。

```
{
  "criteria": {
    "requirement": {
      "trigger": "minecraft:item_used_on_block",
      "conditions": {
        "player": [
        ],
        "location": [
          {
            "condition": "minecraft:match_tool",
            "predicate": {
              "items": [
                "minecraft:oak_planks"
              ]
            }
          },
          {
            "condition": "minecraft:block_state_property",
            "block": "minecraft:oak_planks",
            "properties": {}
          }
        ]
      }
    }
  },
  "rewards": {
    "function": "test:eat_apple"
  }
}
```



# 最後に
時間が足りず、肝心の「本来右クリックできないブロックにアイテムを持って右クリックする」方法が書けていないため、後編に書きます(いつの日か)

右クリックできるブロックとアイテムの場合であれば、この記事でどうにかなりそうです。

ここまで読んでくださりありがとうございました :bow: