石橋を叩いて壊すページ

アイテム名を強引に書き出した

アイテムの取引をするbukkitプラグインを製作するにあたり、アイテムの名前を取得したい。
…が、どうやらbukkitにはアイテム名を取得するメソッドは無いらしい。

GoogleでアイテムIDとアイテム名を結び付けている日本語のサイトを探すとか
クライアントのminecraft.jarの中にあるja_JP.langファイルを直接読むとか
いろいろ試行錯誤した結果、クライアントMODを作ってアイテム名を取り出すことにした。

プログラムを読み進めると、プレイヤーが「アイテムを投げるキー(デフォルトでQ)」を押すと、
MinecraftクラスのrunTick()メソッドが呼ばれるようなので、
このタイミングでforループでアイテムIDを1ずつ増やしながらアイテムを作り、名前を取得していきたい。

※以下の記載は非常に強引なアイテム名取得方法なので、
もっとうまい方法があればそっちを使ったほうがいい。

MinecraftをMCPでデコンパイルし、Client/src/net/minecraft/src/Minecraft.javaを開くと以下のようになっている。

  33行目:public class Minecraft implements IPlayerUsage
  34行目:{
        略
1365行目:    public void runTick()
1366行目:    {
        略
1671行目:            while (this.gameSettings.keyBindDrop.isPressed())
1672行目:            {
1673行目:                this.thePlayer.dropOneItem(GuiScreen.isCtrlKeyDown());
1674行目:            }
        略

ここで、1672行目と次の行の間に以下のコードを追加する。

                //////////////////
                //追加部分ここから
                
                try
                {
                    //出力先パスを画面に表示する
                    File filename=new File("itemname.csv");
                    thePlayer.sendChatMessage(filename.getCanonicalPath()+"にアイテム名一覧を出力しました。");
                    
                    //ファイルを開く
                    FileWriter file=new FileWriter(filename);

                    //アイテムIDを最大値まで1つずつ増やしつつループ
                    for(int id=1;id!=2268;id++)
                    {
                        int min=0,max=1;//メタデータのループ開始値、終了値

                        //メタデータによって異なるアイテムが得られるもの
                        switch(id)
                        {
                        case 5://木材
                            max=4;
                            break;
                        case 6://苗木
                            max=4;
                            break;
                        case 17://原木
                            max=4;
                            break;
                        case 18://葉
                            max=4;
                            break;
                        case 35://羊毛
                            max=16;
                            break;
                        case 43://重ねたハーフブロック
                            max=8;
                            break;
                        case 44://ハーフブロック
                            max=8;
                            break;
                        case 125://重ね木材ハーフブロック
                            max=4;
                            break;
                        case 126://木材ハーフブロック
                            max=4;
                            break;
                        case 24://砂岩
                            max=3;
                            break;
                        case 31://草
                            min=1;
                            max=3;
                            break;
                        case 98://石レンガ
                            max=4;
                            break;
                        case 99://巨大キノコ (茶)
                            max=16;
                            break;
                        case 100://巨大キノコ (赤)
                            max=16;
                            break;
                        case 139://丸石の壁
                            max=2;
                            break;
                        case 144://頭・頭蓋骨
                            max=5;
                            break;
                        case 155://ネザー水晶ブロック
                            max=5;
                            break;
                        case 159://色付き粘土
                            max=16;
                            break;
                        case 171://カーペット
                            max=16;
                            break;
                        case 263://石炭
                            max=2;
                            break;
                        case 351://染料
                            max=16;
                            break;
                        case 373://ポーション
                            max=0x10000;
                            break;
                        case 383://スポーンエッグ
                            min=50;
                            max=121;
                            break;
                        case 322://金のリンゴ
                            max=2;
                            break;
                            
                        }
                        
                        //メタデータを最大値まで1つずつ増やしつつループ
                        for(int meta=0;meta!=max;meta++)
                        {
                            //スポーンエッグの50~65、90~99、120以外は無効なアイテムなので無視
                            if(id==383 && !(
                                    (50<=meta && meta<=65) ||
                                    (90<=meta && meta<=99) ||
                                    (120==meta)))
                            {
                                continue;
                            }
                            //ポーションの無効なビットが立っているメタデータは無効なアイテムなので無視
                            //ちなみに無効なビットは7~13ビット目と15ビット目なので、1011111110000000(2)=49024(10)
                            else if(id==373 && ( 49024 & meta )!=0)
                            {
                                continue;
                            }
                            
                            try{
                                //アイテムを作る
                                ItemStack is=new ItemStack(id,1,meta);

                                //文字列連結用変数
                                StringBuffer sb=new StringBuffer();

                                //IDを連結
                                sb.append(Integer.toString(id));
                                sb.append(",");
                                
                                //data値を連結
                                sb.append(Integer.toString(meta));
                                sb.append(",");
                                
                                //アイテム名を連結
                                sb.append(is.getDisplayName());
                                sb.append(",");
                                
                                //アイテムの説明を取得する
                                List tips=is.getTooltip(this.thePlayer, false);
                                
                                //アイテムの説明を連結
                                for(Object str:tips)
                                {
                                    sb.append((String)str);
                                    sb.append(",");
                                }
                                
                                //改行を追加
                                sb.append("\n");

                                //ファイルに書き出す
                                file.write(sb.toString());
                            }
                            catch(Exception e)
                            {
                                //無効なID・data値でアイテムを作るとエラーが出る
                                //エラーが出たID・data値は記録せず次の処理へ進む
                            }
                        }
                    }

                    //ファイルを閉じる
                    file.close();
                }
                catch(Exception e)
                {
                    thePlayer.sendChatMessage("エラーが発生しました。");
                    thePlayer.sendChatMessage(e.toString());
                }

                //追加部分ここまで
                //////////////////

コンパイルして実行し、ゲームが始まったら適当なアイテムを一個投げると追加したコードが実行される。
そして、コンパイルされたminecraft.jarが実行されるワークディレクトリ(たぶんmcp\jars\bin\)に、itemname.csvというファイルが作成されるはず。

1,0,石,石,
2,0,草ブロック,草ブロック,
3,0,土,土,
4,0,丸石,丸石,
5,0,樫の木材,樫の木材,
5,1,松の木材,松の木材,
5,2,白樺の木材,白樺の木材,
5,3,ジャングルの木材,ジャングルの木材,
6,0,樫の苗木,樫の苗木,
:
略

試行錯誤して数日、ようやくアイテム名を取り出せた。
こんなんですが欲しい方はテキスト版HTML版をどうぞ。
V1.6.2版です。

コードの前半から手作業っぷりがにじみ出てるけど
ここを自動化することはできるのかな?
そして説明の3行目以降が英語になってしまうのはなぜなのだろう。
試行錯誤したけどどうにもならなかった。

参考にしたサイト:
Minecraft WikiのData values

2013/8/10追記:
デコンパイル時に2つのファイルを削除して実行したところ、
アイテム名やアイテムの説明が英語になってしまう問題が解決した。
また、アイテム一覧から色つき粘土のカラーバリエーションが抜け落ちていた。
上記2つの理由で、アイテム一覧のテキスト版とHTML版を更新。
またソースファイルにも色つき粘土に関する部分を追加、わかりにくかった部分を一部変更。

2015/8/22追記:
V1.8.8版を作成しました。

この記事を評価

この記事にコメント

  1. ...

【この記事にコメント】
お名前:
コメント:

Menu