[Java]MinecraftのModを作成しよう 1.16.1【ブロックの追加】

（この記事は一連の解説記事の一つになります）

先頭記事：[入門編](https://qiita.com/koteko/items/8d32c8819e3f9e6a333a)
前の記事：[アイテムの追加](https://qiita.com/koteko/items/578c3cfdfd7ef71df9c1)
次の記事：

# ブロックの追加
ブロックの追加をします。1.14.4のときと少し書き方を変えました(バージョンアップによって実装の方法が変わったという意味ではないです)。

## ブロックの登録

```
\src\main\java\jp\koteko\liveinwater\
   ├ block
   │   └ Blocks.java
   ├ item
   └ LiveInWater.java
```

```java:Blocks.java
package jp.koteko.liveinwater.block;

import jp.koteko.liveinwater.LiveInWater;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import java.util.ArrayList;
import java.util.List;

@Mod.EventBusSubscriber(modid = LiveInWater.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Blocks {
    public static List<Block> blockList = new ArrayList<Block>();
    public static Block WATERTREE_ROOT_BLOCK = register("watertree_root_block", new Block(AbstractBlock.Properties.create(Material.WOOD).hardnessAndResistance(2.5F).sound(SoundType.WOOD)));

    private static Block register(String key, Block blockIn){
        blockList.add(blockIn);
        return blockIn.setRegistryName(LiveInWater.MOD_ID, key);
    }

    @SubscribeEvent
    public static void registerBlocks(RegistryEvent.Register<Block> event) {
        for (Block block : blockList) {
            event.getRegistry().register(block);
        }
    }
}

```
[前回](https://qiita.com/koteko/items/578c3cfdfd7ef71df9c1)のアイテム登録と同様のことをブロックについて行います。
宣言・初期化と同時に`List`にアイテムを追加し、forループでリストのアイテムをすべて`register()`します。
単なる無機能ブロックの場合`Block`クラスのインスタンスとします。コンストラクタの引数には`AbstractBlock.Properties`のインスタンスを与えます。

## アイテムの登録

```
\src\main\java\jp\koteko\liveinwater\
   ├ block
   ├ item
   │   └ Items.java
   └ LiveInWater.java
```

```java:Items.java
package jp.koteko.liveinwater.item;

import jp.koteko.liveinwater.LiveInWater;
import jp.koteko.liveinwater.block.Blocks;
import net.minecraft.block.Block;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import java.util.ArrayList;
import java.util.List;

@Mod.EventBusSubscriber(modid = LiveInWater.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Items {
    public static List<Item> itemList = new ArrayList<Item>();
    public static final Item WATERTREE_ROOT = register("watertree_root", new Item((new Item.Properties()).group(ItemGroup.MATERIALS)));
    public static final Item WATERTREE_ROOT_BLOCK = register("watertree_root_block", Blocks.WATERTREE_ROOT_BLOCK, ItemGroup.BUILDING_BLOCKS);

    private static Item register(String key, Item itemIn) {
        itemList.add(itemIn);
        return itemIn.setRegistryName(LiveInWater.MOD_ID, key);
    }
    private static Item register(String key, Block blockIn, ItemGroup itemGroupIn) {
        return register(key, new BlockItem(blockIn, (new Item.Properties()).group(itemGroupIn)));
    }

    @SubscribeEvent
    public static void registerItems(RegistryEvent.Register<Item> event) {
        for (Item item : itemList) {
            event.getRegistry().register(item);
        }
    }
}
```
ブロックは同時にアイテムとしても存在するので、アイテムも登録します。
`register`メソッドをオーバーロード(異なる引数による同名メソッドの定義)してブロックアイテムの登録が行いやすいようにしました。登録名、ブロック、アイテムグループを渡すと、中でグループを設定した`BlockItem`をつくり、アイテムの`register`に投げるようにします。
`BlockItem`は`Item`のサブクラスで、アイテムとしてのブロックはこのクラスのインスタンスとします。

## resourcesの設定

```
\src\main\resources
   └ assets
      └ liveinwater
         ├ blockstates
         │  └ watertree_root_block.json
         ├ lang
         │  └ en_us.json
         │  └ ja_jp.json
         ├ models
         │  ├ block
         │  │  └ watertree_root_block.json
         │  └ item
         │     └ watertree_root_block.json
         └ textures
            ├ block
            │  └ watertree_root_block.png
            └ item
```

```json:lang\en_us.json
{
  "item.liveinwater.watertree_root_block": "WaterTree Root"
}
```

```json:lang\ja_jp.json
{
  "item.liveinwater.watertree_root_block": "ウォーターツリーの根"
}
```

```json:blockstates\watertree_root_block.json
{
  "variants": {
    "": { "model": "liveinwater:block/watertree_root_block" }
  }
}
```
`"model": "[MOD_ID]/[モデルファイルのパス]"`
ブロックの状態によってモデルを変えるような場合(たとえば、方向を持つブロックや、フェンスなどの連結するブロック)にはこのファイルを編集しますが、不要な場合このような形です。

```json:models\block\watertree_root_block.json
{
  "parent": "block/cube_all",
  "textures": {
    "all": "liveinwater:block/watertree_root_block"
  }
}
```
`[MOD_ID]:[テクスチャファイルのパス]`
`parent`は`block/cube_all`を指定します。
これは単純な立方体のモデルで、全面に同じテクスチャを反映します。

```json:models\item\watertree_root_block.json
{
  "parent": "liveinwater:block/watertree_root_block"
}
```
ブロックアイテムは`parent`にブロックのモデルファイルを指定すればよいです。


**watertree_root_block.png**
テクスチャを作成し、配置します。


## ルートテーブルの設定
Minecraft 1.9以降ではドロップを管理する仕組みとしてルートテーブルが導入されました。ブロックのドロップもこれを使って設定します。

```
\src\main\resources
   ├ assets
   └ data
      └ liveinwater
         └ loot_tables
            └ blocks
               └ watertree_root_block.json
```
[前の記事](https://qiita.com/koteko/items/6560128ebd320f2727ab)で用意しておいた`data\liveinwater`フォルダ内に`blocks\watertree_root_block.json`を配置します。

```json:watertree_root_block.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "conditions": [
        {
          "condition": "minecraft:match_tool",
          "predicate": {
            "enchantments": [
              {
                "enchantment": "minecraft:silk_touch",
                "levels": {
                  "min": 1
                }
              }
            ]
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "liveinwater:watertree_root_block"
        }
      ]
    },
    {
      "rolls": 1,
      "conditions": [
        {
          "condition": "minecraft:inverted",
          "term": {
            "condition": "minecraft:match_tool",
            "predicate": {
              "enchantments": [
                {
                  "enchantment": "minecraft:silk_touch",
                  "levels": {
                    "min": 1
                  }
                }
              ]
            }
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "functions": [
            {
              "function": "minecraft:apply_bonus",
              "enchantment": "minecraft:fortune",
              "formula": "minecraft:binomial_with_bonus_count",
              "parameters": {
                "extra": 3,
                "probability": 0.5714286
              }
            }
          ],
          "name": "liveinwater:watertree_root"
        }
      ]
    },
    {
      "rolls": 1,
      "conditions": [
        {
          "condition": "minecraft:inverted",
          "term": {
            "condition": "minecraft:match_tool",
            "predicate": {
              "enchantments": [
                {
                  "enchantment": "minecraft:silk_touch",
                  "levels": {
                    "min": 1
                  }
                }
              ]
            }
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:dirt"
        }
      ]
    }
  ]
}
```
「シルクタッチのツールで破壊した場合ブロックそのもの(`watertree_root_block`)を、それ以外の場合は土ブロック(`dirt`)1つとアイテム(`watertree_root`)をランダム個ドロップする」という例です。詳しい説明は参考ページに譲ります。
（色々と試しましたが重複する記述があり冗長な書き方である可能性があります。）

<details><summary>最小の構成はこのようになります。</summary><div>

```json:ブロック自身をドロップする最小構成のルートテーブル
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "[MOD_ID]:[ITEM_NAME]"
        }
      ]
    }
  ]
}
```

`type`は何に関するルートテーブルかを選択する。`pools`に与えた各プールが順次適応され、`rolls`回の抽選によって`entries`に与えた各エントリーから結果が選ばれる。エントリーで`type`の`name`を返すと指定。

</div></details>

## 確認
ゲームを起動して確認します。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256627/bd6fb54d-263b-f1d3-dab7-aa52b71daf40.png)
ブロックとそのアイテムの追加ができていること、表示が正しいこと、シルクタッチでブロックそのもの・非シルクタッチで土とアイテムがドロップすることが確認できました。


# 参考
[[Java]MinecraftのModを作成しよう 1.14.4【2. ブロックの追加】](https://qiita.com/koteko/items/c904b3bfdd90f0b9a98a)
[Minecraft 1.14.4 Forge Modの作成 その4 【ブロックの追加】](https://qiita.com/Hiroya_W/items/5b14f397bc52ce87255f)
[ルートテーブル - Minecraft Wiki](https://minecraft-ja.gamepedia.com/%E3%83%AB%E3%83%BC%E3%83%88%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB)
[loot_tables_1.14.md · GitHub](https://gist.github.com/misode/66456e57372ce62cd9b65d1052521069)



# 次の記事