Minecraft testコマンドの説明

この記事では[Minecraft Java Edition](https://www.minecraft.net/ja-jp)におけるtestコマンドについて説明します。[公式Wiki](https://minecraft.fandom.com/wiki/Minecraft_Wiki)には2022/11/13現在testコマンドについての記事は無いようです。

<>で表される引数は必須です。\[\]で表される引数は任意です。

`/test <required argument> [optional argument]`

# テストした環境

* Minecraft 1.19.2
    * Minecraft Forge 1.19.2-43.1.52
```
> ./gradlew --version

------------------------------------------------------------
Gradle 7.5.1
------------------------------------------------------------

Build time:   2022-08-05 21:17:56 UTC
Revision:     d1daa0cbf1a0103000b71484e1dbfe096e095918

Kotlin:       1.6.21
Groovy:       3.0.10
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.4.1 (Eclipse Adoptium 17.0.4.1+1)
OS:           Windows 10 10.0 amd64
```

この記事では`./gradlew runClient`を実行して起動したMinecraftで`/test`の実行をしています。Minecraftの言語は英語にしているので，日本語環境では画面内の位置を参考にして読み替えてください。

# testコマンドとは

MinecraftのGame Testを実行，補助するためのコマンドです。Game Testは実際のワールドを使用して動作の確認や自動テストを行う機構です。ユーザーよりも開発者向けの機能と考えられます。

以下のサブコマンドが存在します。

- [clearAll](#clearall-radius)
- [create](#create-test-name-width-height-depth)
- [export](#export-test-name)
- [exportThis](#exportthis)
- [import](#import)
- [pos](#pos-var)
- [run](#run-like)

Minecraft Launcherから起動できるMinecraftでは実行できません。`/test`は主に開発環境から実行するコマンドです。

# `clearall [radius]`

半径(radius, default=200)内にあるすべてのテストの構造体を消します。

`/test clearall`

# `create <test name> [width] [height] [depth]`

与えられた名前の新しいテスト構造体を作成します。test nameには":"を含むことができないため，namespaceはminecraftとなります。ただ，Game Testにはnamespaceは関係ないためnamespaceは無視します。構造体の大きさはデフォルトで(5, 5, 5)です。
![2022-11-13_13.48.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/3b219e32-fb97-7c15-f4bd-6c523018863b.png)
この構造体は`/test create te`で作成したものです。
コマンドブロックには`/test runthis`のコマンドが入っています。ストラクチャーブロックには"minecraft:\<test name\>"の名前が入っており，保存する準備の整った状態になります。
磨かれた安山岩の上にテストしたい構造を作り，ストラクチャーブロックで保存します。

:::note info
\[0, 0, 0\]の場所はストラクチャーブロックの位置を指します。安山岩のy座標は1となります。
\[0, 0, 0\]を置き換えるとストラクチャーブロックが消えてしまいます。
:::

ストラクチャーブロックを右クリックしてGUIを開くと右下にSAVEのボタンがあります(Cancelの上)。
![2022-11-13_19.35.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/34e85859-8f34-6174-d362-412d7048795e.png)
そこをクリックすると`saves/(world name)/generated/minecraft`に`nbt`ファイルが保存されます。この例では`te.nbt`が作成されます。`nbt`ファイルはバイナリファイルで，メモ帳などでは中身を見れません。VS CodeやIntellij IDEAの拡張機能に中身を確認できるものがあるようです。

## `create <test name> [width]`

(width, width, width)の大きさのテスト構造体を作成します。

## `create <test name> [width] [height] [depth]`

(width, height, depth)の大きさのテスト構造体を作成します。

# `export <test name>`

ストラクチャーブロックで作成した`nbt`ファイルをGame Testで使用する`snbt`ファイルに変換します。
`nbt`ファイルが存在しないとエラーになります。
変換されたファイルは`gameteststructures`に保存されます。

`snbt`ファイルは`nbt`ファイルと違い人間の読み書きできる形式です。jsoncに似たフォーマットを採用しています。
```jsonc
{
    DataVersion: 3120,
    size: [2, 2, 2],
    data: [
        {pos: [0, 0, 0], state: "minecraft:polished_andesite"},
        {pos: [0, 0, 1], state: "minecraft:polished_andesite"},
        {pos: [1, 0, 0], state: "minecraft:polished_andesite"},
        {pos: [1, 0, 1], state: "minecraft:polished_andesite"},
        {pos: [0, 1, 0], state: "minecraft:air"},
        {pos: [0, 1, 1], state: "minecraft:air"},
        {pos: [1, 1, 0], state: "minecraft:air"},
        {pos: [1, 1, 1], state: "minecraft:air"}
    ],
    entities: [],
    palette: [
        "minecraft:polished_andesite",
        "minecraft:air"
    ]
}
```

# `exportthis`

プレイヤーに一番近いテスト構造体をexportします。最も近いストラクチャーブロックの内容に基づいて出力するようです。`nbt`ファイルが存在しないとエラーになります。

# `import`

`snbt`ファイルを`nbt`ファイルに変換します。`nbt`ファイルに変換するとストラクチャーブロックで読み込みできるようになります。`snbt`ファイルを編集したい際に使用すると思われます。

# `pos [var]`

プレイヤーの視線上にあるブロックの，ストラクチャーブロックからの相対位置を取得します。
![2022-11-13_19.45.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/00d11e78-a6c1-dc9f-aa4d-345fa11eff24.png)
tでチャット欄を開き，緑色の座標をクリックするとJavaでの座標の定義をコピーできます。引数のvarはここでの変数名になります。
`/test pos basePos`と実行すると以下のコードがコピーできます。
```java
final BlockPos basePos = new BlockPos(2, 3, 2);
```

# Run like

ここではGame Testを実行するコマンド群について簡単に紹介します。実際には`run`か`runall`あたりしか使われないと思います。

テストにはコードとテスト構造体の2つが必要です。コードにはどのように動作させ，どの状態が期待されるかを記述します。Java EditionではJavaのコードです。この記事では書き方などは触れません。

## `run <test name> [rotation steps]`

引数の名前のテストを実行します。
rotation stepsはどの角度回転させるかのパラメータです。
| rotation step | Rotation |
| -- | -- |
| 0 | None |
| 1 | CLOCKWISE_90 |
| 2 | CLOCKWISE_180 |
| 3 | COUNTERCLOCKWISE_90 |
| Other | Throw error |

## `runall [rotation steps] [test per row]`

すべてのテストを実行します。
rotation stepsはrunと同様のパラメータです。test per rowは1列にいくつのテストを実行するかです(default=8)。

その他にも`runfailed`, `runthese`, `runthis`といったコマンドがあります。

# 1からの`snbt`ファイルの作成手順

ここでは"dispenser_place_water"をテストの名前とします。

1. `/test create dispenser_place_water`を実行します。
![2022-11-13_15.45.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/73e0a35f-bdf5-2f04-9777-6bf3141d64a6.png)
![2022-11-13_15.46.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/06bd8bf5-7ad9-2e04-5da2-abbcd5a36ac7.png)
2. ディスペンサーを置き，その中に水の入ったバケツを入れます。(2, 3のステップでは必要に応じて置くブロックを変えてください)
3. このようにブロックを置きます。ディスペンサーの前に3か所ブロック，ディスペンサーの上にボタンを置きました。
![2022-11-13_15.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/d561c908-42fa-858c-644a-390a257ea9b4.png)
4. ストラクチャーブロックのGUIを開き，右下の"SAVE"をクリックします。
![2022-11-13_15.48.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2966051/b02af784-9115-ac90-0da6-a9cd6dbf20c7.png)
これで`saves/(world name)/generated/minecraft/dispenser_place_water.nbt`が保存されます。
5. `/test export dispenser_place_water`か`/test exportthis`を実行します。
6. `snbt`ファイルが`gameteststructures/dispenser_place_water.snbt`として保存されます。このファイルとテストコードでテストが実行できます。

# 参考
- https://github.com/MinecraftForge/MinecraftForge