【マインクラフト（統合版）】ルートテーブル（Loot Table）の書き方まとめ（トレードアイテム編）

# はじめに

ここでは職業を持った村人とのアイテム取引を定義するためのルートテーブル（Loot Table）の書き方をご紹介します。

基本的な書き方は以下のページでご紹介していますのでそちらをご覧ください。

https://qiita.com/glasses_seven/items/f0e745f9715e6ac34560/

:::note info
ルートテーブルの記述はJSON形式なのでJSONの仕様を理解している前提で話を進めます。
:::


# ファイル構成

バニラのビヘイビアパック内でのファイル構成は以下のようになっています。

:::note info
以下の`economy_trades`フォルダ配下の部分が今回対象にしているファイルです。
:::

```text:トレードテーブルのフォルダ構成
/<ビヘイビアパックのルート>
    /trading
        armorer_trades.json
        butcher_trades.json
        cartographer_trades.json
        cleric_trades.json
        farmer_trades.json
        fisherman_trades.json
        fletcher_trades.json
        leather_worker_trades.json
        librarian_trades.json
        shepherd_trades.json
        stone_mason_trades.json
        tool_smith_trades.json
        weapon_smith_trades.json

        /economy_trades
            armorer_trades.json             防具鍛冶
            butcher_trades.json             肉屋
            cartographer_trades.json        製図家
            cleric_trades.json              聖職者
            farmer_trades.json              農民
            fisherman_trades.json           釣り人
            fletcher_trades.json            矢師
            leather_worker_trades.json      革細工師
            librarian_trades.json           司書
            shepherd_trades.json            羊飼い
            stone_mason_trades.json         石工
            tool_smith_trades.json          道具鍛冶
            wandering_trader_trades.json    行商人
            weapon_smith_trades.json        武器鍛冶
```

このうち`trading`配下のものと`economy_trades`配下のものとに大きく分かれていて`wandering_trader_trades.json`ファイルの有無に違いがあります。

`wandering_trader_trades.json`は行商人のトレードテーブルを定義するためのファイルですが、行商人は比較的新しいバージョンで導入されたエンティティなので`economy_trades`配下のものが新しい定義である事が伺えます。

念のため`trading`配下のファイルを変更して試してみましたが現在のバージョン（確認時は1.21.73）では反映されなかった為、下位互換のため残されているものと思われます。

というわけで、ここでは`economy_trades`配下のファイルを見ていきます。


# 定義ファイルの概要

定義内容はまず行商人とそれ以外に大きく分かれます。
それぞれのファイル内でのレイアウトは以下の通りです。

### 「行商人」用の定義

:::note info
以下`tiers`と`groups`の定義ブロックは固定だとお考えください。
:::

```json:JSON定義のレイアウト
{
    "tiers": [
        {
            "groups": [
                {
                    "num_to_select": 5,
                    "trades": [
                        <トレード項目の定義>
                    ]
                },
                {
                    "num_to_select": 1,
                    "trades": [
                        <トレード項目の定義>
                    ]
                }
            ]
        }
    ]
}
```

`groups`の項目が２つの定義ブロックに分かれています。

画面上では以下のピンク色の枠で示した部分で分かれています。

