Minecraft Mod 開発環境構築 (IntelliJ IDEA + Minecraft Forge 1.15.2) + Hello World Mod 作成

## 概要

- IntelliJ IDEA に Minecraft Mod の開発環境を構築して、シンプルな Hello World Mod を作成する

## 環境

- Minecraft 1.15.2
- Minecraft Forge 1.15.2-31.1.0
- macOS Catalina
- Java 8 (AdoptOpenJDK)
- IntelliJ IDEA 2019.3.1 (Community Edition)

## IntelliJ IDEA に開発環境を構築

### Java 8 のインストール

今回の開発環境では Java 11 以降がサポートされていないため、事前に Java 8 をインストールしておく必要がある。

参考: [Java 8 \(OpenJDK: AdoptOpenJDK\) を Homebrew で macOS にインストールする \- Qiita](https://qiita.com/niwasawa/items/8f52cb0083d888648b02)

### Mdk (Mod Development Kit) のダウンロード

現時点 (2020年2月16日現在) の推奨環境である Minecraft Forge 1.15.2-31.1.0 の Mdk (Mod Development Kit) を [Minecraft Forge](https://files.minecraftforge.net/) からダウンロードする。

<img width="816" alt="minecraft-forge-01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/f15164b8-d3e6-9281-c2a5-052e7f00a78c.png">

ダウンロードした forge-1.15.2-31.1.0-mdk.zip を展開する。

```
$ unzip forge-1.15.2-31.1.0-mdk.zip 
Archive:  forge-1.15.2-31.1.0-mdk.zip
  inflating: gradlew                 
  inflating: gradlew.bat             
  inflating: CREDITS.txt             
  inflating: LICENSE.txt             
  inflating: changelog.txt           
   creating: gradle/
   creating: gradle/wrapper/
  inflating: gradle/wrapper/gradle-wrapper.properties  
  inflating: gradle/wrapper/gradle-wrapper.jar  
  inflating: .gitignore              
   creating: src/
   creating: src/main/
   creating: src/main/java/
   creating: src/main/java/com/
   creating: src/main/java/com/example/
   creating: src/main/java/com/example/examplemod/
  inflating: src/main/java/com/example/examplemod/ExampleMod.java  
   creating: src/main/resources/
  inflating: src/main/resources/pack.mcmeta  
   creating: src/main/resources/META-INF/
  inflating: src/main/resources/META-INF/mods.toml  
  inflating: build.gradle            
  inflating: README.txt              
  inflating: gradle.properties       
```

README.txt にセットアップ方法が載っている。

> If you prefer to use IntelliJ:
> 1. Open IDEA, and import project.
> 2. Select your build.gradle file and have it import.
> 3. Run the following command: "gradlew genIntellijRuns" (./gradlew genIntellijRuns if you are on Mac/Linux)
> 4. Refresh the Gradle Project in IDEA if required.

参考: [MinecraftForge/mdk at 1\.15\.x · MinecraftForge/MinecraftForge · GitHub](https://github.com/MinecraftForge/MinecraftForge/tree/1.15.x/mdk)

### IntelliJ IDEA で Import Project

IntelliJ IDEA で Import Project にて展開したフォルダを指定してプロジェクトを作成する。

<img width="1099" alt="minecraft-forge-02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/30e3edd6-20e7-7e0c-1ad3-52c5315eea83.png">

以下のようなメッセージが出力された場合は適切な Java のバージョンが設定されていない。

```
> Failed to apply plugin [id 'net.minecraftforge.gradle']
   > Found java version null. Minimum required is 1.8.0_101. Versions 11.0.0 and newer are not supported yet.
```

IntelliJ の設定 Preferences > Build, Execution, Deployment > Build Tools > Gradle > Gradle JVM にて Java 8 以降の JVM を指定する必要がある。

### ./gradlew genIntellijRuns

IntelliJ IDEA の Terminal などで ./gradlew genIntellijRuns を実行する。

```
$ ./gradlew genIntellijRuns
```

ここでも Java 8 以降が使われるため、必要に応じて設定をしておく。
参考: [Java 8 \(OpenJDK: AdoptOpenJDK\) を Homebrew で macOS にインストールする \- Qiita](https://qiita.com/niwasawa/items/8f52cb0083d888648b02)

### 開発用 Minecraft Forge の起動

IntelliJ IDEA 右上にある Gradle Tool Window から Tasks > fg_runs > runClient を実行するか、または Terminal などから ./gradlew runClient を実行すると Minecraft が起動する。

<img width="1209" alt="minecraft-forge-03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/9686f576-4663-2fe0-29e2-883886f71df6.png">

「Mods」 をクリックすると Mdk に同梱されている Example Mod が読み込まれていることがわかる。

<img width="854" alt="minecraft-forge-04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/fbea7e45-c118-a7fe-0c5a-0ccd83df16c8.png">

### Example Mod について

Mdk には Mod 開発のサンプルとして Example Mod のソースコードが同梱されている。

ソースコード一覧。

- src/main/java/com/example/examplemod/ExampleMod.java
- src/main/resources/pack.mcmeta
- src/main/resources/META-INF/mods.toml
- build.gradle

[MinecraftForge/mdk at 1\.15\.x · MinecraftForge/MinecraftForge · GitHub](https://github.com/MinecraftForge/MinecraftForge/tree/1.15.x/mdk) でソースコードの中身を確認することも可能。

## Hello World Mod の作成

構築した開発環境上にて、シンプルな Hello World を実現する Mod を作成する。

### ソースコード一覧

- src/main/java/com/example/HelloWorldMod.java
- src/main/resources/pack.mcmeta
- src/main/resources/META-INF/mods.toml
- build.gradle

### src/main/java/com/example/HelloWorldMod.java

Mod のメイン処理を実行する Java のクラスを記述する。

```java
package com.example;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod("helloworldmod") // META-INF/mods.toml に記述した modId
public class HelloWorldMod {

  public HelloWorldMod() {
    // MinecraftForge.EVENT_BUS で処理するイベントのハンドラメソッドを持つオブジェクト(this)を登録
    MinecraftForge.EVENT_BUS.register(this);
  }

  /**
   * プレイヤーのログイン時に実行するイベントハンドラメソッド。
   * メソッド名は任意のもので良い。
   *
   * @param event PlayerLoggedInEvent オブジェクト
   */
  @SubscribeEvent
  public void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
    PlayerEntity player = event.getPlayer();
    BlockPos pos = player.getPosition();
    String message =
      "Hello, World!\n"
        + "[name]=[" + player.getName().getFormattedText() + "]\n"
        + "[pos]=[" + pos.getX() + "," + pos.getY() + "," + pos.getZ() + "]";
    ITextComponent text = new StringTextComponent(message);
    player.sendMessage(text);
  }
}
```

### src/main/resources/pack.mcmeta

リソースパック情報記述用ファイル。このファイルが無いと 「failed to load a valid ResourcePackInfo」 などのエラーが発生してしまう。
ここでは最低限の内容のみ記述する。

```json
{
  "pack": {
    "description": "Hello World mod resources",
    "pack_format": 5
  }
}
```

### src/main/resources/META-INF/mods.toml

Mod 情報記述用ファイル。
ここでは最低限の内容のみ記述する。

```
modLoader="javafml"
loaderVersion="[31,)"

[[mods]]
modId="helloworldmod"
version="1.2.3"
displayName="Hello World Mod"
description='''
This is the ...
Hello World mod.
'''
```

### build.gradle

Gradle 用ビルド設定ファイル。
ここでは最低限の内容のみ記述する。

```groovy
buildscript {
  repositories {
    maven { url = 'https://files.minecraftforge.net/maven' }
    jcenter()
    mavenCentral()
  }
  dependencies {
    classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
  }
}
apply plugin: 'net.minecraftforge.gradle'

version = '1.2.3'
group = 'com.example.helloworld'
archivesBaseName = 'helloworldmod'

sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'

minecraft {
  mappings channel: 'snapshot', version: '20190719-1.14.3'
  runs {
    client {
      workingDirectory project.file('run')
      property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
      property 'forge.logging.console.level', 'debug'
      mods {
        helloworldmod {
          source sourceSets.main
        }
      }
    }
  }
}

dependencies {
  minecraft 'net.minecraftforge:forge:1.15.2-31.1.0'
}
```

### 配布用 jar ファイルを生成

IntelliJ IDEA 右上にある Gradle Tool Window から Tasks > build > build を実行するか、または Terminal などから ./gradlew build を実行する。

```
$ ./gradlew build
```

配布用の jar ファイルが build/libs ディレクトリに出力される。

```
$ ls build/libs/
helloworldmod-1.2.3.jar
```

### Minecraft Forge で実行

正規版 Minecraft Java Edition の Minecraft Launcher を起動して Minecraft Forge 1.15.2-31.1.0 用の構成を設定する。

<img width="1000" alt="minecraft-forge-05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/8cf8105e-4d38-1970-086c-95c93da0cfa4.png">

作成した jar ファイルを設定した構成のゲームディレクトリの mods ディレクトリに設置して、Minecraft Forge 1.15.2-31.1.0 を起動。

<img width="854" alt="minecraft-forge-08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/04f1eb22-0bf1-c95c-c924-7dd09ec59f1d.png">

Hello World Mod が読み込まれているのを確認できる。

<img width="854" alt="minecraft-forge-06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/d403d44f-d136-c91d-e78f-c215db4c79cd.png">

ワールドに入るとチャット欄に Hello World が表示される。

<img width="854" alt="minecraft-forge-07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/3c1a9b77-dfad-156a-6710-2ddba96b9d4b.png">

## 参考資料
- [Forge 31\.1 Minecraft 1\.15\.2 \- Releases \- Minecraft Forge Forums](https://www.minecraftforge.net/forum/topic/80524-forge-311-minecraft-1152/)
- [Forge Documentation](https://mcforge.readthedocs.io/en/1.15.x/)
- [GitHub \- MinecraftForge/MinecraftForge: Modifications to the Minecraft base files to assist in compatibility between mods\.](https://github.com/MinecraftForge/MinecraftForge)
    - [MinecraftForge/BasicEventHooks\.java at 1\.15\.x](https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/main/java/net/minecraftforge/fml/hooks/BasicEventHooks.java)
    - [MinecraftForge/PlayerEvent\.java at 1\.15\.x](https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java)
    - [MinecraftForge/ForgeInternalHandler\.java at 1\.15\.x](https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/main/java/net/minecraftforge/common/ForgeInternalHandler.java)
- [ForgeJavaDocs](https://skmedix.github.io/ForgeJavaDocs/)
- [Minecraft 1\.14\.4 Forge Modの作成 その2 【基本的なファイルの配置】 \- Qiita](https://qiita.com/Hiroya_W/items/f54fb5b85b408c4e5a38)
- [Minecraft Forge Eventシステム概要 \- Minecraft Modding Wiki](https://mcmodding.jp/modding/index.php/Minecraft_Forge_Event%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A6%82%E8%A6%81)
- [Minecraft Forge API \- Minecraft Modding Wiki](https://mcmodding.jp/modding/index.php/Minecraft_Forge_API)