提供: Minecraft Modding Wiki
2015年1月6日 (火) 12:08時点におけるMidorili (トーク | 投稿記録)による版 (Java Decompilerのサイトの移転先を追加)
移動先: 案内検索

このページでは mod がどのようにして動作しているのかを知るため、Java ソースファイルに変換するための Tips を記述します。

デコンパイルに必要なツール

Java Decompiler
http://java.decompiler.free.fr/ (リンク切れ)
http://jd.benow.ca/ (移転先)
GUIとEclipseの両方で使えるデコンパイラ。
動作が軽く、コードエクスプローラ機能もあるため使いやすい。
難読化は解除できないものの、手軽にデコンパイルするには便利。
mcp
http://mcp.ocean-labs.de/index.php/MCP_Releases
ご存知、Minecraft.jar のデコンパイラ。
Minecraft.jar に mod を導入しておけば、mod ごとデコンパイルできる。
この方法だと難読化も解除された状態でデコンパイル可能。
ただし既存classの書き換えがある場合、どれを書き換えているのか事前に調べておかないと探すのが困難。
そのままリコンパイルしても動かない事もある。特にリソースの再配置は必須。
BON(Bearded Octo Nemesis)
https://github.com/immibis/bearded-octo-nemesis
TubeStuffなどのMODの作者であるimmibis氏によって作られた難読解除器。
難読化されているMOD(コンパイル済み)から難読化解除されたMOD(コンパイル済み)を作れる。
これで難読化を解除してから上記のJava Decompilerを使うと、
難読化解除されたソースが得られる。
jad
これまでスタンダードだったデコンパイラ。
公式のページが消滅したため、現在では入手困難。

手作業で逆コンパイルをする場合

mcp 以外で逆コンパイルする場合、手作業で難読化を解除することになります。
量が多いとかなり大変なので、大型の mod の場合は mcp で逆コンパイルすることをおすすめします。
ここでは小型・単機能の mod を手作業で難読化解除する方法について記述します。

Java Decompiler等で class ファイルをソースファイルに変換する。
eclipse で強制的に class ファイルを読ませても逆コンパイルできたような…。
mcp/conf の中にある client.srg を開く。
今回は mcp62(本体ver1.2.5用)を使います。
mcp は mod の対応バージョンをよく確認して選んでください。
本体ver1.2.5用の mod なのに、mcp72(ver1.3.2用)を使ったりすると悲惨なことになります。
このファイルはテキストエディタで開けます。
この中にクラス、フィールド、メソッドが記述されています。
行の先頭が CL ならクラス、FD がフィールド、MD がメソッドになります。
ソースを開き、クラスと思われる部分を置き換える。
例)aan itemstack = ~~;
aan がクラス名になりますので client.srg から検索します("CL: aan" とかね)。
この例ですと変数名から類推可能ですが、「CL: aan net/minecraft/src/ItemStack」となります。
例)if (entity instanceof fq)
正規表現「^CL: fq 」で検索します。EntityItem ですね。
フィールドを置き換える。
例)if(!entity.G)
entity は Entity クラスのインスタンスです。
今度はクラス名から難読化後の名称を調べます。
正規表現「^CL:.*/Entity$」で検索します。「CL: nn net/minecraft/src/Entity」が見つかります。
このクラスのフィールド G ですので、「^FD: nn/G 」を検索します。「FD: nn/G net/minecraft/src/Entity/field_646_aA」が見つかります。
mcp/conf/fields.csv を開きます。テキストエディタがいいかも?
「field_646_aA」を検索すれば、フィールド名が見つかります。「isDead」です。
結果)if(!entity.isDead)
メソッド名を置き換える。
メソッド名は mcp/conf/methods.csv から探します。
メソッド名は場合によって、同一メソッド名が複数存在します。引数が異なることでオーバーロードできるためです。
その場合は引数や戻り値の型からどのメソッドかを調べてください。
例)MD: acb/a ()Z net/minecraft/src/BlockDoor/func_217_b ()Z
これは引数なし、戻り値 Z、つまり boolean のメソッドです。
カッコ内が引数の型、カッコの後ろについているのが戻り値の型です。
例)MD: acb/a (Lali;III)V net/minecraft/src/BlockDoor/func_238_a (Lnet/minecraft/src/IBlockAccess;III)V
「Lali;」は L とセミコロンの間にある ali がクラス名になります。後ろをみればわかりますが、これは IBlockAccess インターフェイスです。
I は int、V は void です。III だと int 型の引数を3つ持ちます。
よって void func_238_a(IBlockAccess b, int i, int j, int k) になります。
同様に F は float、D が double になります。

補助ツール作りました

ファイル:MinecraftObfucationHelper v0.2.zip

mcpのconfディレクトリ(client.srg, fields.csv, methods.csv があるところ)に解凍してください。
minecraftObfucationHelper.jar, dlg.xml, client.srg, , fields.csv, methods.csv が同一ディレクトリにあることを確認して jar をダブルクリック。
もしくは java -jar minecraftObfucationHelper.jar してください。

使い方:テキストボックスに難読化後のクラス名、フィールド名、メソッド名を入れてください。候補が下のテキストエリアに表示されます。
フィールド名、メソッド名は所属するクラスを絞り込める場合があります。半角スペースをあけてクラス名(難読化を解除したもの。Entity とか World とか)
を入れるとその単語を持つクラスだけに絞り込みます。

例:xd と入力→class: net/minecraft/src/World を表示。
例:Worldクラスの b というメソッドを調べたい→b World と入力→あとは戻り値、引数の組み合わせからメソッド名を判断。
例:ItemStack クラスの a というフィールドは?→a itemstack と入力→stackSize と判明。

まれに複数の候補が存在します。そのクラスのソースを見て、どれが正しいか判断しましょう。