[Java]MinecraftのModを作成しよう 1.14.4【9. 木の追加と生成】

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

先頭記事：[入門編](https://qiita.com/koteko/items/7afadf8261eac49bacad)
前の記事：[8. 鉱石の追加と生成](https://qiita.com/koteko/items/f17d723337ddf7d5dbd4)
次の記事：[99. Modの出力](https://qiita.com/koteko/items/cbcfe448def02c3413b9)

# 木の追加
[前記事](https://qiita.com/koteko/items/f17d723337ddf7d5dbd4)では鉱石の追加について学びました。次は木を追加し、ワールドに生成させてみましょう。だいぶ複雑になってきますので、一緒に頑張っていきましょう。

## 原木の追加
まず木を構成する原木ブロックを追加します。[2. ブロックの追加](https://qiita.com/koteko/items/c904b3bfdd90f0b9a98a)を参考にブロックを追加していきますが、ところどころ異なる点があるので順にみていきましょう。

```java:BlockList.java
//...
public class BlockList {
    public static Block ExampleLog = new LogBlock(
            MaterialColor.CYAN,
            Block.Properties.create(Material.WOOD, MaterialColor.BLUE)
                    .hardnessAndResistance(2.0F)
                    .sound(SoundType.WOOD)
                    .lightValue(6))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_log"));

    @SubscribeEvent
    public static void registerBlocks(RegistryEvent.Register<Block> event) {
        event.getRegistry().registerAll(
                ExampleLog
        );
    }

    @SubscribeEvent
    public static void registerBlockItems(RegistryEvent.Register<Item> event) {
        event.getRegistry().registerAll(
                new BlockItem(ExampleLog, new Item.Properties().group(ExampleItemGroup.DEFAULT))
                        .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_log"))
        );
    }
}
```
基本的には同じですが、単なる`Block`クラスではなく、`LogBlock`クラスでつくります。
これは`Block`クラスのサブクラス`RotatedPillarBlock`のサブクラスです。`RotatedPillarBlock`は`Block`に回転に関するものを追加したものです。そして`LogBlock`ではさらにマップ上での表示に関するものを追加しているようです。
コンストラクタの引数は1番目に一つ増えて、`MaterialColor`クラスでマップ上で表示する色を渡します。`Block.Properties.create()`の方でも引数が増えて色を渡していますが、これは非垂直設置時のマップ上の色で、先程のほうが垂直設置時の色になるようです。これらは適当に選びましょう。
___
例のごとく`resources`の設定をしていきますが、原木ブロックは面によってテクスチャが異なるため、この設定を以下に示します。これらはminecraftの原木ブロックを参考にしているので特別なことをしない限りこれでよいです。

```
\src\main\resources
   ├ assets
   │  └ example_mod
   │     ├ blockstates
   │     │  └ example_log.json
   │     ├ lang
   │     │  └ en_us.json
   │     │  └ ja_jp.json
   │     ├ models
   │     │  ├ block
   │     │  │  └ example_log.json
   │     │  └ item
   │     │     └ example_log.json
   │     └ textures
   │        ├ blocks
   │        │  ├ example_log.png
   │        │  └ example_log_top.png
   │        └ items
   └ data
      └ example_mod
         └ loot_tables
            └ blocks
               └ example_log.json
```

```json:blockstates\example_log.json
{
  "variants": {
    "axis=y": { "model": "example_mod:block/example_log" },
    "axis=z": { "model": "example_mod:block/example_log", "x": 90 },
    "axis=x": { "model": "example_mod:block/example_log", "x": 90, "y": 90 }
  }
}
```
このように書くことで、おそらく`LogBlock`(厳密には`RotatedPillarBlock`)クラスが持つメンバ変数`axis`(面の法線方向)がx,y,zのいずれかによって条件分岐するようになっています。([公式ドキュメント](https://mcforge.readthedocs.io/en/1.14.x/models/blockstates/forgeBlockstates/)にもそれっぽいことが書いてありますね。) 
`"x":90``"y":90`などの記述は回転角です。要するに、垂直設置状態を基準に原木を倒した表示になるよう回転させています。

```json:models\block\example_log.json
{
  "parent": "block/cube_column",
  "textures": {
    "end": "example_mod:blocks/example_log_top",
    "side": "example_mod:blocks/example_log"
  }
}
```
`parent`には`block/cube_column`を指定します。これによって立方体型で上下面と側面で区別したテクスチャの適用ができます。それぞれのテクスチャファイルへのパスを指定しましょう。

```json:models\item\example_log.json
{
  "parent": "example_mod:block/example_log"
}
```
これは今まで通り`block`のモデルファイルを引き継げばよいです。

```json:en_us.jp
{
  "block.example_mod.example_log": "Example Log"
}
```

```json:ja_jp.json
{
  "block.example_mod.example_log": "例原木"
}
```
言語ファイルも今まで通りです。

```json:\loot_table\blocks\example_log.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "example_mod:example_log"
        }
      ]
    }
  ]
}
```
いつも通り。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256627/62cd04ea-74eb-475a-45bc-7ecc6580686b.png)
このように方向を持つブロックが追加できました。
___
**もう一つ原木ブロックに関してやっておくことがあります。**
ブロックの追加自体はここまでで完了していますが、あとで木を構成していく段階で必要になるので、ここで行っておきましょう。

今追加した原木ブロックを`minecraft:logs`のタグに追加します。
[6. レシピの追加](https://qiita.com/koteko/items/4e6f4e25db43907770d9)でも軽く触れましたが、「タグ」とはすなわち共通因子を持つオブジェクトたちをまとめたグループです。minecraftには原木に相当するものをまとめたタグがあり、木に関する処理をする際にこれを使います。そのため、この原木ブロックもこのタグに含めておくと無駄な実装をしなくて済みます。

```
\src\main\resources
   ├ assets
   └ data
      ├ example_mod
      └ minecraft
         └ tags
            └ blocks
               └ logs.json
```
**自分のプロジェクトフォルダ内に**`\src\main\resources\data\minecraft\tags\blocks`フォルダを作り、そこに`logs.json`を配置します。この名前は必ず同じにしてください。

```json:logs.json
{
  "replace": false,
  "values": [
    "example_mod:example_log"
  ]
}
```
`replace`に`false`を与えることにより、同名の`minecraft:logs`にこのファイルでの記述が統合されます。`values`の中でブロックを指定しましょう。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256627/243f08d1-6a9f-c70e-70a1-16c028e11266.png)
デバッグモードでブロックにカーソルを合わせた際、赤下線を引いた部分のように`#minecraft:logs`と表示されていれば完了です。

## 葉の追加
次に木を構成する葉ブロックを追加します。重ねてになりますが、ベースは[2. ブロックの追加](https://qiita.com/koteko/items/c904b3bfdd90f0b9a98a)を参考に、順にみていきましょう。

```java:BlockList.java
//...
public class BlockList {
    public static Block ExampleLeaves = new LeavesBlock(
            Block.Properties.create(Material.LEAVES)
                    .hardnessAndResistance(0.2F)
                    .tickRandomly()
                    .sound(SoundType.PLANT)
                    .lightValue(8))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_leaves"));

    @SubscribeEvent
    public static void registerBlocks(RegistryEvent.Register<Block> event) {
        event.getRegistry().registerAll(
                ExampleLeaves
        );
    }

    @SubscribeEvent
    public static void registerBlockItems(RegistryEvent.Register<Item> event) {
        event.getRegistry().registerAll(
                new BlockItem(ExampleLeaves, new Item.Properties().group(ExampleItemGroup.DEFAULT))
                        .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_leaves"))
        );
    }
}
```
葉ブロックは`LeavesBlock`でつくります。その他はいつも通りです。
___
`resources`の設定をしていきます。

```
\src\main\resources
   ├ assets
   │  └ example_mod
   │     ├ blockstates
   │     │  └ example_leaves.json
   │     ├ lang
   │     │  └ en_us.json
   │     │  └ ja_jp.json
   │     ├ models
   │     │  ├ block
   │     │  │  └ example_leaves.json
   │     │  └ item
   │     │     └ example_leaves.json
   │     └ textures
   │        ├ blocks
   │        │  └ example_leaves.png
   │        └ items
   └ data
      └ example_mod
         └ loot_tables
            └ blocks
               └ example_leaves.json
```

```json:blockstates\example_leaves.json
{
  "variants": {
    "": { "model": "example_mod:block/example_leaves" }
  }
}
```

```json:models\block\example_leaves.json
{
  "parent": "block/leaves",
  "textures": {
    "all": "example_mod:blocks/example_leaves"
  }
}
```
`parent`には`block/leaves`を指定しましょう。(グラフィック設定にもよりますが)半透明なテクスチャが適用できます。

```json:models\item\example_leaves.json
{
  "parent": "example_mod:block/example_leaves"
}
```

```json:en_us.jp
{
  "block.example_mod.example_leaves": "Example Leaves"
}
```

```json:ja_jp.json
{
  "block.example_mod.example_leaves": "例の葉"
}
```

これらはいつも通り。

```json:\loot_table\blocks\example_log.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:item",
              "conditions": [
                {
                  "condition": "minecraft:alternative",
                  "terms": [
                    {
                      "condition": "minecraft:match_tool",
                      "predicate": {
                        "item": "minecraft:shears"
                      }
                    },
                    {
                      "condition": "minecraft:match_tool",
                      "predicate": {
                        "enchantments": [
                          {
                            "enchantment": "minecraft:silk_touch",
                            "levels": {
                              "min": 1
                            }
                          }
                        ]
                      }
                    }
                  ]
                }
              ],
              "name": "example_mod:example_leaves"
            },
            {
              "type": "minecraft:item",
              "conditions": [
                {
                  "condition": "minecraft:survives_explosion"
                },
                {
                  "condition": "minecraft:table_bonus",
                  "enchantment": "minecraft:fortune",
                  "chances": [
                    0.05,
                    0.0625,
                    0.083333336,
                    0.1
                  ]
                }
              ],
              "name": "example_mod:example_sapling"
            }
          ]
        }
      ]
    }
  ]
}
```
`loot_table`ファイルは今まで結構異なります。(今まではさぼってきましたが)葉ブロックは複数のドロップをもちエンチャントやツールにも依存するのできちんと実装するとこのようになります。
詳しくは[参考ページ](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)に説明を譲りますが、簡単に説明します。
これは「ブロックからのドロップであり、数は１つ、`children`のどれかを返す。`children`は２つあって、まずハサミあるいはシルクタッチⅠのツールで壊した場合に葉ブロックを返すもの。次にそれ以外の場合のランダム確率(幸運エンチャで確率アップ)で苗を返すもの。」という風に書かれています。ここで先に出てしまい順番が前後しますが、次の項で苗の追加を行います。
これはminecraftのOrkの葉を参考にしています。各自色々と見て好きなように書きましょう。
___
最後に、`MaterialColor`の設定をします。これは葉や草がバイオームに応じて色が変わる効果をもたらすものです。ここは面倒な場合無視してもよいです。無視する場合全バイオームで同じ色が表示されるのでその色でテクスチャを用意しましょう。

```java:BlockList.java
//...
public class BlockList {
    //...
    @SubscribeEvent
    public static void registerBlockColors(ColorHandlerEvent.Block event) {
        event.getBlockColors().register((p_210229_0_, p_210229_1_, p_210229_2_, p_210229_3_) -> {
            return p_210229_1_ != null && p_210229_2_ != null ? BiomeColors.getFoliageColor(p_210229_1_, p_210229_2_) : FoliageColors.getDefault();
        }, ExampleLeaves);
    }

    @SubscribeEvent
    public static void registerBlockItemColors(ColorHandlerEvent.Item event) {
        event.getItemColors().register((p_210235_1_, p_210235_2_) -> {
            BlockState blockstate = ((BlockItem)p_210235_1_.getItem()).getBlock().getDefaultState();
            return event.getBlockColors().getColor(blockstate, (IEnviromentBlockReader)null, (BlockPos)null, p_210235_2_);
        }, ExampleLeaves);
    }
}
```
宣言と登録をしている`BlockList.java`で同時にこれも登録してしまいます。`ColorHandlerEvent`というものがあるので、これをつかって`register()`することで反映されます。ブロックとアイテムそれぞれについて行います。変数などが意味不明な文字の羅列になっていますが、これは難読化されたminecraftのコードからそのまま引っ張ってきただけなので変えてもよいです。
ブロックについては、`BiomeColors.getFoliageColor()`によってそのブロックが存在するバイオームに応じた色が取得され、登録されます。
アイテムについては、デフォルトの色が取得され、登録されます。
両者ともに、`register()`の第一引数に色(ラムダ式で取得してます)、第二引数に色を設定するオブジェクトを渡します。
この辺りは難しいことをやろうとしない限り深く理解しなくてよいです。

実際の色については、[参考ページ](https://minecraft-ja.gamepedia.com/%E3%83%90%E3%82%A4%E3%82%AA%E3%83%BC%E3%83%A0#.E3.83.90.E3.82.A4.E3.82.AA.E3.83.BC.E3.83.A0.E3.82.AB.E3.83.A9.E3.83.BC.E3.81.AE.E6.B1.BA.E5.AE.9A)に詳しく書いてあります。基本的にはグレースケールの葉ブロックテクスチャを用意して色を載せているようですが、今回色味がかったファイルを用意してみた場合実際のブロックもその色味になったので、おそらく内部では加算してるのかな、と思っています。

# TreeFeatureクラスとTreeクラスの追加
これらは違いを言葉で説明するのが難しいですが、ともに木を管理するクラスです。`Tree`クラスは木自体を管理するクラスで、この後で追加する苗に関連して必要になります。一方で、`TreeFeature`クラスは木の生成に関することのみを管理しており、`Tree`クラスから該当する`TreeFeature`を取得することもできます。

```
\src\main\java\jp\koteko\example_mod\
   ├ blocks
   │   └ trees
   │      └ ExampleTree.java
   ├ items
   ├ lists
   ├ world
   │   └ features
   │      └ ExampleTreeFeature.java
   └ ExampleMod.java
```
(ファイル配置はいろいろ参考にして合わせているつもりですが、悩んだら割と適当です。)

```java:ExampleTreeFeature.java
package jp.koteko.example_mod.world.features;

import jp.koteko.example_mod.lists.BlockList;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.feature.TreeFeature;
import net.minecraftforge.common.IPlantable;

public class ExampleTreeFeature extends TreeFeature {
    public ExampleTreeFeature() {
        super(NoFeatureConfig::deserialize, false, 4, BlockList.ExampleLog.getDefaultState(), BlockList.ExampleLeaves.getDefaultState(), false);
        setSapling((IPlantable) BlockList.ExampleSapling);
    }
}
```
`TreeFeature`クラスを継承して`ExampleTreeFeature`クラスを作ります。継承元のコンストラクタに渡す引数は順に以下の通りです。
第一引数は`NoFeatureConfig`のインスタンスで多分特に有効に使われません。
第二引数は何らかの通知の可否を決定する`boolean`値で、他の木々でfalseだったため真似しました。何かわかったら追記します。
第三引数は木の最小の高さを決める`int`値です。
第四引数は幹となるブロックの`BlockState`です。
第五引数は葉となるブロックの`BlockState`です。
第六引数は木にツタを伸ばすかどうかを決める`boolean`値です。
また、`setSapling()`は苗の設定をしており、ここに苗のインスタンスを渡します。苗は次の項で実装します。

```java:ExampleTree.java
package jp.koteko.example_mod.blocks.trees;

import jp.koteko.example_mod.world.features.ExampleTreeFeature;
import net.minecraft.block.trees.Tree;
import net.minecraft.world.gen.feature.AbstractTreeFeature;
import net.minecraft.world.gen.feature.NoFeatureConfig;

import javax.annotation.Nullable;
import java.util.Random;

public class ExampleTree extends Tree {
    @Nullable
    protected AbstractTreeFeature<NoFeatureConfig> getTreeFeature(Random random) {
        return new ExampleTreeFeature();
    }
}

```
抽象クラス`Tree`を継承して`ExampleTree`クラスを作ります。`getTreeFeature`というメソッドを定義します。先ほど定義した`ExampleTreeFeature`のインスタンスを返すようにしましょう。
引数で乱数を受け取って使っていませんが、これはオークの木などが確率で通常種と巨大種に分かれる場合などに使われています。

## 苗の追加
次に苗を追加していきます。
まず苗のクラスを用意します。

```
\src\main\java\jp\koteko\example_mod\
   ├ blocks
   │   ├ trees
   │   └ ExampleSapling.java
   ├ items
   ├ lists
   ├ world
   └ ExampleMod.java
```

```java:BlockExampleSapling.java
package jp.koteko.example_mod.blocks;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.BushBlock;
import net.minecraft.block.IGrowable;
import net.minecraft.block.trees.Tree;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateContainer;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;

import java.util.Random;

public class BlockExampleSapling extends BushBlock implements IGrowable {
    public static final IntegerProperty STAGE = BlockStateProperties.STAGE_0_1;
    protected static final VoxelShape SHAPE = Block.makeCuboidShape(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D);
    private final Tree tree;

    public BlockExampleSapling(Tree p_i48337_1_, Block.Properties properties) {
        super(properties);
        this.tree = p_i48337_1_;
        this.setDefaultState(this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)));
    }

    public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
        return SHAPE;
    }

    public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
        super.tick(state, worldIn, pos, random);
        if (!worldIn.isAreaLoaded(pos, 1)) return; // Forge: prevent loading unloaded chunks when checking neighbor's light
        if (worldIn.getLight(pos.up()) >= 9 && random.nextInt(7) == 0) {
            this.grow(worldIn, pos, state, random);
        }

    }

    public void grow(IWorld worldIn, BlockPos pos, BlockState state, Random rand) {
        if (state.get(STAGE) == 0) {
            worldIn.setBlockState(pos, state.cycle(STAGE), 4);
        } else {
            if (!net.minecraftforge.event.ForgeEventFactory.saplingGrowTree(worldIn, rand, pos)) return;
            this.tree.spawn(worldIn, pos, state, rand);
        }

    }

    /**
     * Whether this IGrowable can grow
     */
    public boolean canGrow(IBlockReader worldIn, BlockPos pos, BlockState state, boolean isClient) {
        return true;
    }

    public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, BlockState state) {
        return (double)worldIn.rand.nextFloat() < 0.45D;
    }

    public void grow(World worldIn, Random rand, BlockPos pos, BlockState state) {
        this.grow(worldIn, pos, state, rand);
    }

    protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
        builder.add(STAGE);
    }
}
```
このコードについてですが、**(ほぼ)すべてminecraftの苗のコードと同じ**です。じゃあ何故わざわざ作ったか、というと、minecraftの`Sapling`クラスのコンストラクタが`protected`で、modのコード内から直接使えなかったためです。minecraft側がこれをどう扱っているかは理解する時間が不足していたためここでは考えないことにしますが、おそらくそちらに合わせた形でのもう少しうまい実装の仕方があると思います。
パッケージ名、クラス名、コンストラクタの3つのみ変更して使います。

```java:BlockList.java
//...
public class BlockList {
    public static Block ExampleSapling = new BlockExampleSapling(
            new ExampleTree(),
            Block.Properties.create(Material.PLANTS)
                    .doesNotBlockMovement()
                    .tickRandomly()
                    .hardnessAndResistance(0.0F)
                    .sound(SoundType.PLANT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_sapling"));

    @SubscribeEvent
    public static void registerBlocks(RegistryEvent.Register<Block> event) {
        event.getRegistry().registerAll(
                ExampleSapling
        );

    }

    @SubscribeEvent
    public static void registerBlockItems(RegistryEvent.Register<Item> event) {
        event.getRegistry().registerAll(
                new BlockItem(ExampleSapling, new Item.Properties().group(ExampleItemGroup.DEFAULT))
                        .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_sapling"))
        );
    }
}
```
先程用意した苗のクラスでブロックを追加します。
第一引数は対応する木を渡すので、先ほど作った`ExampleTree`クラスのインスタンスを渡します。

いつも通り`resources`の設定をしていきます。特に変わらないものは解説を省略します。

```
\src\main\resources
   ├ assets
   │  └ example_mod
   │     ├ blockstates
   │     │  └ example_sapling.json
   │     ├ lang
   │     │  └ en_us.json
   │     │  └ ja_jp.json
   │     ├ models
   │     │  ├ block
   │     │  │  └ example_sapling.json
   │     │  └ item
   │     │     └ example_sapling.json
   │     └ textures
   │        ├ blocks
   │        │  └ example_sapling.png
   │        └ items
   └ data
      └ example_mod
         └ loot_tables
            └ blocks
               └ example_sapling.json
```

```json:blockstates\example_sapling.json
{
  "variants": {
    "": { "model": "example_mod:block/example_sapling" }
  }
}
```

```json:models\block\example_sapling.json
{
    "parent": "block/cross",
    "textures": {
        "cross": "example_mod:blocks/example_sapling"
    }
}

```
`parent`には`block/cross`を指定します。これによって平面が交差したような形でテクスチャの適用ができます(実際に形を見れば言ってる意味が分かると思います)。

```json:models\item\example_sapling.json
{
    "parent": "item/generated",
    "textures": {
        "layer0": "example_mod:blocks/example_sapling"
    }
}
```
`block`のモデルファイルを引き継ぐのではなく、`item/generated`で指定します。

```json:en_us.jp
{
  "block.example_mod.example_sapling": "Example Sapling"
}
```

```json:ja_jp.json
{
  "block.example_mod.example_sapling": "例の苗"
}
```

```json:\loot_table\blocks\example_sapling.json
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "example_mod:example_sapling"
        }
      ]
    }
  ]
}
```

ゲームを起動して確認してみましょう。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256627/0279038e-2e1b-c4b9-9050-49f10e10d1e6.png)
苗が追加され、骨粉で木が育つことが確認できると思います。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256627/d7142a20-87c4-5b90-aab9-fa3468ed88f2.png)
また、木の幹を除去すると、葉ブロックが自然消滅をはじめ、消える際に確率で苗をドロップすることが確認できると思います。

# 木の生成
ここまで来たらあと少しです。ここまでで実装した木をワールド生成時に自動で生成されるようにしましょう。
これは[8. 鉱石の追加と生成](https://qiita.com/koteko/items/f17d723337ddf7d5dbd4)とほぼ同じことをするのでそちらも参考にしてください。

```
\src\main\java\jp\koteko\example_mod\
   ├ blocks
   ├ items
   ├ lists
   ├ world
   │   ├ WorldGenOres.java
   │   └ WorldGenTrees.java
   └ ExampleMod.java
```
`WorldGenTrees.java`を配置します。

```java:WorldGenOres.java
package jp.koteko.example_mod.world;

import jp.koteko.example_mod.world.features.ExampleTreeFeature;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.placement.AtSurfaceWithExtraConfig;
import net.minecraft.world.gen.placement.Placement;
import net.minecraftforge.registries.ForgeRegistries;

public class WorldGenTrees {
    public static void setup() {
        addTreeToOverworld(new ExampleTreeFeature());
    }

    private static void addTreeToOverworld(Feature<NoFeatureConfig> featureIn) {
        for(Biome biome : ForgeRegistries.BIOMES) {
            if (!biome.getCategory().equals(Biome.Category.NETHER) && !biome.getCategory().equals(Biome.Category.THEEND)) {
                biome.addFeature(
                        GenerationStage.Decoration.VEGETAL_DECORATION,
                        Biome.createDecoratedFeature(
                                featureIn,
                                IFeatureConfig.NO_FEATURE_CONFIG,
                                Placement.COUNT_EXTRA_HEIGHTMAP,
                                new AtSurfaceWithExtraConfig(2, 0.1F, 1)
                        )
                );
            }
        }
    }
}
```
`AtSurfaceWithExtraConfig`の引数は、1チャンク当たりの抽選回数、追加抽選を行う可能性、追加抽選を行う場合の追加回数です。この例の場合、「1チャンク当たり2か所抽選を行い、10%の確率でさらに1回抽選を行う」です。

最後に、今定義した`WorldGenOres.setup()`をメインファイル内の`setup`中で呼びます。

```java:ExampleMod.java
//...
public class ExampleMod
{
    //...
    private void setup(final FMLCommonSetupEvent event)
    {
        WorldGenTrees.setup();
    }
    //...
}
```
ゲームを起動して新たにワールドを生成します。
![2020-08-09_17.46.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256627/1cdf45a2-788b-e62d-67a7-8b73f283b312.png)
なんとなく光らせておいたので夜だと一層目立ちます。

**木の追加と生成ができました！**


# 参考
[1.14.3 Tags help - Modder Support - Forge Forums](https://forums.minecraftforge.net/topic/72424-1143-tags-help/?do=findComment&comment=349413)
[バイオーム - Minecraft Wiki](https://minecraft-ja.gamepedia.com/%E3%83%90%E3%82%A4%E3%82%AA%E3%83%BC%E3%83%A0#.E3.83.90.E3.82.A4.E3.82.AA.E3.83.BC.E3.83.A0.E3.82.AB.E3.83.A9.E3.83.BC.E3.81.AE.E6.B1.BA.E5.AE.9A)
[ルートテーブル - 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)
[地図アイテムフォーマット - Minecraft Wiki](https://minecraft-ja.gamepedia.com/%E5%9C%B0%E5%9B%B3%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88)

# 次の記事
[99. Modの出力](https://qiita.com/koteko/items/cbcfe448def02c3413b9)