【Forge】1.13.2での自作したEntityとEntityRenderの登録方法

### 開発環境
|OS |IDE |Forge |JDK |Lang|
|:-----------------------|:-----------------|:-------------|:--------|:---|
|Windows10 1809 17763.593|IntelliJ IDEA 2019|1.13.2-25.0.74|1.8.0_202|Java|

## はじめに
1.13.2でのEntity登録について日本語の資料が少ないと思いましたので、参考になればと思います。
ソースコードは自作ModのTorchBowModを元に説明してきます。

- [GitHub - TorchBowMod](https://github.com/noriokun4649/TorchBowMod)

## 私が気づいた1.12からの変更点
- **Modの初期化処理が並列的に読み込まれるようになった**
- クライアントとサーバ別の処理がしやすくなった。
- **SidedProxyを使わずにクライアントの初期化処理をできるようになった。**
- 一応SidedProxyのような処理方法も残されている。
- **ブロック、アイテム、Entityなどの登録方法が変わった**
- **Entityの追加方法が変わった。**
- META-INFフォルダの中にModの情報ファイル「mods.toml」を造る必要がある。
- recipeのフォルダがassetsからdataになった
- 言語ファイルがlangからjsonになった。
- pack.mcmetaが必要になった。
- データパック用らしい

今回は中でも私がつまずいたEntityの追加についてまとめてみました。
太字部分はEntityの追加に関係してくる変更点です。

## Modの初期化処理が並列的に読み込まれるようになった

```java:preInit
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
}
```
従来ではpreInitやpostInitなどの処理は、上記のようにアノテーションを付加していましたが、今回の変更で`@Mod`アノテーションのあるクラスのコンストラクタで、初期化処理のリスナを登録するように変更されました。
例えば、`@Mod`アノテーションの付いているクラスファイルの名前が`TorchBowMod`の場合、コンストラクタは下記のようになります。

```java:TorchBowMod.java
public class TorchBowMod {
    public TorchBowMod() {
        final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
        modEventBus.addListener(this::preInit);// ここで初期化処理イベントを受け取るリスナを登録
        MinecraftForge.EVENT_BUS.register(this);
    }

    // 仮引数がFMLCommonSetupEventなのでpreInitに相当する
    // FMLLoadCompleteEventだとpostInitに相当する
    // 他にもいろいろなイベントが用意されているが今回は省略
    private void preInit(final FMLCommonSetupEvent event) {
        // preInitで行う処理～～～
    }
}
```

`this::preInit`という見慣れない記述が出てきました。
今回のアップデートでラムダ式が積極的に使われているためラムダ式の記述がよく出てきます。
ラムダ式については他の記事を参考にしてください。

## SidedProxyを使わずにクライアントの初期化処理をできるようになった
1.12では`CommonProxy`というインターフェース若しくはクラスを作り、継承したClientProxyとServerProxyでクライアント・サーバの処理を分岐していたと思います。
1.13.2では上記の初期化処理イベント以外にも、クライアントサイドのイベント`FMLClientSetupEvent`が用意されています。

```java:1.13.2
//クライアントサイドのイベントリスナ
private void initClient(final FMLClientSetupEvent event) {
    //クライアントサイド処理
}
```
このような感じです。イベントの登録は初期化処理イベントと同じ方法でできます。
さて、Entityのレンダですが1.12と1.13.2では、登録方法に変更はないので`ClientProxy`で書いていた

```java:ClientProxy
//この場合自作のEntity→EntityTorchとそのEntityのレンダであるRenderTorchを登録している。
enderingRegistry.registerEntityRenderingHandler(EntityTorch.class, RenderTorch::new);
```
をそのままクライアントサイドのイベントリスナに書くと登録できます。

## ブロック、アイテム、Entityなどの登録方法が変わった
1.12ではアイテムやブロックやモデルなどの登録には`@SubscribeEvent`アノテーションを利用してたと思います。
1.13.2では同じアノテーションを利用していますが少々方法が変わりました。
まず`@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)`アノテーションの付いたstaticクラスを作成する必要があり、そのクラス内に`@SubscribeEvent`アノテーションを付けたレジスターメソッドを記述するようになりました。

```java:RegistryEvents
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public static class RegistryEvents {
    // 仮引数がItemのジェネリクスなのでアイテムの登録だがBlockのジェネリクスにするとブロックの登録処理ができる。
    @SubscribeEvent
    public static void onItemsRegistry(RegistryEvent.Register<Item> event) {
        // この場合アイテムの登録
    }
}
```

## Entityの追加方法が変わった
さてようやく本題ですが。
1.12まではEntityの登録には`EntityRegistry`を使用していましたが、1.13.2で削除されたようです。
そのためEntityの登録には上記の`RegistryEvent`を利用する必要があります。
しかしながらForgeにて定義されているジェネリクスの一覧を見てみると。

```java:ForgeRegistries.class
public static final IForgeRegistry<Block> BLOCKS;
public static final IForgeRegistry<Item> ITEMS;
public static final IForgeRegistry<Potion> POTIONS;
public static final IForgeRegistry<Biome> BIOMES;
public static final IForgeRegistry<SoundEvent> SOUND_EVENTS;
public static final IForgeRegistry<PotionType> POTION_TYPES;
public static final IForgeRegistry<Enchantment> ENCHANTMENTS;
public static final IForgeRegistry<VillagerProfession> VILLAGER_PROFESSIONS;
public static final IForgeRegistry<EntityType<?>> ENTITIES;
public static final IForgeRegistry<TileEntityType<?>> TILE_ENTITIES;
public static final IForgeRegistry<ModDimension> MOD_DIMENSIONS;
```
単純に`<Entity>`ではな`<EntityType<?>>`になっています。
ということでジェネリクスには`<EntityType<?>>`を指定する必要があるのがわかります。
そして`EntityType`のジェネリクスは`EntityType<T extends Entity>`になっているため`EntityType`のジェネリクスに指定する型はEntity型である必要があるのがわかります。

ということで早速自作したEntityのEntityTypeを作ってみます。
レンダのときにも出てきた「EntityTorch」というEntityを登録すると想定します。

```java
public static EntityType<EntityTorch> TORCH;
```
まずは自作のEntityをジェネリクスしたEntityType型のグローバル変数を定義します。


```java:RegistryEvents
@SubscribeEvent
public static void registerEntityTypes(final RegistryEvent.Register<EntityType<?>> event) {
}
```
そして「ブロック、アイテム、Entityなどの登録方法が変わった」で説明したときの、RegistryEventsクラスに上記のメソッドを追加します。
このメソッド内では、nullのままの`TORCH`にEntityのプロパティ的な物を書き込んで、その後登録するような処理になります。

```java:registerEntityTypesメソッド内
TORCH= EntityType.Builder.create(EntityTorch.class, EntityTorch::new).tracker(60, 5, true).build(MODID + ":entitytorch");
TORCH.setRegistryName(new ResourceLocation(MODID, "entitytorch"));
event.getRegistry().register(TORCH);
```
EntityTypeは`EntityType.Builder`にて作成しますが、この際Entity側も1.13.2での書き方に書き換える必要があります。
これは既存のEntityなどを参考にすればできると思いますので調べるなりしてみてください。
`tracker()`はそれぞれrange、updateFrequency、sendVelocityUpdatesの順で指定します。
これは1.12での`EntityRegistry.registerModEntity()`の第6引数、第7引数、第8引数と同じなので特に困らないでしょう。
レジストリネームなどはアイテムなどと同じ感覚で大丈夫です。

## 参考元
- [Minecraft　Forge 1.13.2版　Modding　してみた。　アイテム、エンティティ・レンダの追加](https://noriokun4649.blog.fc2.com/blog-entry-334.html)

### 蛇足
ModdingもQiitaもはじめたばかりなので何か間違いなどやよろしくない点などありましたら指摘していただけると幸いです。
Q：なぜ今更1.13.2のこと書いたの？
A：Qiitaに最近登録したので3か月前ぐらいにブログで書いていた記事を投稿してみました。