提供: Minecraft Modding Wiki
移動先: 案内検索
18行目: 18行目:
 
         super(new ModMetadata());
 
         super(new ModMetadata());
  
         // @Modのように記述します。
+
         // @Modのように記述します(mcmod.infoは使えない)。
 
         ModMetadata meta = super.getMetadata();
 
         ModMetadata meta = super.getMetadata();
 
         meta.modid = "sampleclasstransform";
 
         meta.modid = "sampleclasstransform";
 
         meta.name = "SampleClassTransform";
 
         meta.name = "SampleClassTransform";
 
         meta.version = "1.0";
 
         meta.version = "1.0";
 +
        // 以下は省略可
 +
        meta.authorList = Arrays.asList(new String[] { "Example" });
 +
        meta.description = "A tutorial access transformer mod.";
 +
        meta.url = "http://...";
 
     }
 
     }
  
68行目: 72行目:
 
package tutorial.asm;
 
package tutorial.asm;
  
public class SampleCrassTransformer implements IClassTransformer {
+
public class SampleCrassTransformer extends AccessTransformer {
     //この配列に、書き換えるクラス名を完全修飾で記述します。
+
     private static TutorialAccessTransformer instance;
    public static final String[] transformClasses = new String[] {"net.minecraft.client.renderer.ItemRenderer"};
+
        private static List mapFiles = new LinkedList();
 +
        public TutorialAccessTransformer() throws IOException {
 +
                super();
 +
                instance = this;
 +
                // ここで自分の書き換えるクラス情報を登録する。
 +
                mapFiles.add("tutorial_at.cfg");
 +
                for (String file : mapFiles) {
 +
                        readMapFile(file);
 +
                }
 +
        }
  
    @Override
+
        public static void addTransformerMap(String mapFileName) {
    public byte[] transform(byte[] bytes, String name, String transformedName) {
+
                if (instance == null) {
        if (Arrays.asList(transformClasses).contains(name)) {
+
                        mapFiles.add(mapFileName);
            return replaceClass(bytes, name, transformedName);
+
                }
 +
                else {
 +
                        instance.readMapFile(mapFileName);
 +
                }
 
         }
 
         }
        return bytes;
 
    }
 
  
    private byte[] replaceClass(byte[] bytes, String name, String transformedName) {
+
        private void readMapFile(String name) {
       
+
                System.out.println("Adding transformer map: " + name);
         return bytes;
+
                try {
    }
+
                        // AccessTramsformer(スーパークラス)からreadMapFileのメソッドを読み込み、privateメソッドを実行します。
 +
                        Method e = AccessTransformer.class.getDeclaredMethod("readMapFile", new Class[]{String.class});
 +
                        e.setAccessible(true);
 +
                        e.invoke(this, new Object[]{name});
 +
                }
 +
                catch (Exception ex) {
 +
                        throw new RuntimeException(ex);
 +
                }
 +
         }
 
}
 
}
  
 
</source>
 
</source>
  
*SampleAccessTransformer.java
+
*sample_at.cfg
<source lang="java">
+
<source lang="text">
package tutorial.asm;
+
public net.minecraft.client.renderer.ItemRenderer * #メンバを全て書き換え
 
+
public net.minecraft.client.renderer.ItemRenderer *() #メソッドを全て書き換え
 
 
public class SampleAccessTransformer extends AccessTransformer {
 
    public SampleAccessTransformer() { super("sample_at.cfg"); }
 
}
 
  
 
</source>
 
</source>
  
*sample_at.cfg
+
*MANIFEST.MF
 
<source lang="text">
 
<source lang="text">
public net.minecraft.client.renderer.ItemRenderer * #クラス丸ごと書き換え
+
Manifest-Version: 1.0
public net.minecraft.client.renderer.ItemRenderer *() #メソッドを全て書き換え
+
FMLCorePlugin: tutorial.asm.SampleLoadingPlugin
 
 
 
</source>
 
</source>
  
125行目: 142行目:
 
*sample_at.cfg
 
*sample_at.cfg
 
クラス書き換えに関する情報。
 
クラス書き換えに関する情報。
resourcesの中の、META-INFフォルダに入れる(なければ作成)。
+
resourcesフォルダに入れる。
 +
 
 +
