public MinecraftMod(Mod mod) {
    super(mod);
    haveGetInstance = Mod.getMinecraftVersion().compareTo("1.3") >= 0;

    if (Mod.getMinecraftVersion().compareTo("12w18a") >= 0) {
      theWorld = new FieldRef("Minecraft", "theWorld", "LWorldClient;");
      worldServer = new FieldRef("Minecraft", "worldServer", "LWorldServer;");
    } else {
      theWorld = new FieldRef(getDeobfClass(), "theWorld", "LWorld;");
      worldServer = null;
    }
    if (Mod.getMinecraftVersion().compareTo("13w16a") >= 0) {
      addClassSignature(new ConstSignature("textures/gui/title/mojang.png"));
      addClassSignature(new ConstSignature("crash-reports"));
    } else {
      addClassSignature(new FilenameSignature("net/minecraft/client/Minecraft.class"));
    }

    if (haveGetInstance) {
      addMemberMapper(
          new MethodMapper(getInstance)
              .accessFlag(AccessFlag.PUBLIC, true)
              .accessFlag(AccessFlag.STATIC, true));
    }
  }
 static void setup(Mod mod) {
   mod.addClassMod(new WorldMod(mod));
   mod.addClassMod(new WorldClientMod(mod));
   mod.addClassMod(new WorldProviderMod(mod));
   mod.addClassMod(new WorldProviderHellMod(mod));
   mod.addClassMod(new WorldProviderEndMod(mod));
   mod.addClassMod(new WorldChunkManagerMod(mod));
   mod.addClassMod(new RenderGlobalMod(mod));
   mod.addClassMod(new FontRendererMod(mod));
   mod.addClassMod(new TileEntitySignRendererMod(mod));
   mod.addClassMod(new EntityRendererMod(mod));
 }
  public MinecraftMod addWorldGetter() {
    if (Mod.getMinecraftVersion().compareTo("12w18a") >= 0) {
      addMemberMapper(new FieldMapper(worldServer));

      addPatch(
          new AddMethodPatch(getWorld) {
            @Override
            public byte[] generateMethod() {
              return buildCode(
                  ALOAD_0, reference(GETFIELD, worldServer), reference(GETFIELD, world), ARETURN);
            }
          });
    } else {
      addMemberMapper(new FieldMapper(theWorld));

      addPatch(
          new AddMethodPatch(getWorld) {
            @Override
            public byte[] generateMethod() {
              return buildCode(ALOAD_0, reference(GETFIELD, theWorld), ARETURN);
            }
          });
    }
    return this;
  }
 public static void setup() {
   renderBlockAsItem =
       new MethodRef(
           "RenderBlockManager",
           "renderBlockAsItem",
           Mod.getMinecraftVersion().compareTo("14w32a") >= 0
               ? "(LIBlockState;F)V"
               : "(LBlock;IF)V");
 }
  public RenderBlockManagerMod(Mod mod) {
    super(mod);

    final ClassRef renderBlocksClass = new ClassRef("RenderBlocks");
    final MethodRef renderBlockByRenderType =
        new MethodRef(
            "RenderBlockManager",
            "renderBlockByRenderType",
            "(LBlock;"
                + PositionMod.getDescriptor()
                + (Mod.getMinecraftVersion().compareTo("14w06a") >= 0 ? "LIBlockAccess;" : "")
                + ")Z");
    setup();

    if (RenderBlockCustomMod.haveCustomModels()) {
      addClassSignature(
          new BytecodeSignature() {
            @Override
            public String getMatchExpression() {
              return buildExpression(
                  // if (renderPass == 43)
                  anyILOAD, push(43), IF_ICMPEQ_or_IF_ICMPNE);
            }
          });
    }

    addClassSignature(
        new BytecodeSignature() {
          {
            matchConstructorOnly(true);
            addXref(1, renderBlocksClass);
            addXref(2, registerRenderType);
          }

          @Override
          public String getMatchExpression() {
            return buildExpression(
                // this.registerRenderType(0, new RenderBlocks());
                ALOAD_0,
                push(0),
                captureReference(NEW),
                DUP,
                anyReference(INVOKESPECIAL),
                captureReference(INVOKEVIRTUAL),
                repeat(
                    build(
                        // this.registerRenderType(renderType, new RenderBlocksSubclass());
                        // x10 or more
                        ALOAD_0,
                        any(1, 3), // ICONST_*, BIPUSH x, SIPUSH x x
                        anyReference(NEW),
                        DUP,
                        anyReference(INVOKESPECIAL),
                        backReference(2)),
                    10));
          }
        });

    addClassSignature(
        new BytecodeSignature() {
          {
            setMethod(renderBlockByRenderType);
            addXref(1, BlockMod.getRenderType);
          }

          @Override
          public String getMatchExpression() {
            return buildExpression(
                // renderType = block.getRenderType();
                begin(),
                ALOAD_1,
                captureReference(INVOKEVIRTUAL),
                anyISTORE,

                // return renderType >= 0 ? ...;
                anyILOAD,
                or(
                    build(IFGE_or_IFLT, any(2)), // older
                    build(push(-1), IF_ICMPEQ_or_IF_ICMPNE, any(2)) // 14w06a+
                    ));
          }
        });

    addClassSignature(
        new BytecodeSignature() {
          {
            setMethod(renderBlockAsItem);
            addXref(1, RenderBlocksMod.renderBlockAsItem);
          }

          @Override
          public String getMatchExpression() {
            return buildExpression(
                // renderer.renderBlockAsItem(block, metadata, brightness);
                ALOAD_1, ILOAD_2, FLOAD_3, captureReference(INVOKEVIRTUAL));
          }
        });
  }
  public NBTTagCompoundMod(Mod mod) {
    super(mod);
    setParentClass("NBTBase");

    addClassSignature(
        new OrSignature(
            new ConstSignature(new ClassRef("java.util.HashMap")),
            new ConstSignature(new ClassRef("java.util.Map"))));
    if (Mod.getMinecraftVersion().compareTo("13w36a") >= 0) {
      addClassSignature(
          new ConstSignature(new InterfaceMethodRef("java/io/DataInput", "readByte", "()B")));
      addClassSignature(
          new ConstSignature(
              new InterfaceMethodRef("java/io/DataInput", "readUTF", "()Ljava/lang/String;")));
    } else {
      addClassSignature(new ConstSignature(":["));
      addClassSignature(new ConstSignature(":"));
      addClassSignature(new ConstSignature(","));
      addClassSignature(new ConstSignature("]"));
    }

    addClassSignature(
        new BytecodeSignature() {
          {
            setMethod(new MethodRef(getDeobfClass(), "hasKey", "(Ljava/lang/String;)Z"));
            addXref(1, tagMap);
          }

          @Override
          public String getMatchExpression() {
            return buildExpression(
                ALOAD_0,
                captureReference(GETFIELD),
                ALOAD_1,
                reference(INVOKEINTERFACE, containsKey),
                IRETURN);
          }
        });

    addClassSignature(
        new BytecodeSignature() {
          {
            setMethod(new MethodRef(getDeobfClass(), "removeTag", "(Ljava/lang/String;)V"));
            addXref(1, tagMap);
          }

          @Override
          public String getMatchExpression() {
            return buildExpression(
                ALOAD_0,
                captureReference(GETFIELD),
                ALOAD_1,
                reference(INVOKEINTERFACE, mapRemove));
          }
        });

    mapNBTMethod("Byte", "B");
    mapNBTMethod("ByteArray", "[B");
    mapNBTMethod("Double", "D");
    mapNBTMethod("Float", "F");
    mapNBTMethod("IntArray", "[I");
    mapNBTMethod("Integer", "I");
    mapNBTMethod("Long", "J");
    mapNBTMethod("Short", "S");
    mapNBTMethod("String", "Ljava/lang/String;");

    addMemberMapper(
        new MethodMapper(
            null, new MethodRef(getDeobfClass(), "getBoolean", "(Ljava/lang/String;)Z")));
    addMemberMapper(
        new MethodMapper(new MethodRef(getDeobfClass(), "setBoolean", "(Ljava/lang/String;Z)V")));
    addMemberMapper(
        new MethodMapper(
            new MethodRef(
                getDeobfClass(),
                "getCompoundTag",
                "(Ljava/lang/String;)L" + getDeobfClass() + ";")));
    addMemberMapper(
        new MethodMapper(
            new MethodRef(getDeobfClass(), "getTag", "(Ljava/lang/String;)LNBTBase;")));
  }