Advertisement
akSource

IDを128以上に万が一拡張されてしまってもエラー落ちしないやつ。

Jul 7th, 2014
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.79 KB | None | 0 0
  1. package ak.sampleMod.asm;
  2.  
  3. import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
  4. import cpw.mods.fml.relauncher.FMLLaunchHandler;
  5. import net.minecraft.launchwrapper.IClassTransformer;
  6. import org.objectweb.asm.*;
  7.  
  8. /**
  9.  * Created by A.K. on 14/07/07.
  10.  */
  11. public class PotionEffectTransformer implements IClassTransformer, Opcodes {
  12.  
  13.     private static final String TARGET_CLASS_NAME = "net.minecraft.potion.PotionEffect";
  14.     @Override
  15.     public byte[] transform(String name, String transformedName, byte[] basicClass) {
  16.         if (!FMLLaunchHandler.side().isClient() || !transformedName.equals(TARGET_CLASS_NAME)) {return basicClass;}
  17.         try {
  18.             SampleCorePlugin.LOGGER.info("Start transforming PotionEffect Class");
  19.             ClassReader classReader = new ClassReader(basicClass);
  20.             ClassWriter classWriter = new ClassWriter(1);
  21.             classReader.accept(new CustomVisitor(name, classWriter), 8);
  22.             SampleCorePlugin.LOGGER.info("Finish transforming PotionEffect Class");
  23.             return classWriter.toByteArray();
  24.         } catch (Exception e) {
  25.             throw new RuntimeException("failed : PotionEffectTransformer loading", e);
  26.         }
  27.     }
  28.     /*Custom ClassVisitor
  29.     * visitMethodでメソッドを一から書き直すことが出来る。*/
  30.     class CustomVisitor extends ClassVisitor {
  31.         //難読化後のクラス名。FMLDeobfuscatingRemapper.INSTANCE.mapMethodNameを使う際に使用。
  32.         String owner;
  33.         public CustomVisitor(String owner ,ClassVisitor cv) {
  34.             super(Opcodes.ASM4, cv);
  35.             this.owner = owner;
  36.         }
  37.         static final String TARGET_METHOD_NAME1 = "func_76455_a";//onUpdate
  38.         static final String TARGET_METHOD_NAME_DEBUG1 = "onUpdate";
  39.         static final String TARGET_METHOD_DESC1 = "(Lnet/minecraft/entity/EntityLivingBase;)Z";//method description
  40.  
  41.         static final String TARGET_METHOD_NAME2 = "func_82722_b";//readCustomPotionEffectFromNBT
  42.         static final String TARGET_METHOD_NAME_DEBUG2 = "readCustomPotionEffectFromNBT";
  43.         static final String TARGET_METHOD_DESC2 = "(Lnet/minecraft/nbt/NBTTagCompound;)Lnet/minecraft/potion/PotionEffect;";//method description
  44.  
  45.         static final String TARGET_METHOD_NAME3 = "func_76456_a";//getPotionID
  46.         static final String TARGET_METHOD_NAME_DEBUG3 = "getPotionID";
  47.         static final String TARGET_METHOD_DESC3 = "()I";//method description
  48.  
  49.         @Override
  50.         public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
  51.             //onUpdateメソッドの書き換え
  52.             if (TARGET_METHOD_NAME1.equals(FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(owner, name, desc))
  53.                     && TARGET_METHOD_DESC1.equals(FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(desc))) {
  54.                 SampleCorePlugin.LOGGER.info("Transforming onUpdate method");
  55.                 return new CustomMethodVisitor1(this.api, super.visitMethod(access, name, desc, signature, exceptions));
  56.             }
  57.             //readCustomPotionEffectFromNBTメソッドの書き換え
  58.             if (TARGET_METHOD_NAME2.equals(FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(owner, name, desc))
  59.                     && TARGET_METHOD_DESC2.equals(FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(desc))) {
  60.                 SampleCorePlugin.LOGGER.info("Transforming readCustomPotionEffectFromNBT method");
  61.                 return new CustomMethodVisitor2(this.api, super.visitMethod(access, name, desc, signature, exceptions));
  62.             }
  63.             //getPotionIDメソッドの書き換え
  64.             if (TARGET_METHOD_NAME3.equals(FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(owner, name, desc))
  65.                     && TARGET_METHOD_DESC3.equals(FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(desc))) {
  66.                 SampleCorePlugin.LOGGER.info("Transforming getPotionID method");
  67.                 return new CustomMethodVisitor3(this.api, super.visitMethod(access, name, desc, signature, exceptions));
  68.             }
  69.             return super.visitMethod(access, name, desc, signature, exceptions);
  70.         }
  71.     }
  72.  
  73.     /*Custom MethodVisitor
  74.     * visit**Methodで、InsnNodeの入れ替えや、追加等出来る。*/
  75.     class CustomMethodVisitor1 extends MethodVisitor {
  76.         public CustomMethodVisitor1(int api, MethodVisitor mv) {
  77.             super(api, mv);
  78.         }
  79.         //visitFieldInsnメソッドの1回めの呼び出しで処理するためのフラグ
  80.         boolean check = false;
  81.  
  82.         @Override
  83.         public void visitFieldInsn(int opcode, String owner, String name, String desc) {
  84.             //判定。ここは実は、checkだけ見ればよい。
  85.             if (opcode == GETFIELD && desc.equals("I") && !check) {
  86.                 check = true;
  87.                 SampleCorePlugin.LOGGER.info("onUpdate:change id in [0 - 255]");
  88.                 //これは、PUTFIELDとのペア
  89.                 super.visitVarInsn(ALOAD, 0);
  90.                 //この2つはペア
  91.                 super.visitVarInsn(ALOAD, 0);
  92.                 super.visitFieldInsn(GETFIELD, "net/minecraft/potion/PotionEffect", "field_76462_a", "I");//potionID
  93.                 //ここで、スタックに数字が1つスタックされる。
  94.                 //256をスタック
  95.                 super.visitIntInsn(SIPUSH, 256);
  96.                 //スタックされた2つの数字を加算する
  97.                 super.visitInsn(IADD);
  98.                 //加算された数字がスタックされる。
  99.                 //もう一度256をスタック
  100.                 super.visitIntInsn(SIPUSH, 256);
  101.                 //スタックされている2つの数字のうち、あとの数字で最初の数字の剰余をとる
  102.                 super.visitInsn(IREM);
  103.                 //剰余がスタックされる。
  104.                 //スタックされた数字をフィールドに代入する
  105.                 super.visitFieldInsn(PUTFIELD, "net/minecraft/potion/PotionEffect", "field_76462_a", "I");//potionID
  106.             }
  107.             super.visitFieldInsn(opcode, owner, name, desc);
  108.         }
  109.     }
  110.  
  111.     class CustomMethodVisitor2 extends MethodVisitor {
  112.         public CustomMethodVisitor2(int api, MethodVisitor mv) {
  113.             super(api, mv);
  114.         }
  115.         //visitMethodInsnが複数あるため、直前のfieldNameを保存する。
  116.         String fieldName = "";
  117.         @Override
  118.         public void visitLdcInsn(Object cst) {
  119.             if (cst.equals("Id")) {
  120.                 fieldName = (String)cst;
  121.             }
  122.             super.visitLdcInsn(cst);
  123.         }
  124.         //識別用description
  125.         static final String TARGET_DESC = "(Ljava/lang/String;)B";
  126.         @Override
  127.         public void visitMethodInsn(int opcode, String owner, String name, String desc) {
  128.             super.visitMethodInsn(opcode, owner, name, desc);
  129.             //処理を割りこませる部分を判定
  130.             if (opcode == INVOKEVIRTUAL && TARGET_DESC.equals(desc) && fieldName.equals("Id")) {
  131.                 SampleCorePlugin.LOGGER.info("readCustomPotionEffectFromNBT:change id in [0 - 255]");
  132.                 //256をスタック
  133.                 super.visitIntInsn(SIPUSH, 256);
  134.                 //スタックされた2つの数字を加算する
  135.                 super.visitInsn(IADD);
  136.                 //加算された数字がスタックされる。
  137.                 //もう一度256をスタック
  138.                 super.visitIntInsn(SIPUSH, 256);
  139.                 //スタックされている2つの数字のうち、あとの数字で最初の数字の剰余をとる
  140.                 super.visitInsn(IREM);
  141.                 //剰余がスタックされる。
  142.                 //代入してないが、このメソッドが呼ばれたあと、代入処理が呼ばれている。PotionEffectクラスのバイトコードを参照のこと。
  143.             }
  144.         }
  145.     }
  146.  
  147.     class CustomMethodVisitor3 extends MethodVisitor {
  148.         public CustomMethodVisitor3(int api, MethodVisitor mv) {
  149.             super(api, mv);
  150.         }
  151.  
  152.         @Override
  153.         public void visitFieldInsn(int opcode, String owner, String name, String desc) {
  154.             //1回しか呼ばれないので、判定なしで、処理を挟み込む。
  155.             SampleCorePlugin.LOGGER.info("getPotionID:change id in [0 - 255]");
  156.             super.visitFieldInsn(opcode, owner, name, desc);
  157.             super.visitIntInsn(SIPUSH, 256);
  158.             super.visitInsn(IADD);
  159.             super.visitIntInsn(SIPUSH, 256);
  160.             super.visitInsn(IREM);
  161.             //代入してないが、このメソッドが呼ばれたあと、代入処理が呼ばれている。PotionEffectクラスのバイトコードを参照のこと。
  162.         }
  163.     }
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement