【Minecraft】Mod開発の必須技術「Mixin」とは？

# はじめに

Minecraft Java版のMod開発における「Mixin」をご存知ですか？

**MixinはModdingをする上での必須技術**と言っても過言ではありません。

この記事では、このMixinについて簡単にご紹介したいと思います。

### 対象読者

* ForgeまたはFabricのMod開発をしている
* Mixinについて知らない

### この記事では扱わないこと

* Mixinの環境構築、コーディングの解説
* Forge、FabricなどのMod作成の解説



# Mixinとは？

Minecraft Java版の既存のソースコードを、実行時に変更することができるフレームワークです。

* Mod開発で利用される
* SpongePoweredが開発

https://github.com/SpongePowered/Mixin

# できるようになること

### Mixinを使わない場合

Mixinを使わないでMod開発をする場合、

* イベントシステム
* タスクシステム
* イニシャライザー

などの、APIよりあらかじめ提供されているエントリーポイントに沿って、オリジナルの処理を加えていくことになるでしょう。

しかしながら、こんなときはどうすればいいでしょうか？

**「○○の部分に処理を加えたいのに、いい感じのイベントがない！！」**

**「既存の○○を無効化したいのに、APIでサポートされてない！！」**

このように、APIでサポートされていない機能に対してModを適用する場合、複雑な実装になりがちです。

### Mixinで解決

Mixinはこれらの問題を解決します。
Mixinにより可能になる主なことを、まとめます。

* **ソースコードの任意の場所に、自由に処理を加えられる**

* **ソースコード上のメソッドの呼び出しや、フィールド、変数へのアクセスを書き換えられる**

* **privateなメソッド、フィールドへのアクセサーを追加できる**

※正確には他にもあります

ひとつずつ簡単に説明します。

### 1. 【Inject】処理の追加する

Mixinでは`Inject`と呼ばれます。

これは、マインクラフト内部の`method()`の中へ、オリジナルの処理`injected()`を追加する例です。

```java
  // マインクラフト内部のメソッド
  public void foo() {
    // Modにより追加された処理
+   injected(new CallbackInfo("foo", false));
    // 元からある処理
    doSomething1();
    doSomething2();
    doSomething3();
  }

// https://fabricmc.net/wiki/tutorial:mixin_examplesより引用
```

他にも、次のようなことも可能です。

* 任意の場所で`return;`する
* メソッドの返し値を書き換える


### 2. 【Redirect】呼び出しを変更する

Mixinでは`Redirect`と呼ばれます。

```java
  // マインクラフト内部のメソッド
  public void foo() {
    doSomething1();
    Something something = new Something();
    // 元からある処理は削除される
-   int i = something.doSomething(10);
    // Modにより定義された処理に置き換わる
+   int i = injected(something, 10);
    doSomething2();
  }

// https://fabricmc.net/wiki/tutorial:mixin_examplesより引用
```

正確には異なる機能ですが、似たようなもので次のものもあります。

* `int i = 4;`の`4`といった定数の部分を置き換える`ModifyConstant`
* `doSomegthing(i);`の`i`といったメソッドの引数を置き換える`ModifyArg` `ModifyArgs`
* ローカル変数を書き換える`ModifyVariable`

### 3. 【Accessor】privateへのアクセサーを追加する

Mixinでは`Invoker`や`Accessor`と呼ばれます。

__privateなメソッドを呼び出せるようにする__

```java
EndermanEntity enderman = ...;
// EndermanEntityInvokerを経由して、通常では呼び出せないprivateメソッドを呼び出せる
((EndermanEntityInvoker) enderman).invokeTeleportTo(0.0D, 70.0D, 0.0D);

// https://fabricmc.net/wiki/tutorial:mixin_accessorsより引用
```

__privateなフィールドにアクセスする__
```java
// 通常ではアクセス出来ないフィールド、itemUseCooldownにアクセス
int itemUseCooldown = ((MinecraftClientAccessor) MinecraftClient.getInstance()).getItemUseCooldown();

// https://fabricmc.net/wiki/tutorial:mixin_accessorsより引用
```

__「リフレクションを使えばいいのでは？」__

と言われそうですが、リフレクションにはない次のメリットがあります。

* リフレクションに比べて早い
* アクセサーの定義はコンパイル時なので型安全



# 最後に

Mixinを扱えるようになると、Modで作れるものが大幅に増えます。
まだまだ日本語の文献が少ない状況ですが、みなさんも是非学んでみてください。

### おまけ

Mixinの実装はKotlin、Scalaなどで行えません；；
一度はJavaの沼から抜け出した皆さんも、再びJavaを書くチャンスです！やったね！

あと詳しくは知らないけど、Mixinはサーバープラグインにも適用できるらしい。



# 参考資料&補足資料

### FabricMCによる解説

今すぐMixinを使いたいならこっちがおすすめ。

https://fabricmc.net/wiki/tutorial:mixin_introduction

### 開発元SpongePoweredによるドキュメント

技術的な内容ばかりで、実践的なことは書かれてないかも。

https://github.com/SpongePowered/Mixin/wiki

### 数少ない日本語文献

https://naari.hatenablog.com/entry/2022/01/15/015043

https://www.youtube.com/watch?v=Fki_4UYwaBs

https://qiita.com/sae220/items/b48469840756cc6918dd



# 宣伝

### Youtubeチャンネル

自作Modを遊ぶゆっくり実況動画を投稿しています。
登録者は15万人ほどです。

https://www.youtube.com/@gorayan

### X（旧Twitter）

技術に関する投稿をしています。

https://x.com/Gora65535

### Discordサーバー

マイクラ技術系をメインに交流できるサーバーです。
多少内輪ノリがありますが、興味があればどうぞ。

https://discord.gg/Dh825d7bmj