*MANIFEST.MF
 +
CoreModの読み込みやデバッグに必須なファイル。
 +
resources/META-INFフォルダに入れる(無ければ作成)。

2015年4月1日 (水) 18:02時点における版

この記事は"Minecraft Forge Universal 10.13.0.1207"を前提MODとしています。

Stone pickaxe.png
中級者向けのチュートリアルです。



1.7からの、クラス書き換え方法です。 基本的にはcoremodsの基礎と同じです。

import文は記述していません。

ソースコード

  • SampleClassTransformCore.java
package tutorial.asm;

public class SampleClassTransformCore extends DummyModContainer {
    public SampleClassTransformCore() {
        super(new ModMetadata());

        // @Modのように記述します(mcmod.infoは使えない)。
        ModMetadata meta = super.getMetadata();
        meta.modid = "sampleclasstransform";
        meta.name = "SampleClassTransform";
        meta.version = "1.0";
        // 以下は省略可
        meta.authorList = Arrays.asList(new String[] { "Example" });
        meta.description = "A tutorial access transformer mod.";
        meta.url = "http://...";
    }

    @Override
    public boolean registerBus(EventBus bus, LoadController lc) {
        bus.register(this);
        return true;
    }
}
  • SampleLoadingPlugin.java
package tutorial.asm;

public class SampleLoadingPlugin implements IFMLLoadingPlugin {
       @Override
        public String[] getLibraryRequestClass() {
                return null;
        }

        @Override
        public String[] getASMTransformerClass() {
                return new String[] {"tutorial.asm.SampleClassTransformer"};;
        }
        @Override
        public String getModContainerClass() {
                return "tutorial.asm.SampleClassTransformCore";
        }
        @Override
        public String getSetupClass() {
                return null;
        }
        @Override
        public void injectData(Map<String, Object> data) {

        }
}
  • SampleClassTransformer.java
package tutorial.asm;

public class SampleCrassTransformer extends AccessTransformer {
    private static TutorialAccessTransformer instance;
        private static List mapFiles = new LinkedList();
        public TutorialAccessTransformer() throws IOException {
                super();
                instance = this;
                // ここで自分の書き換えるクラス情報を登録する。
                mapFiles.add("tutorial_at.cfg");
                for (String file : mapFiles) {
                        readMapFile(file);
                }
        }

        public static void addTransformerMap(String mapFileName) {
                if (instance == null) {
                        mapFiles.add(mapFileName);
                }
                else {
                        instance.readMapFile(mapFileName);
                }
        }

        private void readMapFile(String name) {
                System.out.println("Adding transformer map: " + name);
                try {
                        // AccessTramsformer(スーパークラス)からreadMapFileのメソッドを読み込み、privateメソッドを実行します。
                        Method e = AccessTransformer.class.getDeclaredMethod("readMapFile", new Class[]{String.class});
                        e.setAccessible(true);
                        e.invoke(this, new Object[]{name});
                }
                catch (Exception ex) {
                        throw new RuntimeException(ex);
                }
        }
}
  • sample_at.cfg
public net.minecraft.client.renderer.ItemRenderer * #メンバを全て書き換え
public net.minecraft.client.renderer.ItemRenderer *() #メソッドを全て書き換え
  • MANIFEST.MF
Manifest-Version: 1.0
FMLCorePlugin: tutorial.asm.SampleLoadingPlugin

解説

  • SampleClassTransformCore.java

Modのダミーのエントリポイント。 @Modアノテーションを使わず、DummyModContainerをextendsする。


  • SampleLoadingPlugin.java

このModの実体であるLoadingPlugin。 ここでクラス書き換えをするクラスのパッケージを返す。

  • SampleClassTransformer.java

クラス読み込み処理の割り込みをし、クラスを実際に書き換えるクラス。 IClassTransformerを実装するため、transformメソッドをオーバーライドする必要がある。

  • SampleAccessTransformer.java

スーパークラスに書き換えるクラスの詳細情報が入ったcfgファイル名を渡すだけ。

  • sample_at.cfg

クラス書き換えに関する情報。 resourcesフォルダに入れる。

  • MANIFEST.MF

CoreModの読み込みやデバッグに必須なファイル。 resources/META-INFフォルダに入れる(無ければ作成)。