◆総合◆Modderのための雑談所

クライアント/サーバーMODの開発に関する話題、技術交換はこちらで。質問は質問フォーラムへお願いします。
  • (PostNo.110768)

OptiFineLocalizeFixの作り方

投稿記事by takanasayo » 2013年6月30日(日) 09:20

OptiFineLocalizeFix引継ぎ希望者がいないので、1.5.2を例にして更新方法を晒してみる。

:not: 準備:開発環境構築
  1. mcpを使えるようにする。
  2. minecraft.jar に OptiFineをぶち込む。
  3. デコンパイルする。
    昔と違って、今はこれだけで環境構築できる。
    マメ知識
    昔はデコンパイルしたソースでエラーしている部分を修正して、updatemd5する必要があった。
    ちなみにminecraft.jarにOptiFine入れるときは、OptiFineバージョンアップ時にも同じ環境使えるように、mcpatcherなんかを利用して導入すると良い。
    mcpのjarsフォルダ内でMCPatcher使うには、
    コード: 全て選択
    set APPDATA=%CD%\
    mcpatcher.exe

    のバッチファイルを作って、MCPatcherと一緒にjarsフォルダに放り込めば良い。


    :not: 準備:書き換えファイルの収集
    1. srcフォルダから書き換えるファイルを集める。
    2. 念のためバックアップする。
      ファイル収集自動化
      mcp以下に作業用フォルダを作る。
      ここでは、/mcp/mymods/OptifineLocalizeFix/ とする。

      _FileList.txt を作成する。
      内容:
      コード: 全て選択
      EnumOptions.java
      GameSettings.java
      GuiAnimationSettingsOF.java
      GuiDetailSettingsOF.java
      GuiOtherSettingsOF.java
      GuiPerformanceSettingsOF.java
      GuiQualitySettingsOF.java
      GuiVideoSettings.java


      _FileCopy.batを作成する。
      内容:
      コード: 全て選択
      set dir1=..\..\src\minecraft\net\minecraft\src\
      set dir2=_backup\
      :
      for /F %%i in ( _FileList.txt ) do copy %dir1%\%%i %dir2%
      pause


      _FileCopy.bat を実行する。
      (_backup/ フォルダに必要なファイルがコピーされる)



      :not: EnumOptionsの書き換え
      一番重要な部分。
      ここには各種設定項目に表示されるStringデータが列挙型で定義されているので、これをローカライズ用の識別子に置き換える。(具体的には37行目以降の定義部分)
      私は「optifine.設定名」という識別子に置き換えている。
      コード: 全て選択
      例:
      FOG_FANCY("Fog", false, false),
       ↓
      FOG_FANCY("optifine.fog_fancy", false, false),

      ただし、AO_LEVELとRENDER_DISTANCE_FINEだけは、バニラのローカライズ識別子を指定している。
      コード: 全て選択
      AO_LEVEL("options.ao", true, false),
      RENDER_DISTANCE_FINE("options.renderDistance", true, false),

      OptiFineに新しい設定が増えた場合、ここに項目が増えるので、そのつど識別子に変換する。
      書き換え後
      コード: 全て選択
         
          AO_LEVEL("options.ao", true, false),
          RENDER_DISTANCE_FINE("options.renderDistance", true, false),
         
          FOG_FANCY("optifine.fog_fancy", false, false),
          FOG_START("optifine.fog_start", false, false),
          MIPMAP_LEVEL("optifine.mipmap_level", false, false),
          MIPMAP_TYPE("optifine.mipmap_type", false, false),
          LOAD_FAR("optifine.load_far", false, false),
          PRELOADED_CHUNKS("optifine.preloaded_chunks", false, false),
          SMOOTH_FPS("optifine.smooth_fps", false, false),
          CLOUDS("optifine.clouds", false, false),
          CLOUD_HEIGHT("optifine.cloud_height", true, false),
          TREES("optifine.trees", false, false),
          GRASS("optifine.grass", false, false),
          RAIN("optifine.rain", false, false),
          WATER("optifine.water", false, false),
          ANIMATED_WATER("optifine.animated_water", false, false),
          ANIMATED_LAVA("optifine.animated_lava", false, false),
          ANIMATED_FIRE("optifine.animated_fire", false, false),
          ANIMATED_PORTAL("optifine.animated_portal", false, false),
          LAGOMETER("optifine.lagometer", false, false),
          AUTOSAVE_TICKS("optifine.autosave_ticks", false, false),
          BETTER_GRASS("optifine.better_grass", false, false),
          ANIMATED_REDSTONE("optifine.animated_redstone", false, false),
          ANIMATED_EXPLOSION("optifine.animated_explosion", false, false),
          ANIMATED_FLAME("optifine.animated_flame", false, false),
          ANIMATED_SMOKE("optifine.animated_smoke", false, false),
          WEATHER("optifine.weather", false, false),
          SKY("optifine.sky", false, false),
          STARS("optifine.stars", false, false),
          SUN_MOON("optifine.sun_moon", false, false),
          CHUNK_UPDATES("optifine.chunk_updates", false, false),
          CHUNK_UPDATES_DYNAMIC("optifine.chunk_updates_dynamic", false, false),
          TIME("optifine.time", false, false),
          CLEAR_WATER("optifine.clear_water", false, false),
          SMOOTH_INPUT("optifine.smooth_input", false, false),
          DEPTH_FOG("optifine.depth_fog", false, false),
          VOID_PARTICLES("optifine.void_particles", false, false),
          WATER_PARTICLES("optifine.water_particles", false, false),
          RAIN_SPLASH("optifine.rain_splash", false, false),
          PORTAL_PARTICLES("optifine.portal_particles", false, false),
          POTION_PARTICLES("optifine.potion_particles", false, false),
          PROFILER("optifine.profiler", false, false),
          DRIPPING_WATER_LAVA("optifine.dripping_water_lava", false, false),
          BETTER_SNOW("optifine.better_snow", false, false),
          FULLSCREEN_MODE("optifine.fullscreen_mode", false, false),
          ANIMATED_TERRAIN("optifine.animated_terrain", false, false),
          ANIMATED_ITEMS("optifine.animated_items", false, false),
          SWAMP_COLORS("optifine.swamp_colors", false, false),
          RANDOM_MOBS("optifine.random_mobs", false, false),
          SMOOTH_BIOMES("optifine.smooth_biomes", false, false),
          CUSTOM_FONTS("optifine.custom_fonts", false, false),
          CUSTOM_COLORS("optifine.custom_colors", false, false),
          SHOW_CAPES("optifine.show_capes", false, false),
          CONNECTED_TEXTURES("optifine.connected_textures", false, false),
          AA_LEVEL("optifine.aa_level", false, false),
          AF_LEVEL("optifine.af_level", false, false),
          ANIMATED_TEXTURES("optifine.animated_textures", false, false),

          NATURAL_TEXTURES("optifine.natural_textures", false, false),
          CHUNK_LOADING("optifine.chunk_loading", false, false),
          SMOOTH_WORLD("optifine.smooth_world", false, false),
          FAST_DEBUG_INFO("optifine.fast_debug_info", false, false),
          FRAMERATE_LIMIT_FINE("options.framerateLimit", true, false),
         
          HELD_ITEM_TOOLTIPS("optifine.holdItemTooltips", false, false),
          DROPPED_ITEMS("optifine.droppedItems", false, false),
          LAZY_CHUNK_LOADING("optifine.lazy_chunk_loading", false, false),
          CUSTOM_SKY("optifine.custom_sky", false, false);



      :not: GameSettingsの書き換え
      これはバニラのゲームメニューのファイルだが、OptiFineが書き換えているので、その部分を書き換える。
      具体的には描画距離の表記をローカライズ文字列に戻す。
      書き換える場所は5行。getKeyBindingメソッド内。
      コード: 全て選択
      1266: String var9 = "Tiny";
      1271: var9 = "Short";
      1277: var9 = "Normal";
      1283: var9 = "Far";
      1289: var9 = "Extreme";
       ↓
      String var9 = var2.translateKey("options.renderDistance.tiny");
      var9 = var2.translateKey("options.renderDistance.short");
      var9 = var2.translateKey("options.renderDistance.normal");
      var9 = var2.translateKey("options.renderDistance.far");
      var9 = var2.translateKey("optifine.renderDistance.extreme");

      Tiny~Farはバニラの翻訳データを使用する。
      Extremeのローカライズ識別子は、実際にEnumOptionsで書き換えた値を書く事。


      :not: GuiVideoSettingsの書き換え
      これもバニラのビデオ設定のファイルだが、OptiFineが書き換えているので、その部分を書き換える。
      具体的には新しい設定項目をローカライズ文字列に変更にする。
      書き換える場所は5行。initGuiメソッド内。
      コード: 全て選択
      64: this.buttonList.add(new GuiSmallButton(102, var7, var13, "Quality..."));
      67: this.buttonList.add(new GuiSmallButton(101, var7, var13, "Details..."));
      69: this.buttonList.add(new GuiSmallButton(112, var7, var13, "Performance..."));
      72: this.buttonList.add(new GuiSmallButton(111, var7, var13, "Animations..."));
      74: this.buttonList.add(new GuiSmallButton(122, var7, var13, "Other..."));
       ↓
      this.buttonList.add(new GuiSmallButton(102, var7, var13, var1.translateKey("optifine.qualityBtn")));
      this.buttonList.add(new GuiSmallButton(101, var7, var13, var1.translateKey("optifine.detailsBtn")));
      this.buttonList.add(new GuiSmallButton(112, var7, var13, var1.translateKey("optifine.performanceBtn")));
      this.buttonList.add(new GuiSmallButton(111, var7, var13, var1.translateKey("optifine.animationsBtn")));
      this.buttonList.add(new GuiSmallButton(122, var7, var13, var1.translateKey("optifine.otherBtn")));

      基本的に、固定文字列をローカライズ文字列に置き換えるだけなので、難しくはない。


      :not: Gui~SettingOFの書き換え
      これらのファイルはOptiFineで追加される設定画面のファイル。
      それぞれのページのタイトルだけ修正する。タイトル無視すれば実は書き換えなくても問題ない。
      それぞれinitGuiメソッドの最初の部分に、1行追加する。
      コード: 全て選択
      StringTranslate var1 = StringTranslate.getInstance();
      //この部分に
       ↓
      title = var1.translateKey("optifine.otherTitle");
      //各タイトルごとのローカライズ変換コードを追加する。


      GuiOtherSettingsOFだけは、47行目を書き換える必要アリ。
      コード: 全て選択
      this.buttonList.add(new GuiButton(210, this.width / 2 - 100, this.height / 6 + 168 + 11 - 22, "Reset Video Settings..."));
       ↓
      this.buttonList.add(new GuiButton(210, this.width / 2 - 100, this.height / 6 + 168 + 11 - 22, var1.translateKey("optifine.reset")));



      :not: パッケージング
      1. リコンパイルする。(recompile実行)
      2. 再難読化する。(reobfuscate実行)
      3. zip化する。
      4. バニラのminacraft.jarから言語ファイルを取り出す。(とりあえずen_US.langとja_JP.lang)
      5. OptiFineローカライズ用の言語ファイルの内容を足す。
      6. zip内にlangフォルダを作り、書き足したlangファイルをコピーする。
      7. 終わり。
        OptiFine用言語ファイル
        en_US.lang
        コード: 全て選択
        optifine.renderDistance.extreme=Extreme
        optifine.fog_fancy=Fog
        optifine.fog_start=Fog Start
        optifine.detailsBtn=Details...
        optifine.detailsTitle=Details Settings
        optifine.clouds=Clouds
        optifine.cloud_height=Cloud Height
        optifine.trees=Trees
        optifine.grass=Grass
        optifine.water=Water
        optifine.rain=Rain & Snow
        optifine.sky=Sky
        optifine.stars=Stars
        optifine.sun_moon=Sun & Moon
        optifine.show_capes=Show Capes
        optifine.depth_fog=Depth Fog
        optifine.qualityBtn=Quality...
        optifine.qualityTitle=Quality Settings
        optifine.mipmap_level=Mipmap Level
        optifine.mipmap_type=Mipmap Type
        optifine.af_level=Anisotropic Filtering
        optifine.aa_level=Antialiasing
        optifine.clear_water=Clear Water
        optifine.random_mobs=Random Mobs
        optifine.better_grass=Better Grass
        optifine.better_snow=Better Snow
        optifine.custom_fonts=Custom Fonts
        optifine.custom_colors=Custom Colors
        optifine.swamp_colors=Swamp Colors
        optifine.smooth_biomes=Smooth Biomes
        optifine.connected_textures=Connected Textures
        optifine.natural_textures=Natural Textures
        optifine.animationsBtn=Animations...
        optifine.animationsTitle=Animations Settings
        optifine.animated_water=Water Animated
        optifine.animated_lava=Lava Animated
        optifine.animated_fire=Fire Animated
        optifine.animated_portal=Portal Animated
        optifine.animated_redstone=Redstone Animated
        optifine.animated_explosion=Explosion Animated
        optifine.animated_flame=Flame Animated
        optifine.animated_smoke=Smoke Animated
        optifine.void_particles=Void Particles
        optifine.water_particles=Water Particles
        optifine.rain_splash=Rain Splash
        optifine.portal_particles=Portal Particles
        optifine.potion_particles=Potion Particles
        optifine.dripping_water_lava=Dripping Water/Lava
        optifine.animated_terrain=Terrain Animated
        optifine.animated_items=Items Animated
        optifine.animated_textures=Textures Animated
        optifine.performanceBtn=Performance...
        optifine.performanceTitle=Performance Settings
        optifine.smooth_fps=Smooth FPS
        optifine.smooth_input=Smooth Input
        optifine.load_far=Load Far
        optifine.preloaded_chunks=Preloaded Chunks
        optifine.chunk_updates=Chunk Updates
        optifine.chunk_updates_dynamic=Dynamic Updates
        optifine.otherBtn=Other
        optifine.otherTitle=Other Settings
        optifine.fast_debug_info=Fast Debug Info
        optifine.profiler=Debug Profiler
        optifine.weather=Weather
        optifine.time=Time
        optifine.fullscreen_mode=Fullscreen Mode
        optifine.autosave_ticks=Autosave
        optifine.reset=Reset Video Settings...
        optifine.smooth_world=Smooth World
        optifine.lagometer=Lagometer
        optifine.chunk_loading=Chunk Loading
        optifine.holdItemTooltips=Held Item Tooltips
        optifine.droppedItems=Dropped Items
        optifine.lazy_chunk_loading=Lazy Chunk Loading
        optifine.custom_sky=Custom Sky


        ja_JP.lang
        コード: 全て選択
        optifine.renderDistance.extreme=凄く遠い
        optifine.fog_fancy=霧の種類
        optifine.fog_start=霧の距離
        optifine.detailsBtn=グラフィックスの詳細設定
        optifine.detailsTitle=グラフィックスの詳細設定
        optifine.clouds=雲の設定
        optifine.cloud_height=雲の高さ
        optifine.trees=葉の設定
        optifine.grass=草ブロック側面の設定
        optifine.water=水の設定
        optifine.rain=雨と雪の設定
        optifine.sky=空の表示
        optifine.stars=星の表示
        optifine.sun_moon=太陽と月の表示
        optifine.show_capes=Optifineマントの表示
        optifine.depth_fog=岩盤付近を暗くする
        optifine.qualityBtn=クオリティの詳細設定
        optifine.qualityTitle=クオリティの詳細設定
        optifine.mipmap_level=ミップマップの設定
        optifine.mipmap_type=ミップマップの種類
        optifine.af_level=奥行きのチラツキ抑制
        optifine.aa_level=輪郭のギザギザ軽減
        optifine.clear_water=水の透明度を上げる
        optifine.random_mobs=Random Mobsを有効化
        optifine.better_grass=草ブロックを繋げる
        optifine.better_snow=設置物の下に雪を表示
        optifine.custom_fonts=カスタムフォント
        optifine.custom_colors=カスタムカラー
        optifine.swamp_colors=湿地帯の色を変える
        optifine.smooth_biomes=バイオームを滑らかに表示
        optifine.connected_textures=テクスチャの継ぎ目をなくす
        optifine.natural_textures=自然なテクスチャ
        optifine.animationsBtn=アニメーションの詳細設定
        optifine.animationsTitle=アニメーションの詳細設定
        optifine.animated_water=水
        optifine.animated_lava=溶岩
        optifine.animated_fire=炎
        optifine.animated_portal=ネザーゲート
        optifine.animated_redstone=レッドストーン
        optifine.animated_explosion=爆発
        optifine.animated_flame=松明やかまど
        optifine.animated_smoke=煙
        optifine.void_particles=岩盤付近の粒子
        optifine.water_particles=水中の粒子
        optifine.rain_splash=雨の水しぶき
        optifine.portal_particles=ネザーゲートの粒子
        optifine.potion_particles=ポーションの粒子
        optifine.dripping_water_lava=水/溶岩の滴り
        optifine.animated_terrain=Terrainアニメを有効にする
        optifine.animated_items=Itemsアニメを有効にする
        optifine.animated_textures=Texturesアニメを有効にする
        optifine.performanceBtn=パフォーマンスの詳細設定
        optifine.performanceTitle=パフォーマンスの詳細設定
        optifine.smooth_fps=FPS安定化処理
        optifine.smooth_input=キー入力を安定化
        optifine.load_far=チャンクを常にFarで読み込む
        optifine.preloaded_chunks=チャンクを読み込む距離 16m x
        optifine.chunk_updates=チャンクの更新頻度
        optifine.chunk_updates_dynamic=静止中は読み込み優先
        optifine.otherBtn=その他の設定
        optifine.otherTitle=その他の設定
        optifine.fast_debug_info=デバッグのグラフを消す
        optifine.profiler=デバッグの円グラフを表示
        optifine.weather=天候の有無
        optifine.time=クリエイティブの時刻
        optifine.fullscreen_mode=フルスクリーンのサイズ
        optifine.autosave_ticks=オートセーブの間隔
        optifine.reset=ビデオ設定を初期化する
        optifine.smooth_world=サーバー負荷を分散
        optifine.lagometer=デバッグの棒グラフを表示
        optifine.chunk_loading=チャンク読込方法
        optifine.holdItemTooltips=持ち替え時アイテム名表示
        optifine.droppedItems=落ちてるアイテムの表示
        optifine.lazy_chunk_loading=チャンク読込を遅延
        optifine.custom_sky=カスタムスカイ



        :not: OptiFine更新時の対応
        例えばD2でLocalizeFixを作成し、D3がリリースされた場合
        1. LocalizeFixで書き換えたclassファイル名をリストアップする。
        2. それぞれのファイルに対して、D2のファイルとD3のファイルをバイナリ比較する。
          バイナリに違いがなければ、そのまま利用可能。
        3. バイナリに違いがあった場合には、そのファイルだけを作り直す。
        4. 新しい設定が追加された場合には、言語ファイルの更新も忘れずに。
          (マイクラのバージョンが上がった場合、公式言語ファイルの更新忘れに注意)
        5. 対応版リリース


          ざっと、以上のような流れになる。
          書き換えている部分のコードは全て掲載しているので、理解できる人なら1時間とかからずにリビルドできるはず。
          チュートリアル化するつもりはないので、わからない人はわかるまで自習推奨。

          まあ、良く見れば簡単な処理しかしていないのがわかるはず。
          さして難しくもないので、他のMODの日本語化も出てくることを期待。


          7/9追記:
          OptiFine1.6.2が来たのでちょっと調べてみた。
           EnumOptions が auk.class
           GuiVideoSettings が awl.class
           GameSettings が avf.class っぽいですね。
          ぱっと見た感じ、中身もほぼ変わってないので、上記通りの手順で日本語化できそうです。
          最後に編集したユーザー takanasayo [ 2014年9月04日(木) 17:33 ], 累計 2 回
          アバター
          takanasayo
          ID:2d93d573
          ラピスラズリ収集家
           
          記事: 954
          登録日時: 2012年7月26日(木) 04:00
          お住まい: 石の中にいる

          • (PostNo.110990)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by takanasayo » 2013年6月30日(日) 23:01

          MCP1.6pre版来ましたね。
          https://twitter.com/SeargeDP/status/351325611685462020
          1.6オンリーで1.6.1では動かないらしいですが。
          1.6組はようやくModding始動ですね。
          アバター
          takanasayo
          ID:2d93d573
          ラピスラズリ収集家
           
          記事: 954
          登録日時: 2012年7月26日(木) 04:00
          お住まい: 石の中にいる

          • (PostNo.111018)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by 天狐-SkyFox » 2013年7月01日(月) 01:00

          ベッドのようにリスポーン地点を変更するためにはどうすればいいのでしょう…?
          ベッドを見てもちんぷんかんぷんです。
          SmartCraft更新中
          アバター
          天狐-SkyFox
          ID:49fd26f1
          人生、宇宙、すべての答え
           
          記事: 42
          登録日時: 2012年10月21日(日) 13:04

          • (PostNo.111022)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by 炎の戦士ピスタチオン » 2013年7月01日(月) 01:25

          トピックのルール:ここでは質問しない
          アバター
          炎の戦士ピスタチオン
          ID:e7047047
          木を殴ってる
           
          記事: 28
          登録日時: 2013年6月21日(金) 02:26
          お住まい: 地霊殿:ゴミ箱

          • (PostNo.111025)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by 天狐-SkyFox » 2013年7月01日(月) 01:40

          すいません、トピック立ててきます
          SmartCraft更新中
          アバター
          天狐-SkyFox
          ID:49fd26f1
          人生、宇宙、すべての答え
           
          記事: 42
          登録日時: 2012年10月21日(日) 13:04

          • (PostNo.111115)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by takanasayo » 2013年7月01日(月) 19:55

          1.6がリリースされる前から1.6.2の話。
          https://twitter.com/jeb_/status/351653909464481793
          毎度の事ながら安定しないなぁ。
          アバター
          takanasayo
          ID:2d93d573
          ラピスラズリ収集家
           
          記事: 954
          登録日時: 2012年7月26日(木) 04:00
          お住まい: 石の中にいる

          • (PostNo.111478)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by A.K. » 2013年7月03日(水) 00:21

          Forge8.9.09.10.0とそれ以前とのModdingの違いについて(その1)

          ・@PreInit,@Init,@PostInit→@EventHandlerに
          @PreInit,@Init,@PostInitアノーテーションが廃止予定になり,代わりに@EventHandlerアノーテーションが推奨されています.
          全て@EventHandlerに置き換えれば良いだけです.
          ちなみにブロックやアイテムの登録はPreInitで,
          Initでは名前の登録や,その他登録,
          PostIntiでは他のMODとの連携のためのコードを書くのがForgeの意図しているところのようです.

          ・bindTextureメソッドの廃止.テクスチャの指定の仕方の変更
          これがおそらく一番面倒です.
          今までGUIやレンダリングで,mc.renderEngine.bindTextureとかで画像へのパスを登録していましたが,
          これからは,
          コード: 全て選択
          ResourceLocation res = new ResourceLocation("Domain", "texturesフォルダ以下のファイルのパス(.pngは除く)");
          //あるいは
          ResourceLocation res = new ResourceLocation("Domain:texturesフォルダ以下のファイルのパス(.pngは除く)");
          mc.func_110434_K().func_110577_a(res);
          //or
          mc.renderEngine.func_110577_a(res);

          というような書き方で登録するようになりました.
          画像の置き場所は1.5.2でのmodsフォルダをasssetsフォルダにリネームで良いようですが,以下の注意点があります.
          ・domainは小文字にすること.(上の例の前者はDomainの文字列そのままを扱うが,後者は小文字に変換するため)

          また,アイテム等のアイコンの指定はsetUnlocalizedNameメソッドで間接的に指定できたものがfunc_111206_dメソッドあるいはresisterIconメソッドで指定するようになりました.
          (ブロックはfunc_111022_dメソッドです.)
          func_111206_dメソッドはprotectedなので追加アイテムのクラス内で指定する必要があります.
          func_111206_dメソッドで登録した文字列を用いてresisterIconで登録しているので,正直どちらでも構わないですね.
          こちらでの指定法は"Domain:画像ファイルの名前"固定です.

          ・アーマーテクスチャの指定方法の変更.
          アーマーのテクスチャはItemArmorのgetArmorTextureメソッドで行います.
          ここで指定する文字列は"Domain:ファイルパス"です.

          ・属性の追加により,各種パラメータへのアクセスの変更と設定の変更.
          1.6から属性と呼ばれるものが追加されました.これはアイテムやエンティティのパラメータを変更しやすいようにする枠組みです.
          この変更により,エンティティのgetHealthメソッドはfunc_110143_aJメソッドにgetMaxHealthメソッドはfunc_110138_aPになりました.(関数テーブルが更新されたら元の名称に戻るかもしれません.)
          また,アイテムのgetDamageVsEntityメソッドが廃止され,次のように書くようになりました.
          ex.ItemSword
          コード: 全て選択
              public Multimap func_111205_h()
              {
                  Multimap multimap = super.func_111205_h();
                  multimap.put(SharedMonsterAttributes.field_111264_e.func_111108_a(), new AttributeModifier(field_111210_e, "Weapon modifier", (double)this.weaponDamage, 0));
                  return multimap;
              }

          実際ItemSwordを継承した場合は,上のメソッドをOverrideするだけではダメで,以下のように
          コード: 全て選択
              public Multimap func_111205_h()
              {
                  Multimap multimap = HashMultimap.create();//putメソッドを使う際に同じキーの要素は登録されないため.ItemSwordのものを持ってきてはいけない.
                  multimap.put(SharedMonsterAttributes.field_111264_e.func_111108_a(), new AttributeModifier(field_111210_e, "Weapon modifier", (double)this.weaponDamage, 0));
                  return multimap;
              }

          エンティティの属性指定は次のように書きます.
          コード: 全て選択
              protected void func_110147_ax()
              {
                  super.func_110147_ax();
                  this.func_110148_a(SharedMonsterAttributes.field_111263_d).func_111128_a(0.38D);//この行を必要なだけ書き足す.
              }

          field_111263_aが最大HP
          field_111263_bが索敵範囲
          field_111263_cがノックバック耐性
          field_111263_dがmovespeed
          field_111263_eが攻撃力です.
          func_111128_aの引数がパラメータの数値になります.

          ・その他
          EntityLivingクラスがEntityLivingBaseクラスになり,EntityLivingクラスとEntityPlayerクラスは継承関係ではなくなりました.
          取り敢えず,EntityLivingの変数を全てEntityLivingBaseに置き直せばエラーは潰せます.

          (追記)誤情報の修正とビルド761で修正された部分の削除.それと修正され得る不具合は載せないことに.
          はっきり言ってまだForge自体が不安定なので,私みたいな人柱になりたくなければ,しばらく1.6のModding環境は構築しないほうが時間の節約になります.
          (追記)テクスチャの指定が判明したので,追記.
          (追記)アーマーテクスチャについてコメント
          最後に編集したユーザー A.K. [ 2013年10月22日(火) 18:29 ], 累計 6 回
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:1e285010
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.111958)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by NurseAngel » 2013年7月05日(金) 14:53

          1.5.1でsrg化した自作MODを1.6.1に持って行ってみたら
          名前とテクスチャは全滅だわ一部でNoSuchMethodException発生するわで、このままではとても1.6対応とは言えず。
          srg化で更新不要、なんてのはやはり夢物語だったか。

          #それなりに機能する、ってだけでもこれまでとは雲泥の差だけど

          > func_110434_K()

          こういうのってどうやって読んでるんですか?
          単に中身を解読してるだけ?
          まともなメソッド名になるまでは手が出せそうにありません><


          #地球防衛が完了するころには開発情報も揃ってるかな…
          NurseAngel
          ID:36a0fd66
          石炭掘り
           
          記事: 205
          登録日時: 2012年3月17日(土) 21:38

          • (PostNo.112012)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by A.K. » 2013年7月05日(金) 21:23

          NurseAngel さんが書きました:
          > func_110434_K()

          こういうのってどうやって読んでるんですか?
          単に中身を解読してるだけ?
          まともなメソッド名になるまでは手が出せそうにありません><

          泥臭いですが,Eclipseで呼び出し元をたどったりして探しています.
          ちなみに,主要変更点は
          https://docs.google.com/spreadsheet/ccc?key=0AhdLhUzgJSx2dFdsMk1SbDdQRTdQMXVuenBEcmpHbmc#gid=0
          に暫定的ですがまとめられています.
          安定したら,おそらく今度はネームテーブルの変更がなされるので,まともなメソッド名になるまで手を出さないのが正解だと思います.
          (1.3のときはほんとうに泣きそうになった.)
          最後に編集したユーザー A.K. [ 2013年7月05日(金) 23:21 ], 累計 1 回
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:1e285010
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.112020)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by A.K. » 2013年7月05日(金) 21:53

          Forge8.9.09.10.0とそれ以前とのModdingの違いについて(その2)
          ・Entityのテクスチャの指定方法の変更
          従来EntityのテクスチャはEntity内で指定していましたが,今度はEntityのRenderクラス内の
          コード: 全て選択
             private ResourceLocation tex = new ResourceLocation("Domain","textures以下のファイルパス");
             protected ResourceLocation func_110775_a(Entity entity) {
                return tex;
             }

          と指定するようになりました.複数のテクスチャを使ったマルチパスレンダリング(クリーパーの帯電)の際にはrenderメソッド内でbindTextureメソッドを入れていた位置に
          コード: 全て選択
             private ResourceLocation power = new ResourceLocation("textures/entity/creeper/creeper_armor.png");
          ~~
          render()
          {
          ~~
          func_110776_a(power);
          ~~
          }

          というふうに入れれば良いです.

          ・TileEntitySpecialRendererでのテクスチャ指定方法の変更
          こちらではfunc_110776_aメソッドの代わりにfunc_110628_aメソッドで代用されます.

          ・サウンドの指定方法の変更
          ごめんなさい,サウンドは手をつけたことがないので
          https://docs.google.com/spreadsheet/ccc?key=0AhdLhUzgJSx2dFdsMk1SbDdQRTdQMXVuenBEcmpHbmc#gid=0
          こちらを参照下さい.

          ・Domainで指定するフォルダ名を小文字にする必要性について
          Itemにおける,func_111206_dメソッド,Blockにおけるfunc_111022_dメソッド
          およびregisterIconメソッドでの文字列の指定方法でDomain文字列は強制的に小文字になります.
          一方で,ResourceLocation("Domain","ファイル名")メソッドでの登録ではDomain文字列はそのまま扱われます.
          どちらも当然揺らぎ無くフォルダを探しに行くので,フォルダ名に大文字を含んでいる場合,Item等での指定での読み込みでエラーが出ます.
          ですので,最初からフォルダ名は小文字にして,Domain指定もそれにしておけばどちらの記法でも同じフォルダを参照させることができます.
          (おそらく1.6.1でテクスチャが指定できない方々の多くがこの問題で詰まっているのだと思います.)
          Domainの階層指定について動作するかしないか分からないですが,ironchestに倣って階層は1つで済ませるのが良いと思います.

          以下に1.6.1で動作する私のMODのソースを公開しているGitHubのURLを載せます.
          https://github.com/aksource/EnchantChanger161
          これは1.3で多くのModderが開発を断念したのを繰り返さないための特別処置です.
          (基本バックアップとして使っていて,WIPのソースも含んでいるので,平時に公開するつもりはないです.)
          何度も書きますが,ネームテーブルが変更されるおそれがあるので,forgeのRecommendedが出るまでは様子見するのが賢明です.

          (追記)forge771現在startclientが上手く機能しませんが,Eclipse+MagicLauncherでデバッグ作業は可能です.
          最後に編集したユーザー A.K. [ 2013年7月09日(火) 22:05 ], 累計 1 回
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:1e285010
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.112045)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by takanasayo » 2013年7月06日(土) 00:02

          現状ではmcpにもバグがあるっぽいですしね。
          無理に急いで開発しないで、開発環境が安定してからの方が良いのかもしれませんね・・・
          アバター
          takanasayo
          ID:2d93d573
          ラピスラズリ収集家
           
          記事: 954
          登録日時: 2012年7月26日(木) 04:00
          お住まい: 石の中にいる

          • (PostNo.112962)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by A.K. » 2013年7月09日(火) 22:19

          Forge8.9.0 9.10.0とそれ以前とのModdingの違いについて(その3)
          ・Itemクラス
          hasEffect(ItemStack par1ItemStack)は廃止予定に,hasEffect(ItemStack par1ItemStack, int pass)への切替推奨.

          itemInteractionForEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving)
          →func_111207_a(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, EntityLivingBase par3EntityLivingBase)

          (追記)forge784がReccomandedになりました.Modding開始ですよ.
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:1e285010
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.116682)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by pc12 » 2013年7月25日(木) 22:02

          トピ建てしました
          最後に編集したユーザー pc12 [ 2013年7月25日(木) 22:06 ], 累計 1 回
          大型MOD EDOCraft作成中!
          トピック↓
          viewtopic.php?t=8888
          プロジェクト参加者募集中!募集要項↓
          viewtopic.php?f=21&t=5156&p=88915#p88915
          アイデア募集中!トピック↓
          viewtopic.php?f=9&t=11009
          pc12
          ID:7e8f9bc7
          石掘り
           
          記事: 115
          登録日時: 2012年7月27日(金) 10:46
          お住まい: TOKYO

          • (PostNo.119164)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by NurseAngel » 2013年8月04日(日) 21:41

          アイテムを拾ったハンドラはあるのに、
          ブロックを壊したハンドラがないのは何故だ!!
          NurseAngel
          ID:17ba66d7
          石炭掘り
           
          記事: 205
          登録日時: 2012年3月17日(土) 21:38

          • (PostNo.119173)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by squarep » 2013年8月04日(日) 22:08

          NurseAngel さんが書きました:アイテムを拾ったハンドラはあるのに、
          ブロックを壊したハンドラがないのは何故だ!!

          Bukkitにはあるんですけどねぇ...その辺りのフック全般をAPI化するのも手ですが..
          squarep
          ID:78321e12
          ラピスラズリ収集家
           
          記事: 1367
          登録日時: 2012年8月25日(土) 16:29

          • (PostNo.119175)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by dewfalse » 2013年8月04日(日) 22:12

          NurseAngel さんが書きました:アイテムを拾ったハンドラはあるのに、
          ブロックを壊したハンドラがないのは何故だ!!


          そーだそーだ!
          dewfalse
          ID:1fd27f1e
          金掘り
           
          記事: 373
          登録日時: 2012年2月28日(火) 21:09
          お住まい: Y=1

          • (PostNo.119194)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by A.K. » 2013年8月04日(日) 23:29

          NurseAngel さんが書きました:アイテムを拾ったハンドラはあるのに、
          ブロックを壊したハンドラがないのは何故だ!!

          「壊せないようにしたい」であれば、PlayerInteractEventでブロックを左クリックしたかどうかを判定できます。

          トピックで叫ばれていたピストンと範囲検知の件ですが、ピストンはイベントフックがないので、インスタンスの置き換えで設置メソッドか押し出しメソッドに適当なフックを挟むかするしか無いですね。
          範囲検知もチャンク跨ぎは判定できそうですが、今回の場合はtickhandlerで監視するしか無いですね。
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:1e285010
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.141691)

          ForgeGradle始め方

          投稿記事by A.K. » 2013年11月22日(金) 22:25

          forgeビルド960からGradleを利用したビルド方法になりました。
          今までと少し環境の整え方が違うので、取り敢えず出来た方法を書いておきます。

          1.ForgeソースのDL
          Forgeのソースをhttp://files.minecraftforge.net/でDLして下さい。
          2.Forgeソースの展開
          DLしたソースを適当なフォルダに展開して下さい。
          3.Gradleのセットアップ
          Gradleがすでにある方は、ここを見ていないと思うので、gradleが無いと仮定します。
          展開したソースのフォルダをカレントフォルダとしてコマンドプロンプトを立ち上げて、
          コード: 全て選択
          >gradlew setupDevWorkspace
          >gradlew eclipse

          と打ってeclipse用の設定を行って下さい。1回では設定が終わらないかもしれません。
          4.EclipseにGradleプラグインの追加
          EclipseのマーケットプレイスでGradleプラグインをインストールし、Eclipseを再起動して下さい。
          5.ワークスペースの構築
          Eclipseのワークスペースはどこでもいいので、適当なフォルダを指定し、
          ファイル>インポートから既存プロジェクトをワークスペースへ
          英語だと
          file>import>General>Exists Projects into Workspace
          でforgeのソースフォルダを選択します。(例えば、”forge-1.6.4-9.11.1.964-src”)
          6.MODソースのインポート
          MODのソースはforgeソースフォルダのsrc/main/javaフォルダ内に入れることで、認識されるようです。
          7.Clientの実行構成
          MCPのeclipseワークスペースを利用しなくなったので、Clientの実行も自分で構成しないといけません。
          Eclipseの実行>実行構成でJavaアプリケーションの新規アプリケーションを選択し、
          名前はRun ClientとかClientとかにして、
          プロジェクトを先ほどインポートしたプロジェクト、
          メインクラスを
          コード: 全て選択
          net.minecraft.launchwrapper.Launch

          として下さい。また、プログラム引数として、
          コード: 全て選択
          --version 1.6 --tweakClass cpw.mods.fml.common.launcher.FMLTweaker

          を、VM引数として、
          コード: 全て選択
          -Dfml.ignoreInvalidMinecraftCertificates=true -Xincgc -Xmx512M -Xms512M

          を指定して下さい。VM引数後半はメモリ指定なので本質的には要りません。
          Serverも同様にして、
          Run Serverなど名づけて、プロジェクトは先程と同じで、メインクラスを
          コード: 全て選択
          cpw.mods.fml.relauncher.ServerLaunchWrapper

          として下さい。引数は必要ないです。
          これで実行すると、MODを読み込んでクライアントが起動するはずです。

          ビルド方法ですが、先ほどのカレントフォルダ下のコマンドプロンプトで
          コード: 全て選択
          gradlew build

          でjarにビルドされます。ビルドの詳細はbuild.gradleで変えることが出来ます。
          もし、ソース内に日本語を使っているのであれば、build.gradle内に
          コード: 全て選択
          tasks.withType(Compile) {
            options.encoding = 'UTF-8'
          }

          と記述する必要があるのでご注意下さい。(書かないとビルドでエラーになります。)

          今わかるのはここまでです。他に分かり次第追記します。
          添付ファイル
          ss0040.jpg
          ss0038.jpg
          ss0037.jpg
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:996a4c3d
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.144837)

          [1.6forge]アイテムの可変攻撃力の仕方

          投稿記事by A.K. » 2013年12月09日(月) 21:52

          1.5までの手法が使えなくなって困っている方がいたので、簡単なチュートリアルを書きます。
          1.7でまた変わる可能性があるので、トピックは立てません。自力でこのコメントを探しだして下さい。
          (注意)NBTで変更できるのですが、バニラでメソッドが用意されておらず、現状ではこちらのほうがシンプルです。
          ・まずはじめにアイテムの攻撃力はどこで決まるのか?
          1.6で武器の攻撃力を指定するにはItemクラスのgetItemAttributeModifiersメソッドを使います。
          ItemSwordクラスを見ればweaponDamageというprivate変数が代入されていることが分かります。
          従って、攻撃力を動的に可変させるには、
          ・getItemAttributeModifiersメソッド
          ・weaponDamageのリフレクションによる上書き(ItemSword継承クラス)
          のいずれかの手段を取ることになります。
          後者は簡単なので、今回は、前者のgetItemAttributeModifiersメソッドの上書きによる方法を紹介します。

          ・どのタイミングで可変させるか。
          どういう可変の仕方をしたいかによります。
          例えば、耐久が下がると攻撃力が上がるといった処理であるなら、MOBへの攻撃後のイベントで処理します。
          また、叩いたMOBによって可変させたいのなら、Item#onLeftClickEntityメソッドが手軽です。
          プレイヤーの状態で変化させたいのであれば、onTichUpdateメソッドが汎用的でしょう。

          ・どうコーディングするか。
          では、実際にコーディングしてみましょう。
          ここで、テストソースがあると解説しやすいので、GitHubから究極剣のソースを拾ってきます。
          コード: 全て選択
          package 省略
          import 省略
          public class EcItemUltimateWeapon extends EcItemSword//ItemSwordの継承クラス
          {
                  private double ultimateWeaponDamage = 0;
                  public EcItemUltimateWeapon(int par1)
                  {
                          super(par1, EnumToolMaterial.EMERALD);
                  this.setTextureName(EnchantChanger.EcTextureDomain + "UltimateWeapon");
                  }
                  public Multimap getItemAttributeModifiers()
                  {
                          Multimap multimap = HashMultimap.create();
                          multimap.put(SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName(), new AttributeModifier(field_111210_e, "Weapon modifier", this.ultimateWeaponDamage, 0));
                          return multimap;
                  }
                  @Override
                  public boolean onLeftClickEntity(ItemStack itemstack, EntityPlayer player, Entity entity)
                  {
                          if(player.worldObj.isRemote)return false;
                          if(entity instanceof EntityLivingBase){
                                  float mobmaxhealth =((EntityLivingBase) entity).getMaxHealth() / 3 + 1;
                                  float weaponDmgFromHP = WeaponDamagefromHP(player);
                                  ultimateWeaponDamage = (mobmaxhealth > weaponDmgFromHP)?mobmaxhealth:weaponDmgFromHP;
                          }else if(entity instanceof EntityDragonPart){
                                  ultimateWeaponDamage = 100;
                          }else{
                                  ultimateWeaponDamage = 10;
                          }
                          changeItemDamageStrength(player, itemstack);
                          return false;
                  }
                  private void changeItemDamageStrength(EntityLivingBase entity, ItemStack item){
                          BaseAttributeMap attributeMap = ObfuscationReflectionHelper.getPrivateValue(EntityLivingBase.class, entity, 2);
                          attributeMap.applyAttributeModifiers(item.getAttributeModifiers());
                  }
                  public float WeaponDamagefromHP(EntityPlayer player)
                  {
                          float nowHP = player.getHealth();
                          float maxHP = player.getMaxHealth();
                          float hpRatio = nowHP / maxHP;
                          float damageratio;
                          if(hpRatio >= 0.8){
                                  damageratio = 1;
                          }else if(hpRatio >= 0.5){
                                  damageratio = 0.7F;
                          }else if(hpRatio >= 0.2){
                                  damageratio = 0.5F;
                          }else{
                                  damageratio = 0.3F;
                          }
                          int EXPLv = player.experienceLevel;
                          return MathHelper.floor_float((10 + EXPLv/5)*damageratio);
                  }
          }


          まず、getItemAttributeModifiersメソッドを見てみましょう。
          コード: 全て選択
                  public Multimap getItemAttributeModifiers()
                  {
                          Multimap multimap = HashMultimap.create();
                          multimap.put(SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName(), new AttributeModifier(field_111210_e, "Weapon modifier", this.ultimateWeaponDamage, 0));
                          return multimap;
                  }

          これは、ItemSwordクラスを元にしています。MultiMapの生成の箇所が違いますが、superクラスのItemSwordのMultiMapを取ってくると、putした際に値が2番目以降に格納されてしまうため、ここで、MultiMapを生成します。
          MultiMapはそれが売りなのですが、現状キーにアサインされている2番目以降の値をバニラでは考慮しないので、このような方法を取っています。
          SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName()がKeyです。
          AttributeModifierの第一引数はItemクラスのUUIDで、第二引数は属性名、第三引数は属性の値、第四引数は、実行時のFlagのようなものです。

          次に可変している処理を見ましょう。
          コード: 全て選択
                  public boolean onLeftClickEntity(ItemStack itemstack, EntityPlayer player, Entity entity)
                  {
                          if(player.worldObj.isRemote)return false;
                          if(entity instanceof EntityLivingBase){
                                  float mobmaxhealth =((EntityLivingBase) entity).getMaxHealth() / 3 + 1;
                                  float weaponDmgFromHP = WeaponDamagefromHP(player);
                                  ultimateWeaponDamage = (mobmaxhealth > weaponDmgFromHP)?mobmaxhealth:weaponDmgFromHP;
                          }else if(entity instanceof EntityDragonPart){
                                  ultimateWeaponDamage = 100;
                          }else{
                                  ultimateWeaponDamage = 10;
                          }
                          changeItemDamageStrength(player, itemstack);
                          return false;
                  }
                  private void changeItemDamageStrength(EntityLivingBase entity, ItemStack item){
                          BaseAttributeMap attributeMap = ObfuscationReflectionHelper.getPrivateValue(EntityLivingBase.class, entity, 2);
                          attributeMap.applyAttributeModifiers(item.getAttributeModifiers());
                  }
                  public float WeaponDamagefromHP(EntityPlayer player)
                  {
                          float nowHP = player.getHealth();
                          float maxHP = player.getMaxHealth();
                          float hpRatio = nowHP / maxHP;
                          float damageratio;
                          if(hpRatio >= 0.8){
                                  damageratio = 1;
                          }else if(hpRatio >= 0.5){
                                  damageratio = 0.7F;
                          }else if(hpRatio >= 0.2){
                                  damageratio = 0.5F;
                          }else{
                                  damageratio = 0.3F;
                          }
                          int EXPLv = player.experienceLevel;
                          return MathHelper.floor_float((10 + EXPLv/5)*damageratio);
                  }

          Server側で処理すれば良いので、onLeftClickEntityで処理を分けています。
          WeaponDamagefromHPメソッドはHPを参照して攻撃力を変えるメソッドです。
          本質的に重要なのが、changeItemDamageStrengthメソッドで、プレイヤー等の生物Entityの大元のクラスEntityLivingBaseの属性マップをリフレクションで拾ってきて、ItemStackのgetAttributeModifiersメソッドを経由して、上記getItemAttributeModifiersメソッドを呼んでいます。
          これをしないと、getItemAttributeModifiersメソッドはスロットのアイテムが変化しない限り呼ばれないので、いくら、ultimateWeaponDamage 変数を変化させても反映されません。

          以上で、解説は終わりです。
          不足な点、間違い等ありましたら、お知らせ下さい。
          もじんぐしたい。。。。
          アバター
          A.K.
          ID:996a4c3d
          ラピスラズリ収集家
           
          記事: 1417
          登録日時: 2012年9月03日(月) 19:34

          • (PostNo.148796)

          Re: ◆総合◆Modderのための雑談所

          投稿記事by flameFox » 2013年12月28日(土) 16:51

          forge 1.7.2の起動用メモです。
          (一応だいたい仕組みがわかっている人向けです)

          viewtopic.php?f=13&t=9318&start=60#p148793

          マルチポストに当たってしまうようなら連絡ください。
          flameFox
          ID:2fb62aeb
          石炭掘り
           
          記事: 230
          登録日時: 2013年1月19日(土) 19:53

          1つ前へ次へ

          Return to 開発関連

          x