TileEntitySignRendererMod(Mod mod) {
      super(mod);
      RenderUtilsMod.setup(this);

      final FieldRef sign;
      final MethodRef colorizeSignText =
          new MethodRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "colorizeSignText", "()I");

      if (ResourceLocationMod.haveClass()) {
        sign = new FieldRef(getDeobfClass(), "sign", "LResourceLocation;");
        addClassSignature(new ResourceLocationSignature(this, sign, "textures/entity/sign.png"));
      } else {
        sign = null;
        addClassSignature(new ConstSignature("/item/sign.png"));
      }

      addPatch(
          new BytecodePatch() {
            {
              addPreMatchSignature(
                  new BytecodeSignature() {
                    @Override
                    public String getMatchExpression() {
                      return buildExpression(
                          sign == null ? push("/item/sign.png") : reference(GETSTATIC, sign));
                    }
                  });
            }

            @Override
            public String getDescription() {
              return "override sign text color";
            }

            @Override
            public String getMatchExpression() {
              return buildExpression(
                  push(0), RenderUtilsMod.glDepthMask(this), push(0), capture(anyISTORE));
            }

            @Override
            public byte[] getReplacementBytes() {
              return buildCode(
                  push(0),
                  RenderUtilsMod.glDepthMask(this),
                  reference(INVOKESTATIC, colorizeSignText),
                  getCaptureGroup(1));
            }
          });
    }
    RenderGlobalMod(Mod mod) {
      super(mod);

      final FieldRef clouds;
      final FieldRef mc = new FieldRef(getDeobfClass(), "mc", "LMinecraft;");
      final FieldRef gameSettings = new FieldRef("Minecraft", "gameSettings", "LGameSettings;");
      final JavaRef fancyGraphics;
      final int fancyGraphicsOp;
      final String fancyGraphicsIf;
      final MethodRef drawFancyClouds;
      if (getMinecraftVersion().compareTo("1.8.1-pre4") < 0) {
        fancyGraphics = new FieldRef("GameSettings", "fancyGraphics", "Z");
        fancyGraphicsOp = GETFIELD;
        fancyGraphicsIf = buildExpression(IFEQ, any(2));
        drawFancyClouds =
            new MethodRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "drawFancyClouds", "(Z)Z");
      } else {
        fancyGraphics = new MethodRef("GameSettings", "fancyGraphics", "()I");
        fancyGraphicsOp = INVOKEVIRTUAL;
        fancyGraphicsIf = buildExpression(ICONST_2, IF_ICMPNE_or_IF_ICMPEQ, any(2));
        drawFancyClouds =
            new MethodRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "drawFancyClouds", "(I)I");
      }
      final boolean intParam = getMinecraftVersion().compareTo("14w25a") >= 0;
      final MethodRef renderClouds =
          new MethodRef(getDeobfClass(), "renderClouds", "(F" + (intParam ? "I" : "") + ")V");
      final MethodRef renderCloudsFancy =
          new MethodRef(getDeobfClass(), "renderCloudsFancy", renderClouds.getType());
      final FieldRef endSkyColor =
          new FieldRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "endSkyColor", "I");

      RenderUtilsMod.setup(this);

      if (ResourceLocationMod.haveClass()) {
        clouds = new FieldRef(getDeobfClass(), "clouds", "LResourceLocation;");
        addClassSignature(
            new ResourceLocationSignature(this, clouds, "textures/environment/clouds.png"));
      } else {
        addClassSignature(new ConstSignature("/environment/clouds.png"));
        clouds = null;
      }

      addClassSignature(
          new BytecodeSignature() {
            {
              setMethod(renderClouds);
              addXref(1, mc);
              addXref(2, gameSettings);
              addXref(3, fancyGraphics);
              addXref(4, renderCloudsFancy);
              if (clouds != null) {
                addXref(5, clouds);
              }
            }

            @Override
            public String getMatchExpression() {
              return buildExpression(
                  // 1.8.1-pre4+: if (mc.gameSettings.fancyGraphics() == 2) {
                  // earlier: if (mc.gameSettings.fancyGraphics) {
                  ALOAD_0,
                  captureReference(GETFIELD),
                  captureReference(GETFIELD),
                  captureReference(fancyGraphicsOp),
                  fancyGraphicsIf,

                  // this.renderCloudsFancy(...);
                  ALOAD_0,
                  FLOAD_1,
                  intParam ? build(ILOAD_2) : "",
                  captureReference(INVOKESPECIAL, INVOKEVIRTUAL),
                  or(build(GOTO, any(2)), build(RETURN)),

                  // ...
                  any(0, 150),

                  // ...(RenderGlobal.clouds);
                  // ...("/environment/clouds.png");
                  clouds == null ? push("/environment/clouds.png") : captureReference(GETSTATIC));
            }
          });

      addPatch(
          new BytecodePatch() {
            @Override
            public String getDescription() {
              return "override cloud type";
            }

            @Override
            public String getMatchExpression() {
              return buildExpression(
                  capture(
                      build(
                          ALOAD_0,
                          reference(GETFIELD, mc),
                          reference(GETFIELD, gameSettings),
                          reference(fancyGraphicsOp, fancyGraphics))),
                  capture(fancyGraphicsIf));
            }

            @Override
            public byte[] getReplacementBytes() {
              return buildCode(
                  getCaptureGroup(1), reference(INVOKESTATIC, drawFancyClouds), getCaptureGroup(2));
            }
          }.targetMethod(renderClouds));

      if (TessellatorMod.haveVertexFormatClass()) {
        addPatch(
            new BytecodePatch() {
              @Override
              public String getDescription() {
                return "override end sky color";
              }

              @Override
              public String getMatchExpression() {
                return buildExpression(
                    // 40, 40, 40, 255
                    push(40), push(40), push(40), push(255));
              }

              @Override
              public byte[] getReplacementBytes() {
                return buildCode(
                    // (ColorizeWorld.endSkyColor >> 16) & 0xff
                    reference(GETSTATIC, endSkyColor),
                    push(16),
                    ISHR,
                    push(0xff),
                    IAND,

                    // (ColorizeWorld.endSkyColor >> 8) & 0xff
                    reference(GETSTATIC, endSkyColor),
                    push(8),
                    ISHR,
                    push(0xff),
                    IAND,

                    // ColorizeWorld.endSkyColor & 0xff
                    reference(GETSTATIC, endSkyColor),
                    push(0xff),
                    IAND,

                    // 255
                    push(255));
              }
            });
      } else {
        addPatch(
            new BytecodePatch() {
              @Override
              public String getDescription() {
                return "override end sky color";
              }

              @Override
              public String getMatchExpression() {
                return buildExpression(
                    or(
                        build(push(0x181818)), // pre-12w23a
                        build(push(0x282828)) // 12w23a+
                        ));
              }

              @Override
              public byte[] getReplacementBytes() {
                return buildCode(reference(GETSTATIC, endSkyColor));
              }
            });
      }
    }