たくさんの自由帳
Androidのお話
たくさんの自由帳
文字数(だいたい) : 10031
目次
本題
前回
差分
ドキュメント
難読化がなくなったというニュース
ついでにバージョン命名ルールも変わる
Fabric チーム側の話
遊ぶ側メリット
作る側メリット
Fabric Mojang マッピング移行
2つそろった
yarn とのお別れ
エラーを治す
Gradle Sync する
起動してみる
'useWithoutItem' overrides nothing. Potential signatures for overriding
Type argument is not within its bounds: must be subtype of 'Any'.
Argument type mismatch: actual type is 'Item.Properties?', but 'Item.Properties' was expected
Mojang マッピングしょかん
jar ファイル作成
遊ぶ側
そのほか
Gradle
ResourceLocation→Identifier 名前変更
NonNull アノテーション
おわりに
どうもこんばんわ。1.21.11 対応版がクリスマスプレゼントです。 もう年末ですね。寒い!!!
Minecraft 1.21.11が来たので自作MODを対応させました。やり?の使い方がわからんかった。。
チェストがクリスマス仕様?一体何のことやら
NeoForgeとForgeに関しては、特にそんな大きな変更はないです。
またFabricに関しても大きな変更はありません。Yarn マッピングからMojang マッピングの移行作業をやるならそこそこ大変です。
Fabricですが、Yarn マッピングからMojang マッピングへ移行したため差分が大きいです、
Comparing 1.21.10-fabric...1.21.11-fabric · takusan23/ClickManaita2
クリックまな板のソースコード Forge 1.12.2 / Forge 1.16.x / Forge 1.17.1 / Fabric 1.17.x / Fabric 1.18.x / Forge 1.18.x / Fabric 1.19.x / Forge 1.19.x / Fabric 1.20.x / Forge 1.20.x / NeoForge 1.20.x / Fabric 1....
https://github.com/takusan23/ClickManaita2
Comparing 1.21.10-neoforge...1.21.11-neoforge · takusan23/ClickManaita2
クリックまな板のソースコード Forge 1.12.2 / Forge 1.16.x / Forge 1.17.1 / Fabric 1.17.x / Fabric 1.18.x / Forge 1.18.x / Fabric 1.19.x / Forge 1.19.x / Fabric 1.20.x / Forge 1.20.x / NeoForge 1.20.x / Fabric 1....
https://github.com/takusan23/ClickManaita2
Comparing 1.21.10-forge...1.21.11-forge · takusan23/ClickManaita2
クリックまな板のソースコード Forge 1.12.2 / Forge 1.16.x / Forge 1.17.1 / Fabric 1.17.x / Fabric 1.18.x / Forge 1.18.x / Fabric 1.19.x / Forge 1.19.x / Fabric 1.20.x / Forge 1.20.x / NeoForge 1.20.x / Fabric 1....
https://github.com/takusan23/ClickManaita2
Fabricチームが書いてくれた資料です。
今回はMojang マッピングへの移行を行うので、難読化がなくなった記事も。
NeoForgeも。今の段階のFabricと違ってMojang マッピングを使っているのでその話があります。
難読化されなくなる。
今まではMinecraftの.jar ファイルを何らかの方法で.java コード相当に復元したとしても、でたらめな名前が表示されるだけになると思う。やったことないので知らない。
目的としては、でたらめな名前に置き換えることで解析をある程度妨害できるので、中で使っているプログラムや画像、音声なんかを引っこ抜かれないようにするため。だと思ってる。
(次点にでたらめな短い名前に置き換えればコード自体が小さくなり、ファイルサイズ自体が小さくなるのも見込めますが、多分それが目的じゃないと思うので)
ところが難読化を辞めるとのこと。MODユーザーのためだって。
お金取ってるゲームでこの判断がみんなにも出来るだろうか。
これまでにもMODユーザーには結構親身に対応してくれていて、MojangはMinecraftを難読化しつつも、数年前から難読化を解除し元のプログラムに戻すためのファイルを公開していました。
(マッピングファイル、難読化する前の名前とした後の名前の関連付けを記録したファイル)
が、今回は難読化自体をやめてしまおうと。
大きなニュースに思えますが、遊ぶ側は特に影響ないです。
また作る側も、難読化されないので元のMinecraftコードが見やすくはなると思う・・・今までは各自マッピングファイルを使って難読化前相当のコードを生成してたのでその手間がなくなる。くらい。
NeoForgeとForgeはすでにMojang 公式マッピングファイルを利用していたため、置き換えが大変みたいな問題ないはず?Fabricは自分たちでマッピングファイルを作っていました。そして今回、難読化を辞めたバージョンより自分たちで作ったマッピングを廃止することを決定したそうです。
まずはSNAPSHOTリリースから難読化を解除した版が配信されるとのこと。
いつ正式版に適用されるかわからないので、1.21.11の今急いでやる必要もない。が、そこまで大変じゃなかったです(後述)
1.21.11の次は26.1になる。iOSみたいになったね。
これが俗に言うカレンダーバージョニングですか、今よりわかりやすくなるならそれでいいと思います。
これは完全に余談ですが、公式の声明をみてください。
FabricのmoddingではMojang 公式マッピングではなく、自分たちで作っていたYarn マッピングがデフォルトで採用されていました。(moddingテンプレートがそれだったはず)
同じMODでも、FabricのコードとNeoForge / Forgeでのコードを見比べると、部分的に名前が違って見えるのは、このマッピングが違うから。
難読化されたクラス名、関数名にどんな名前をつけるか。の関連付けをしてくれていたのが、このYarn / Mojang マッピングファイルだったわけですね。
Yarn マッピングはIntermediaryというプロジェクトが生成した賜物でした。
このIntermediaryは、難読化された関数、クラスに、人間がわかる名前をつける機能だけでなく、バージョンを跨いで人間が読める同じ名前を付ける機能もありました。
難読化は新しいバージョンが公開されるたびに行われます。よって、例えばBlocks.jarは今のバージョンではab.javaになっていても、新しいバージョンではaab.javaになるかもしれません。Intermediaryはちゃんとクラスや関数の中身を見て前のバージョンと同じなら同じ名前をつけてくれました。
ある程度MODで遊んだことがあればわかるかもしれないですが、バグ修正バージョンで同じMODファイルがなぜか遊べるみたいな。
バグ修正バージョン対応版を開発者が出さなくても、なぜか動いているみたいな。この裏側にはIntermediaryがいたわけ・・・
ところが、難読化がされなくなるということは、Yarn/Mojang マッピング自体がそもそも不要になることを意味します。
そのため、Yarn マッピングは廃止されることが発表されました。既存のバージョン向けには残るが、新しくリリースされることはなく、テンプレートや Fabric ドキュメントでは Mojang マッピングを採用するようになります。
ほぼない。しいていえば
クラッシュしたときのスタックトレースが意味のある文字列になる。のと、Minecraftの挙動を調べるとかはわんちゃん出来るんじゃないでしょうか。調べるにしろEULAが引き続き適用されるとは思いますが。
難読化されなくなるため、Yarn / Mojang マッピングからMinecraftのソースコードを復元する手間がなくなるはず。GradleにあるgenSourcesする手間が不要に!
あとはマッピングファイルからソースの復元とは違い、そもそも難読化されないので、関数の中で使われている変数名(ローカル変数)の名前がそのまま表示されるようになるはず?。ProGuardによらないと思うが、マッピングファイルの手が及ぶのはクラスとクラスの関数、変数まで。それ以上の、関数内の変数名は難読化されている以上見れなかったんじゃないかな?
正直、大きく取り上げた割には時間が節約できるとか、関数の中の変数の名前が見れるとかなので、実はそこまで大騒ぎすることでもない。
本家
私はKotlinで書いているので、Loom Gradle プラグインではなく、Ravel IDEA プラグインの方を使うことにした。Javaのみの場合はどちらでも良いらしい。
上の手順にしたがって入れます。zipファイルがダウンロード出来るので、IDEAの設定のプラグインの設定を開いて、歯車を押してInstall Plugin From Diskを選び、さっきのzipを読み込む。
次に、yarn マッピングとmojang マッピングのファイルをダウンロードします。
から、今使っているyarn マッピングのバージョンを選択してダウンロード。gradle.propertiesを開いて、ここの値と同じものを探します。
minecraft_version=1.21.11
yarn_mappings=1.21.11+build.3 # ←これ
loader_version=0.18.4
loom_version=1.14-SNAPSHOT
fabric_kotlin_version=1.13.8+kotlin.2.3.0見つけたら開いて、その中のmergedv2.jarファイルをダウンロードします。
ダウンロードできたら、7zip等を使い展開し、mappingsフォルダのmappings.tinyを探します。このファイルが必要です。
JSON オブジェクトがいくつもありますが、自分のバージョン(今回1.21.11)が書いてあるJSON オブジェクトを探し、その中のurlの値に書いてあるアドレスにアクセスします。
開いたら、サイト内検索でclient_mappingsで検索をかけます。
見つかったら同様にurlの値のアドレスにアクセスしてください。できたら、謎の文字がいっぱいでてくるので、何でも良いのでダウンロードしてください。
一番楽なのはWebサイトを右クリックして名前をつけて保存するのがいいかと。
適当にファイルを選んで右クリックし、Refactorを押して、Remap Using Ravelを押します。
するとこんなダイアログがでます。
まず左側の+を押します。Add Local File Mappting...を選びます。選んだら、ファイルを選ぶ画面になるので、まずはyarnの方を読み込ませます。mappings.tinyですね。
選んだら、それぞれ以下のように選びます。
| なまえ | あたい |
|---|---|
| Source Namespace | named |
| Destination Namespace | official |
出来たらOK、同様にMojangのclient.txtを選び、以下のように選びます。
| なまえ | あたい |
|---|---|
| Source Namespace | target |
| Destination Namespace | source |
最後、右側にモジュールが表示されています。一個ずつ選んで+ボタンを押しましょう。すべてやります。
これでOKを押すと処理が始まります。
build.gradleファイルを開き、以下のyarn_mappingsの1行をofficialMojangMappings()に置き換えます。
- mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
+ mappings loom.officialMojangMappings()gradle.propertiesファイルのyarn_mappingsの値も使わなくなったので削除できます。
- yarn_mappings=1.21.11+build.3IDEAを使っている場合は、左の虫メガネボタンを押すか、Shift + Ctrl + Fキーを同時押しするかで全体検索を出すことが出来ます。
ここで、TODO(Ravel)で検索をかけることで、自動で置き換えできなかった箇所が見つかるという仕組み。
package nameがおかしい言われてますが、確かに存在するのでよくわからない。
あと普通にJavaコードのimport間違えている箇所があるのでそれは手動で直した。
IDEAの右にあるゾウのボタン(Gradle)を押し、その中にある更新ボタンみたいなのを押します。
これをするまでソースコードが赤いままになると思う。
これで終わりなはず・・・!
再生マークの隣りにあるドロップダウンメニューをMinecraft Clientにしてチャレンジ・・・
しっぱい!w
コード直します。
'useWithoutItem' overrides nothing. Potential signatures for overriding:
fun useWithoutItem(blockState: BlockState, level: Level, blockPos: BlockPos, player: Player, blockHitResult: BlockHitResult): InteractionResultNonNullだったらしい。シグネチャ違い
override fun useWithoutItem(blockState: BlockState?, level: Level?, blockPos: BlockPos?, player: Player?, blockHitResult: BlockHitResult?): InteractionResult?を
override fun useWithoutItem(blockState: BlockState, level: Level, blockPos: BlockPos, player: Player, blockHitResult: BlockHitResult): InteractionResultしたらなおった。ところでmoddingにおいてKotlinとJava相互のNull安全の体験、こんなにも良かった記憶ないんだけど。
と思って調べたらNull系アノテーションがJSpecifyになったらしい。相互利用が良くなったのはこれのおかげかも知れない
<T>だとAny?、nullを許容できてしまうので、<T:Any>してNonNullの型のみにする
private fun <T : Any> applyEffects(
entries: List<ConditionalEffect<T>>,
lootContext: LootContext,
onEffect: (T) -> Unit
) { }同様にNonNullが保証されたらしい
class ClickManaitaBaseItem(settings: Properties?, private val dropSize: Int = 2) : Item(settings)が
class ClickManaitaBaseItem(settings: Properties, private val dropSize: Int = 2) : Item(settings)Kotlinを使っている場合、?(Nullable)を消していく作業
NonNullなの?信じるよ?Levelって名前なんだけど由来何なんだろう、?
yarnのが好きだったiとかjとかの引数名の時があるんだけど手動で難読化してるの?
作る側はこれまで通りgradleのbuildで良いはず。
遊ぶ側も同様にMODのjarファイルとFabric APIと、私みたいにKotlinで書いている場合はFabric Language Kotlinをmodsフォルダへ入れれば起動できた。
ここからはFabric、NeoForge、Forgeで同じ!
Fabric9.2.1NeoForge9.2.0ForgeNeoForgeやForgeみたいにMojang マッピングを使っている場合の話。
private static final ResourceLocation ID_CLICKMANAITA_WOOD = ResourceLocation.fromNamespaceAndPath(ClickManaita.MOD_ID, "clickmanaita_wood");
private static final ResourceKey<Item> KEY_CLICKMANAITA_WOOD = ResourceKey.create(Registries.ITEM, ID_CLICKMANAITA_WOOD);
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(ClickManaita.MOD_ID);
public static final DeferredItem<ClickManaitaBaseItem> CLICKMANAITA_WOOD = ITEMS.register(KEY_CLICKMANAITA_WOOD.location().getPath(), () -> /* 省略... */ );ResourceLocationをIdentifierに置き換える。location()もidentifier()に置き換える
private static final Identifier ID_CLICKMANAITA_WOOD = Identifier.fromNamespaceAndPath(ClickManaita.MOD_ID, "clickmanaita_wood"); // ここと
private static final ResourceKey<Item> KEY_CLICKMANAITA_WOOD = ResourceKey.create(Registries.ITEM, ID_CLICKMANAITA_WOOD);
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(ClickManaita.MOD_ID);
public static final DeferredItem<ClickManaitaBaseItem> CLICKMANAITA_WOOD = ITEMS.register(KEY_CLICKMANAITA_WOOD.identifier().getPath(), () -> /* 省略... */ ); // ここところで、このIdentifierはFabricのYarn マッピングで使われていた名前なんですよね。以下参照Mojang マッピングはResourceLocationだった。が、なぜか今Fabricと同じ名前に変わった。
private val ID_CLICKMANAITA_WOOD = Identifier.of("clickmanaita", "clickmanaita_wood")
private val KEY_CLICKMANAITA_WOOD = RegistryKey.of(RegistryKeys.ITEM, ID_CLICKMANAITA_WOOD)
val CLICKMANAITA_WOOD = ClickManaitaBaseItem(settings = Item.Settings().registryKey(KEY_CLICKMANAITA_WOOD), dropSize = 2)
Registry.register(BuiltInRegistries.ITEM, KEY_CLICKMANAITA_WOOD, CLICKMANAITA_WOOD)NeoForgeチームも言っていますが、どういう風の吹き回しでこのような改名になったのかは中の人しかわからないでしょう。
ResourceLocationよりも短いから採用した説Fabric製MODのMojang マッピングの移行時の混乱を避けるため説Yarn マッピングのことを忘れないようにするため説
使ったことがなくてよくわからないですが、JSpecifyってライブラリの@NonNullアノテーションが採用されたらしいです。Kotlinのnull安全機能は、Kotlin言語で書くだけでなく、Java言語でも@NonNullを書いたコードに対しても発動します。なのでMojang マッピングへの移行をしつつ、NonNullに書き直すようにする必要もあります。
Optionalを駆逐できるようになるのかはわかりません。
わたしてきにはOptional#isPresent()がnullable != nullよりも優れてるとはあんまり思わないので、アノテーション付けるだけでいい感じに支援されるならもうそれでいいと思った。
IDEAのStart Free Trialボタンめっちゃ緑色で自己主張してて草