どうもこんばんわ。
一応言っておくと定住先でよく使われる1.12.2ではなく1.21.2です。
(最近はどこに定住しているのか知らない)
本題
自作 MOD のMinecraft 1.21.2
への移行メモです。
移行メモ振り返ってみたけど、1.20.6
から全部今年なの・・・
今回も地味に大変だった。前回のエンチャント作り直しよりはマシかな?
レシピ周り(ServerWorld#getRecipeManager
とか)触ってなければ多分今回のアップデートは怖くない。はず。
今回も今回とてFabric
の方々がまとめてくれているので、どこが変わっているかはそれを見ればいいです。
https://fabricmc.net/2024/10/14/1212.html
1.21.3
はバグ修正バージョンらしいので、1.21.2
からの対応は無いと思います。
前回
https://takusan.negitoro.dev/posts/minecraft_mod_1_21_migration/
レシピの JSON が変更されています
Fabric
チームがまとめてくれてないですが、JSON
の構造が変更されています。
https://github.com/takusan23/ClickManaita2/blob/1.21.3-fabric/src/main/resources/data/clickmanaita/recipe/clickmanaita_wood.json
オブジェクト{ "item": "アイテムID" }
じゃなくて、アイテムのID
を渡すようになりました。
不定形レシピも同様です。
https://github.com/takusan23/ResetTable/blob/1.21.3-fabric/src/main/resources/data/resettable/recipe/reset_table_block.json
アイテム、ブロックの登録前に ID を渡す必要があります
1.21.1
時代のコードを貼り付けるとこんなエラーが出る。
これは、Minecraft
にアイテムを追加する前までに、アイテムの設定(食べ物かどうか、スタック数)へアイテムID
を設定しておく必要があるということです。
いままでは、Minecraft
に登録する際に、アイテムID
とアイテムのクラスのインスタンスを渡せば登録できたのですが、もう一箇所、アイテム設定の時点でも渡す必要があります。
Fabric + Kotlin
の場合は多分こんな感じで、Item.Settings#registryKey
を呼べば良いはず。
Forge
の場合は多分こんな感じで、Item.Properties#setId
を呼べば良いはず。
ActionResult
型推論に頼っている場合は明示的に型を渡さないといけなくなりそうです。
ブロックエンティティ
BlockEntityType.Builder
は削除された?FabricBlockEntityTypeBuilder
になったそうです。
レシピのシステムの変更
大幅に変わってそう、これのせいでResetTable
はかなりの書き直しが必要だった。
一番でかいのが、サーバー側のみレシピが参照できる点。クライアント側のコード(例えばGUI
のテクスチャを描画するクラス)ではレシピにアクセスできなくなりました。
World
クラスにレシピに関してのクラスがあったのですが、World
の中でもServerWorld
にしかレシピのクラスがゲットできなくなってしまったので、まずはif (world instanceof ServerWorld)
する必要があります。
サーバー側で処理されるクラスの場合には(Entity
とかはサーバー側なのでServerWorld
になると思う)、instanceof
でServerWorld
かどうか見れば特に問題はないはず。
詳しくはこの辺:
https://fabricmc.net/2024/10/14/1212.html#serverworld-parameters
一方GUI
のテクスチャを描画する、クライアント側にしか無い場合はレシピにアクセスできなくなりました。
自作MOD
ではレシピが存在するかをGUI
側で確認して、無い場合は無いというテキストをGUI
に描画するためクライアント側でもレシピを使っていた。
困った。
仕方ないので、サーバー側でレシピがあるか確認して、戻せない場合にはクライアント側へFabric
のNetworking API
で通知するようにしました。
シリアライズする必要があって面倒。
Networking API で置き換えた話
本家のNetworking API
の説明で十分な気がするけど一応。
https://fabricmc.net/wiki/tutorial:networking
今回はレシピが戻せない理由をクライアント側へ送ろうと思います。
戻せない理由はenum(初見で読めない)
で定義済みで、enum
のシリアライズにはordinal()
で順番を使おうと思います、、、
まずはネットワークで使う一意のID
を作ります。
つぎにサーバー側
←→クライアント側
でやり取りするためのクラスを作ります。
Kotlin
ならdata class
、Java
ならrecord
で作って、CustomPayload
インターフェース(?)を実装します。
また、わかりやすいので、ここにシリアライズ、デシリアライズ用の処理もstatic
で用意しておくことにします。
PacketByteBufs
っていう書き込むクラスが渡されて、シリアライズの際はそのクラスに順番に書き込んでいく。writeInt()
とか、あとMinecraft
で使いがちのブロック位置を書き込むwriteBlockPos
なんてもあります。
デシリアライズの時は書き込んだPacketByteBufs
が渡されます。書き込んだ順番と同じ順番でread
していけば良いです。
次はサーバー側とクライアント側でネットワークを登録します。
ClientPlayNetworking.registerGlobalReceiver
で、サーバー側から送られてきたデータを受け取ることができます。
あとはサーバー側でクライアント側に送る処理を書けば良いはず。
サーバー側である必要があります。多分
おわりに
差分をおいておきます。
- ClickManaita Fabric 1.21 → 1.21.2
- ClickManaita Forge 1.21 → 1.21.2
- ResetTable Fabric 1.21 → 1.21.2
以上です。88888888。ノシ