【マインクラフト】コマンド上級者はみんな知ってるダイナミックなシュルカーボックスでコンテナを上書きするやつ【Command Advent Calendar 2024】

[Minecraft Command Advent Calendar 2024](https://qiita.com/advent-calendar/2024/mccmd) Series 2 Day 1 (2024/12/1)

---
# 1. はじめまして
クロスプです。どこかで活動していない人です。
今回はシュルカーボックスを使った簡単にコンテナを上書きする方法を紹介します。

# 2. シュルカーボックスで何が出来るの？
はい、ここにあるシュルカーボックス、今は何も出来ません。

![cmdshulker_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/6a232da7-4c81-ce12-0ed7-be0c404279a1.png)

今回このシュルカーボックスにアクセントを入れます。
シュルカーボックスのルートテーブルに**とある機能**を追加します。

:::note warn
- ノーマルシュルカーボックス以外も使えますが、コード内のshulker_boxも書き換える必要があったり、いろんな方々のデータパックでも使われることがあるので、ノーマルシュルカーボックスを推奨します。
- アップデートでたまに構文が変わります。以下に1.20.5~1.21.3、1.17~1.20.4、1.13~1.16版がありますのでアップデートでの構文の変更点も知っておきましょう。
:::


<details open><summary>1.20.5~1.21.3</summary>

```json #namespace:minecraft:blocks/shulker_box.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:dynamic",
              "name": "minecraft:contents",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "items": [
                      "minecraft:debug_stick"
                    ]
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "functions": [
                {
                  "function": "minecraft:copy_components",
                  "include": [
                    "minecraft:custom_name",
                    "minecraft:container",
                    "minecraft:lock",
                    "minecraft:container_loot"
                  ],
                  "source": "block_entity"
                }
              ],
              "name": "minecraft:shulker_box",
              "conditions": [
                {
                  "condition": "minecraft:inverted",
                  "term": {
                    "condition": "minecraft:match_tool",
                    "predicate": {
                      "items": [
                        "minecraft:debug_stick"
                      ]
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
```

:::note info
ランダムシーケンス消しています！あっても動作には全く影響しません！
:::


</details>

<details><summary>1.17~1.20.4</summary>

```json #namespace:minecraft:blocks/shulker_box.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:dynamic",
              "name": "minecraft:contents",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "items": [
                      "minecraft:debug_stick"
                    ]
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "name": "minecraft:shulker_box",
              "functions": [
                {
                  "function": "minecraft:copy_name",
                  "source": "block_entity"
                },
                {
                  "function": "minecraft:copy_nbt",
                  "source": "block_entity",
                  "ops": [
                    {
                      "source": "Lock",
                      "target": "BlockEntityTag.Lock",
                      "op": "replace"
                    },
                    {
                      "source": "LootTable",
                      "target": "BlockEntityTag.LootTable",
                      "op": "replace"
                    },
                    {
                      "source": "LootTableSeed",
                      "target": "BlockEntityTag.LootTableSeed",
                      "op": "replace"
                    }
                  ]
                },
                {
                  "function": "minecraft:set_contents",
                  "type": "minecraft:shulker_box",
                  "entries": [
                    {
                      "type": "minecraft:dynamic",
                      "name": "minecraft:contents"
                    }
                  ]
                }
              ],
              "conditions": [
                {
                  "condition": "minecraft:inverted",
                  "term": {
                    "condition": "minecraft:match_tool",
                    "predicate": {
                      "items": [
                        "minecraft:debug_stick"
                      ]
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
```

:::note info
ランダムシーケンス消しています！あっても動作には全く影響しません！
:::


</details>

<details><summary>1.13~1.16.5</summary>

```json #namespace:minecraft:blocks/shulker_box.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:dynamic",
              "name": "minecraft:contents",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "item": "minecraft:debug_stick"
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "name": "minecraft:shulker_box",
              "functions": [
                {
                  "function": "minecraft:copy_name",
                  "source": "block_entity"
                },
                {
                  "function": "minecraft:copy_nbt",
                  "source": "block_entity",
                  "ops": [
                    {
                      "source": "Lock",
                      "target": "BlockEntityTag.Lock",
                      "op": "replace"
                    },
                    {
                      "source": "LootTable",
                      "target": "BlockEntityTag.LootTable",
                      "op": "replace"
                    },
                    {
                      "source": "LootTableSeed",
                      "target": "BlockEntityTag.LootTableSeed",
                      "op": "replace"
                    }
                  ]
                },
                {
                  "function": "minecraft:set_contents",
                  "type": "minecraft:shulker_box",
                  "entries": [
                    {
                      "type": "minecraft:dynamic",
                      "name": "minecraft:contents"
                    }
                  ]
                }
              ],
              "conditions": [
                {
                  "condition": "minecraft:inverted",
                  "term": {
                    "condition": "minecraft:match_tool",
                    "predicate": {
                      "item": "minecraft:debug_stick"
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
```


</details>

さて、このコードは説明するより実際に実行した方が早いので、簡潔に紹介します。

まず、適当なデータパックをつくってminecraft:blocks/shulker_box.jsonに上の構文をコピペします。

次に、入れたワールドにシュルカーボックスを設置します。

その後、適当にアイテムをいれます。

![cmdshulker_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/f0636a3c-3719-5f5d-0dc4-83ad5675c4aa.png)

この後に、/lootコマンドを使用します。

```
/loot give @s mine <シュルカーボックスの座標: x y z> minecraft:debug_stick
```

上のコマンドは座標のブロックを採取、つまりシュルカーボックスを採取したように自分に入手するコマンドです。
ただ最後にデバッグ棒をいれていることから、サバイバルでデバッグ棒で破壊していることになります。

デバッグ棒にしているのは、サバイバルでデバッグ棒でブロックを破壊出来ないからです。

![cmdshulker_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/ff296dbf-438d-2fd1-140f-39f9ee4807fd.png)

※ちゃんと出来なかった。

この特性を利用して、デバッグ棒で破壊している時だけのシュルカーボックスのドロップアイテムを変更しました。
この状態で上記のコマンドを実行すると、

![cmdshulker_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/2e493d7d-06e9-7a80-2f60-e6fe7ebd87a1.png)

自分の手元(画像はサブ垢)にシュルカーボックスに入れたアイテムが順番通りに一気に手に入ります。

![cmdshulker_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/32cff274-cda4-c94f-647d-2fdb8cb2308c.png)

これで、シュルカーボックスにアイテムを入れるとプレイヤーに一度に与える事が出来るようになりました。

# 3. インベントリをいじれる！？
そして、今回は/lootコマンドで変更しています。先ほどはgiveを使用していましたが、insertやreplace、spawnも使うことが可能です。

この中のreplaceを使うと、複数のコンテナを一度に変更する事が可能です。
言葉で表すより実際にやったほうが早いので下記のコマンドをやってみましょう！

```
/loot replace entity @s inventory.0 27 mine <シュルカーボックスの座標: x y z> minecraft:debug_stick
```

lootコマンドとitemコマンドの違いとして、コンテナの後に数値を入れることがlootコマンドでは可能となり、ここを27に変更するとインベントリを一度に変更できます。

![cmdshulker_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/9166745f-4dce-be4e-9ec5-cc713164ebac.png)

このコマンドを実行するとシュルカーボックスの27スロット全てそのままインベントリに上書きされます。

![cmdshulker_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/c011816f-47bb-eccd-58a3-b6a44f10a821.png)

たったの数コマンドで、実質的にずっと

# 4. この機能の応用
これは実は最近のライブラリや配布マップにも見かけることが多々あります。
まずこの機能のメリットを紹介します。
- プレイヤーを直接操作していないので、渡す前に/dataで操作する事が出来る。
ストレージとの相性が良くなる。
- コマンド数が少なくなる。
処理が軽くなる。
- マルチプレイ対応がしやすい。

次にデメリットを紹介します。
- ディメンションが違うとバグる事がある。
(座標にシュルカーボックスがない可能性がある)
- 違うディメンションにあるブロック同士のコンテナが1コマンドで制御出来ない。
対処法として、全てのディメンションにシュルカーボックスを設置しなければならない。
- プレイヤーのインベントリのスロットは0~35、-106(オフハンド)、101~104(防具)である。
シュルカーボックスのSlotは0~26までしかないので、ストレージに移動するとき一度Slot値を変換しないといけない。ここに追加でホットバーとインベントリを分けるのが超大変。

なお、大体の人は座標[0, 0, 0]にフォースロードをかけてシュルカーボックスを設置している方が多いです。
自分はひねくれているので[1, 1, 1]に置いています(どうでもいい)。

# おまけ
今日12/1は投稿主の誕生日なので勝手に自己紹介します。

クロスプ(クロミウムスープ)です。
どこかで活動していない人です。

普段はPaperサーバー/Bukkitプラグインとデータパック/リソースパックを使った自由なコマンドをしています。

現在やっていることはインベントリ内でスマートフォンのUIをデータパックでつくったりしていて、こちらにSkriptを使用してクリエイティブでもUIを操作しやすいように調整している人です。

スマートフォンを持って設置する(実は中身コマンドブロック)と、ブロックが出てきます。

![cmdshulker_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/80c35769-2f03-7522-fb40-f19aee5f889d.png)

このブロックはリソースパックで見た目を変えており、元のブロックは上下付き石化したオークのハーフブロックです。

![cmdshulker_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/7b41baf0-f3fc-ae8c-e876-7086b82623cd.png)

こちらのブロックをスマートフォンで右クリックすると、

![cmdshulker_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897459/73579183-5a6c-137d-2a46-0f30e3ddaea8.png)

勿論このシステムにもダイナミックシュルカーボックスも使っています。
といってもスマートフォンから切り換えたときに元のアイテムを読み込むときだけなんだけどね…

ダイナミックシュルカーボックスはストレージと組み合わせると凄く便利なので、皆さんも覚えましょう！

それではまたどこかでお会いしましょう、バイバイ！

この記事の内容/コード全ては[Minecraftエンドユーザー使用許諾契約](https://aka.ms/MinecraftEULA)の範囲内の中で
あなたが自由に使用して頂いて構いません。