Modding時の備忘録集

# はじめに

この記事にはマイクラのModdingの最中に得られたテクニックや知識等をメモ程度に書き連ねていく記事です。
（備忘録あるたびに新記事作るのは気が引けたため）

# 1.12

## Item.onItemRightClick

ブロックに向かっても空に向かってもちゃんと呼ばれる。
昔Moddingしたときに使ったやつはそれぞれで別のメソッドだった気がするけど記憶があいまい。
まあこれを使っておけばよい。

## WorldTypeとWorldProvider

自作のWorldProviderはそのディメンションに行けばいつでも使われる。
自作のWorldTypeはワールド生成時の設定で決めたものにしかならない。
そのため、自作BiomeProviderやChunkGeneratorをWorldType側で呼ぶとそのWorldTypeが選ばれた時しか使われない。

常にそのディメンションで使いたいのが普通だからWorldProvider側に書くのが吉か。

## ディメンション移動

```java
server.getPlayerList().transferPlayerToDimension((EntityPlayerMP) player, DIMENSION_ID, new ITeleporter() {
            @Override
            public void placeEntity(World world, Entity entity, float yaw) {
                    BlockPos spawnPos = BlockPos.ORIGIN;
                    entity.setLocationAndAngles(spawnPos.getX() + 0.5, spawnPos.getY(), spawnPos.getZ() + 0.5, entity.rotationYaw, 0.0F);
                    entity.motionX = 0.0D;
                    entity.motionY = 0.0D;
                    entity.motionZ = 0.0D;
            }
        });
```
ITeleporterを自作せずに横着するとクラッシュ。


## The One Probeの紙

PlayerLoggedInEvent（priority指定なし）で渡される。
登録順によっては消しそびれるのでpriorityのLOWとかで消すのが良いか。

## blocksとblockフォルダ

1.12のリソース（パック）はmodels内が`block`でtextures内が`blocks`。
itemも同様。
~~本当にどうにかならなかったのか~~
どっかのバージョンからはblockに統一された。
~~modelsやtexturesは複数形のままなのか~~

## 自作Particle

全部ここに書いてある。
https://jabelarminecraft.blogspot.com/p/minecraft-modding-spawning-custom.html
（他のチュートリアルも大体ここに書いてある）
ポイントなのはバニラと自作パーティクルで表示する際の呼び出し方が違うこと。

## 自作アニメーション3Dモデル

GeckoLibを使うのが良い。（1.12.2はGeckolib3）
BlockBenchにPluginもあるのでかなり便利。
今はGeckoLibのGitHubのwiki見ながら実装中。
とりあえず簡易やり方：
- BlockBenchでモデル・テクスチャ・アニメーション作成
- それらをエクスポートしてresourcesに入れとく
    ※入れる場所指定あり（**ファイル名に大文字禁止…**）
    - モデル：`assets/<modid>/geo`内（サブフォルダ含む）
    - テクスチャ：`assets/<modid>/textures`内（サブフォルダ含む）
    - アニメーション：`assets/<modid>/animations`内（サブフォルダ含む）
- repositoriesにGeckoLibのmaven追加
    ```
    repositories {
        maven {
            name = 'GeckoLib'
            url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' 
        }
    }
    ```
- dependenciesにGeckoLib追加（これはapi？implementation？）
    とりあえず`api rfg.deobf("curse.maven:geckolib-388172:4020277")`としといた
    deobfでいいのかも分からないけどとりあえずこれで（実環境でも動作確認済み）
- Modのメインクラスのコンストラクタで`GeckoLib.initialize();`を呼ぶ
    開発環境ではこれを忘れてても動作するが、いざ実環境だとレンダリング時にクラッシュ

---以降はブロックの話---

- TileEntityはIAnimatableを実装
- TESRはGeoBlockRendererを継承
- AnimatedGeoModelを継承したクラスを作る（TE毎）
- それ以外はTESRの作成の話
- 特にGeckoLib特有の登録作業は不要（TESR登録で十分）

apiにexampleソースコードも入ってるので中身はそれを参考に。
アニメーション切り替え等はまだよく分からないけど何とかなるでしょうきっと。

## GTCEu's Buildscripts

1.12.2時代の最新のMDK。
Forge公式より便利なのでForge公式を使う理由がない。

### dependenciesやrepositories

build.gradleから分離してそれぞれ単ファイル化されている。
つまりbuild.gradleを書き換えなくて済む。
加えてaddon.gradleというファイルを作ればそれの中も読み込んでくれる。
~~つまりbuild.gradleを書き換えなくて済む。~~

## dependenciesの追加

書ける場所が3つある。（情報が正しいかの検証がまだなので記事にしてない）
- dependencies.gradle（GTCEu's Buildscriptsじゃなければbuild.gradle）
    ここに書くと開発時に対象Modのクラスにアクセスできる
    逆に無しで開発する方がムズイ
- `@Mod`のdependencies
    ここに書いとけばMod起動時に○○が不足してるよ！とかメッセージを出す
    書かない&対象Mod入ってないと大抵クラッシュするのでユーザに親切にしてあげるために書く
    ~~拙作Modでも書き忘れてるの結構ある~~
- mcmod.infoのdependencies
    用途不明
    ゲーム内で表示されてる様子は無さそう（少なくともMod Listでは）
    もしかしてサードパーティーランチャーが依存関係をここで確認してたりするのか？

## TileEntity作成

BlockはITileEntityProviderを実装するだけでよい。
前はhasTileEntityだのなんだのをOverrideした記憶があったけどもっと簡単にできる。

## TESR(TileEntitySpecialRenderer)使えるようになるためのメモ

- 要素作成
    - Block作成
        - BlockのcreateNewTileEntityをOverride
        - BlockのgetRenderTypeをENTITYBLOCK_ANIMATEDに
    - TileEntity作成
        - 中身は空でよい
    - TESR作成
        - renderをOverrideして何かしらレンダリング
- 登録
    - Block登録
    - TileEntity登録（GameRegistry.registerTileEntity）
    - TESR登録（ClientRegistry.bindTileEntitySpecialRenderer）※ClientOnly
- まだやってないので分からない
    - アイテムのモデル
    - パーティクル系（破壊・落下・上を走る）

## 東西南北とXZ

いつも忘れるのでメモ。
- 東：+X
- 西：-X
- 南：+Z
- 北：-Z

## IBlockStateのwithProperty

IBlockStateはImmutableなのでちゃんと代入しよう。

## プレイヤー等が受けるダメージに干渉したい

LivingAttackEventを使おう。
イベントハンドラの使い方記事はまだ書いてないのであしからず。

## Yaw/Pitch

Yaw : Y軸時計回り、-180°~180°、南が0°、西が90°、東が-90°
Pitch : 上下回転、-90°~90°、水平が0°、下が90°、上が-90°

## Tessellator

まとめてレンダリングするために使ってるやつ
内部的には
1. 頂点情報を配列に詰め込み、
1. `glEnableClientState`で有効化し、
1. `glVertexPointer`でポインタを渡し、
1. `glDrawArrays`で描画（転送込み）
1. (`glDisableClientState`で後片付け)

vboのようにあらかじめ転送しておいて毎フレーム使いまわすような使い方は想定していない？
~~フィールド名は`vboUploader`なのに~~

glDrawArraysなので設定値(座標、色、テクスチャUV、法線を除く)が同じ図形を一気に描画するのには向くが、`GlStateManager`を呼ぶようなレンダリングの設定・状態を変更させながら描画するのには向かない。

# Intellij IDEA

## 保存時自動フォーマット

使ってたプラグイン(Save Actions Tool)が死んでしまったので暫定的にエディタ本体の機能を使用。
場所は`設定>ツール>保存時のアクション`。
プロジェクト作るたびにリセットになるのが困る。
あと、環境構築編で説明書かねば。

# Fabric

## Access Widners

ForgeでいうAccess Transformer。
Access Transformer同様にバニラのコードにしか効果が無い。
（その注意書きはなぜか英語版のwikiにしか書いていない）

# MCバージョンとJavaバージョン

いつも分からなくなるのでメモ


|MC|Java|
|:-:|:-:|
|1.7.10[^238564]~|8|
|1.17[^962957]~|16|
|1.18[^298435]~|17|
|1.20.5~|21|

[^238564]: 1.7.10より古いModを扱うことはきっと無いだろう
[^962957]: 正確には21w19aから
[^298435]: 正確にはPre-release 2から