![行商人との取引画面](https://socket-manager.github.io/document/minecraft-contents/img/loot-table-trade/wandering_trader.png "行商人との取引画面")

それぞれの`num_to_select`の数値はトレード項目の数を表していて、定義できる最大値ではなく、`trades`項目内で定義されているトレード項目のうち`num_to_select`の件数分選出する事を表しています。

つまり<トレード項目の定義>の部分は、選出候補として`num_to_select`の件数を超えて定義する事ができます。

### 「行商人」以外の定義

:::note info
以下`tiers`の定義ブロックは固定だとお考えください。
:::

```json:JSON定義のレイアウト
{
    "tiers": [
        {   // レベル１（新米）
            "total_exp_required": 0,
            "groups": [
                {
                    "num_to_select": <職業やレベルに応じた数値>,
                    "trades": [
                        <トレード項目の定義>
                    ]
                }
            ]
        },
        {   // レベル２（見習い）
            "total_exp_required": 10,
            "groups": [
                {
                    "num_to_select": <職業やレベルに応じた数値>,
                    "trades": [
                        <トレード項目の定義>
                    ]
                }
            ]
        },
        {   // レベル３（一人前）
            "total_exp_required": 70,
            "groups": [
                {
                    "num_to_select": <職業やレベルに応じた数値>,
                    "trades": [
                        <トレード項目の定義>
                    ]
                }
            ]
        },
        {   // レベル４（熟練者）
            "total_exp_required": 150,
            "groups": [
                {
                    "num_to_select": <職業やレベルに応じた数値>,
                    "trades": [
                        <トレード項目の定義>
                    ]
                }
            ]
        },
        {   // レベル５（達人）
            "total_exp_required": 250,
            "groups": [
                {
                    "num_to_select": <職業やレベルに応じた数値>,
                    "trades": [
                        <トレード項目の定義>
                    ]
                }
            ]
        }
    ]
}
```

上のレイアウトは村人の各職業でほぼ共通です。

`tiers`の項目が５つの定義ブロックに分かれているのは、職業別のレベル項目（一番の上の項目がレベル１で下に向かってレベルが上がっていく配置）と一致しているからで、全ての職業で最大５レベルまである事を表しています。

各レベルで定義されている`total_exp_required`の数値は村人が次のレベルアップに必要な経験値を表しています。

あとの構成は行商人の場合と同じですが、`groups`の要素数が各々の職業やレベルに応じて異なります。

### groupsの項目について

例外として以下のような`groups`要素が存在しない職業である「石工」の定義がありますが、このファイルには`num_to_select`の項目も存在しないので、複数のトレード項目から採用する項目を選定したい場合に限り`groups`要素を使うようです。

:::note info
以下`tiers`の定義ブロックは固定だとお考えください。
:::

```json:JSON定義のレイアウト
{
    "tiers": [
        {   // レベル１（新米）
            "total_exp_required": 0,
            "trades": [
                {
                    <トレード項目の定義１つ目>
                },
                {
                    <トレード項目の定義２つ目>
                }
            ]
        },
        {   // レベル２（見習い）
            "total_exp_required": 10,
            "trades": [
                {
                    <トレード項目の定義１つ目>
                },
                {
                    <トレード項目の定義２つ目>
                }
            ]
        },
        {   // レベル３（一人前）
            "total_exp_required": 70,
            "trades": [
                {
                    <トレード項目の定義１つ目>
                },
                {
                    <トレード項目の定義２つ目>
                }
            ]
        },
        {   // レベル４（熟練者）
            "total_exp_required": 150,
            "trades": [
                {
                    <トレード項目の定義１つ目>
                },
                {
                    <トレード項目の定義２つ目>
                }
            ]
        },
        {   // レベル５（達人）
            "total_exp_required": 250,
            "trades": [
                {
                    <トレード項目の定義１つ目>
                }
            ]
        }
    ]
}
```

これを画面で表すと以下のようになります。

![石工の取引画面](https://socket-manager.github.io/document/minecraft-contents/img/loot-table-trade/stone_mason.png "石工の取引画面")

画面上ではレベル２までしか見えていませんが、各レベル毎にトレード項目が固定で２件ずつ表示されていることがわかります。


# trades項目内で設定できる内容

この部分は行商人も含めて共通の内容になります。

```json:trades定義項目のオーソドックスな例
"trades": [
    {
        "wants": [
            {
                "item": "minecraft:emerald",
                "quantity": 3,
                "price_multiplier": 0.2
            },
            {
                "item": "minecraft:diamond",
                "quantity": 1,
                "price_multiplier": 0.2
            }
        ],
        "gives": [
            {
                "item": "minecraft:fishing_rod",
                "quantity": 1,
                "functions": [
                    {
                        "function": "enchant_with_levels",
                        "treasure": false,
                        "levels": {
                            "min": 5,
                            "max": 19
                        }
                    }
                ]
            }
        ],
        "trader_exp": 10,
        "max_uses": 3,
        "reward_exp": true
    }
]
```

<br />
<dl>
    <dt>・wants</dt>
    <dd>
        この要素は最大２件まで定義でき、トレードの対象アイテムを指定します。<br /><br />
        <dl>
            <dt>item</dt>
            <dd>
                トレードの対象アイテムを指定します。<br /><br />
            </dd>
            <dt>quantity</dt>
            <dd>トレードの対象アイテムの数量を指定します。<br /><br /></dd>
            <dt>price_multiplier</dt>
            <dd>
                以前はトレードの対象アイテムの価格調整係数として機能していたようですが、現在は機能していないようです。<br />
            </dd>
        </dl>
        <br />
    </dd>
    <dt>・gives</dt>
    <dd>
        この要素は最大１件まで定義でき、トレードの結果得られるアイテムを指定します。<br /><br />
        <dl>
            <dt>item</dt>
            <dd>
                トレードの結果得られるアイテムを指定します。<br /><br />
            </dd>
            <dt>quantity</dt>
            <dd>アイテムの数量を指定します。<br /><br /></dd>
            <dt>functions</dt>
            <dd>
                アイテムに関数を適用する場合に指定します。<br />
                ここではエンチャントを付与する関数を指定していますが、<a href="https://qiita.com/glasses_seven/items/f0e745f9715e6ac34560/">&gt;&gt; ルートテーブルの書き方</a>でご紹介したような関数が使用できます。<br />
            </dd>
        </dl>
        <br />
    </dd>
    <dt>・trader_exp</dt>
    <dd>
        トレードを行った際に村人が得られる経験値を指定します。<br />
        ここでは<code>10</code>と指定しているので、トレードを行う度に村人は<code>10</code>の経験値を得る事になります。<br /><br />
    </dd>
    <dt>・max_uses</dt>
    <dd>
        トレードの最大使用回数を指定します。<br />
        ここでは<code>3</code>と指定しているので、トレードを行うと<code>3</code>回までトレードが可能になります。<br />
        例え３回トレードを行ったとしても、村人の職業が変わったり村のイベントが発生したりすると、<code>max_uses</code>の回数はリセットされます。<br /><br />
    </dd>
    <dt>・reward_exp</dt>
    <dd>
        トレードを行った際にプレイヤーが経験値を得られるかどうかを指定します。<br />
        ここでは<code>true</code>と指定しているので、トレードを行う度にプレイヤーは経験値を得る事になります。<br />
        <code>false</code>と指定すると、トレードを行っても経験値は得られません。<br />
        得られる経験値は<code>trader_exp</code>で指定した数値に比例しているようです。<br />
    </dd>
</dl><br />

`wants`定義のアイテムを２件登録した場合、画面には以下のピンク色の枠囲いのように表示されます。

![渡すアイテムが２つ必要な場合](https://socket-manager.github.io/document/minecraft-contents/img/loot-table-trade/2slot.png "渡すアイテムが２つ必要な場合")

```json:trades定義項目でchoice項目を使った例
"trades": [
    {
        "wants": [
            {
                "choice" : [
                    {
                        "item": "minecraft:emerald",
                        "quantity": 3,
                        "price_multiplier": 0.2
                    },
                    {
                        "item": "minecraft:diamond",
                        "quantity": 1,
                        "price_multiplier": 0.2
                    }
                ]
            }
        ],
        "gives": [
            {
                "choice" : [
                    {
                        "item": "minecraft:fishing_rod",
                        "quantity": 1
                    },
                    {
                        "item": "minecraft:diamond_sword",
                        "quantity": 1
                    }
                ]
            }
        ],
        "trader_exp": 10,
        "max_uses": 3,
        "reward_exp": true
    }
]
```

この場合、`choice`の要素を使う事でトレードの対象アイテムを選択できるようになります。

`wants`項目の場合は、エメラルドとダイヤモンドのどちらかが選ばれ、`gives`項目の場合は、釣り竿とダイヤモンドのどちらかが選ばれます。


# おわりに

以前ご紹介した以下の環境で、実装例としてのアイテムを登録しています。

https://qiita.com/glasses_seven/items/433ac9d9fcbdb72c6d18/

## 登録しているアイテムの内訳

### ・武器鍛冶師と取引できるアイテム

👇ファンネルユニットの構成要素である「サイコフレーム」

https://qiita.com/glasses_seven/items/129d40545884750e4e78/

👇ホバーユニットの構成要素である「Ｅパック」

https://qiita.com/glasses_seven/items/690f46f3ac6181d91ebc/

👇「エヴォーカーファングの杖」

https://qiita.com/glasses_seven/items/fa09b1f4ef3779dd692d/

### ・行商人と取引できるアイテム

👇ホバーユニットの構成要素である「Ｎジャマー」

https://qiita.com/glasses_seven/items/690f46f3ac6181d91ebc/