「ヤジが飛んでくるマインクラフト」DeepLearningで適当テキスト生成 ~modで動かす~

DeepLearningの力を借りて、マイクラのプレイ中、ゲームに関係のある文章を読み上げてくれるソフトを作った。

↓こんなやつ
![でもミニ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358231/9fa597d6-abc1-58df-4007-82037b68318d.gif)

[実際に遊んでいる動画](https://youtu.be/xseWajIDe4M?t=55)

1つの記事にまとめるのが困難なため、いくつかの記事に分けます。
ここでは、<font color = red>**アプリケーション部分**</font>について説明します。

### ↓他の記事

- [全体の流れ](https://qiita.com/eteeeeeerminal/items/428f0618c775da816519)

- [データを用意する](https://qiita.com/eteeeeeerminal/items/0c7d737da264bd61d0ff)

- [Deep Learning する](https://qiita.com/eteeeeeerminal/items/3c3ea279999724aa37d3)

# やりたいこと
マインクラフトで、近くにゾンビがいるか判定。
ゾンビがいたら、ゾンビに関連する文章を表示。

(文章そのものを用意するところは別の記事へ)

# マインクラフトmod
マインクラフトは有志の方が制作した、modというものがある。
mod を使えば、かなり自由にゲームを改造することができる。

[MCreator](https://mcreator.net/) を使えば、すぐにmod制作が始められる。
簡単な変更なら、コードすら書く必要がない。

### Python プログラムを組み込みたい
マインクラフト mod は Java で書かれている。

- Java あまり分からない。
- DeepLearningのモデルも動かしたいので、Python が使いたい。

### [Raspberry Jam Mod](https://xn--minecrafter-k83ja61doa.com/raspberry-jam-mod1)([mcpi](https://github.com/martinohanlon/mcpi))
Pythonからマインクラフトを一部操作できる。
[いろんなことができる。](https://ichibariki.hatenablog.com/entry/2017/05/18/073340)
しかし、ゲーム情報を取得する部分は微妙。

### Python と Java で通信

[mcpi](https://github.com/martinohanlon/mcpi)のコードを見てみる。
[Socket通信](https://qiita.com/megadreams14/items/32a3eed4661e55419e1c)でやりとりしているらしい。
ポートを指定してごにょごにょするらしい。

- Python側は [mcpi の Connectionクラスを改造](https://github.com/eteeeeeerminal/mcpi/tree/master/mcpi)

- Java側は ゴリ押しで書く
    - [JavaのSocket通信](https://itsakura.com/java-socket)
    - [Pythonと通信](http://androooooooid-blog.blogspot.com/2014/09/pythonjavasocket.html)

## 近くにゾンビがいるかどうか調べる
ようやく、modの実装。
MCreator1.9.1 を使用した。

MCreator で新しいワークスペースを作ると mod の雛形が作成される。

- GUIで、新しいコマンドを作れる。空のコマンドを作成。
    - hogehogeCommandExecuted みたいなやつの、`executeProcedure`関数に書く。

- やりたいことを別の関数に詰め込む。  
    - Socketを準備
    - 継続して、データを取得・送信・受信

- コマンド実行時に、別のプロセスで、作った関数を実行するようにする。
    - mod 素人(+Java素人)なので、mod と切り分けたかった。
    - 脳死で、[Thread とかいうのを使ってみる。](https://itsakura.com/java-thread-runnable)

### ゲーム内情報取得
```Java
Minecraft mc = Minecraft.getMinecraft()
WorldClient world = mc.world;
List<Entity> entities = world.getEntities(Entity.class, (entity)->!entity.isInvisible());
```

これで、ワールド内で透明でない敵mobや動物mobが取得できる。

```Java
Entity player = world.getEntityByID(mc.player.getEntityId());
```
そして、プレイヤーのインスタンスもとる。

```Java
String minecraftData;
for (Entity e: entities) {
    if (e.getDistance(player) < 8.0f) {
        minecraftData += e.getName() + ",";
    }
}
```
`getDistance`で Entity 同士の距離が分かる。
近くにいる Entity の名前を`getName`で取得して、送信用の文字列に加えている。

### 表示
マインクラフト内のチャットに文字を出す。

```Java
MinecraftServer mcserv;
mcserv.getPlayerList().sendMessage(new TextComponentString("hogehoge"));
```

## 参考になりそうなサイト
- [リファレンス?](https://skmedix.github.io/ForgeJavaDocs/javadoc/forge/1.9.4-12.17.0.2051/overview-summary.html)
- [日本語で関数が列挙されてる記事](http://talestail-gamediary.hatenablog.com/entry/2016/04/07/130010)


## mod で気をつけること
バージョンによって少しずつ、ライブラリの仕様が異なる。
ライブラリのソースは、MCreatorからでも見られる。分かる人は直接読んでみてもいいと思う。

# 文字列を用意する。
あらかじめ、どのオブジェクトに関係のある文か分けてあるので、mod からのデータを元にランダムに選ぶ。
その文章の先頭単語を生成モデルに入れて、文を生成してみた。
詳しくは別記事参照。

# おまけ
表示するだけでは、味気ない。
ゆっくりに喋らせてみた。
[簡単に、こんな感じでやった(windows)。](http://tripssd.blog.fc2.com/blog-entry-8.html)

```Python
subprocess.call("start C:\hoge\softalk\SofTalk.exe /R: /W: "+"読ませたい文章", shell=True)
```

# まとめ
マインクラフトのmodは有名なので、解説記事が充実しているかと思ったが、そうでもなかった。

MCreator を使わない環境構築が面倒で、出来ていない。
ガチガチにコーディングしようと思うと不便な気がするので、どうにかしたい。

マインクラフトはかなり可能性を秘めているので、みんなもやってみてほしい。