@Override
  public void paintTerrain(
      Block[] blocks,
      byte[] metadata,
      int i,
      int j,
      int x,
      int y,
      int depth,
      World world,
      Random rand,
      OpenSimplexNoise simplex,
      CellNoise cell,
      float[] noise,
      float river,
      BiomeGenBase[] base) {

    float c = CliffCalculator.calc(x, y, noise);
    boolean cliff = c > 1.4f ? true : false;
    boolean mix = false;

    for (int k = 255; k > -1; k--) {
      Block b = blocks[(y * 16 + x) * 256 + k];
      if (b == Blocks.air) {
        depth = -1;
      } else if (b == Blocks.stone) {
        depth++;

        if (shouldReplaceStone()) {
          blocks[(y * 16 + x) * 256 + k] =
              EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, hcStone(world, i, j, x, y, k));
          metadata[(y * 16 + x) * 256 + k] =
              EBAPI.ebStonify(EBAPI.SLATE, hcStoneMeta(world, i, j, x, y, k));
        }

        if (cliff) {
          if (depth > -1 && depth < 2) {
            if (rand.nextInt(3) == 0) {
              blocks[(y * 16 + x) * 256 + k] = blockCliff2;
              metadata[(y * 16 + x) * 256 + k] = byteCliff2;
            } else {
              blocks[(y * 16 + x) * 256 + k] = blockCliff1;
              metadata[(y * 16 + x) * 256 + k] = byteCliff1;
            }

          } else if (depth < 10) {
            blocks[(y * 16 + x) * 256 + k] = blockCliff1;
            metadata[(y * 16 + x) * 256 + k] = byteCliff1;
          }
        } else {
          if (depth == 0 && k > 61) {
            if (simplex.noise2(i / floMixWidth, j / floMixWidth)
                    + simplex.noise2(i / floSmallWidth, j / floSmallWidth) * floSmallStrength
                > floMixHeight) {
              blocks[(y * 16 + x) * 256 + k] = blockMixTop;
              metadata[(y * 16 + x) * 256 + k] = byteMixTop;

              mix = true;
            } else {
              blocks[(y * 16 + x) * 256 + k] = topBlock;
              metadata[(y * 16 + x) * 256 + k] = topBlockMeta;
            }
          } else if (depth < 4) {
            if (mix) {
              blocks[(y * 16 + x) * 256 + k] = blockMixFiller;
              metadata[(y * 16 + x) * 256 + k] = byteMixFiller;
            } else {
              blocks[(y * 16 + x) * 256 + k] = fillerBlock;
              metadata[(y * 16 + x) * 256 + k] = fillerBlockMeta;
            }
          }
        }
      }
    }
  }
public class RealisticBiomeEBVolcanoM extends RealisticBiomeEBBase {
  public static Block[] ebDominantStoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone)
      };

  public static byte[] ebDominantStoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.CHERT, (byte) 0), EBAPI.ebStonify(EBAPI.LIMESTONE, (byte) 0)
      };

  public static Block[] ebDominantCobblestoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone)
      };

  public static byte[] ebDominantCobblestoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.CHERT, (byte) 0), EBAPI.ebStonify(EBAPI.LIMESTONE, (byte) 0)
      };

  private static Block ebTopBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.grassEB, Blocks.grass);
  private static byte ebTopByte = EBAPI.ebGrassify(EBAPI.ANDISOL, (byte) 0);
  private static Block ebFillBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.dirtEB, Blocks.dirt);
  private static byte ebFillByte = EBAPI.ebGrassify(EBAPI.ANDISOL, (byte) 0);
  private static Block ebMixTopBlock = EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone);
  private static byte ebMixTopByte = EBAPI.ebStonify(EBAPI.BASALT, (byte) 0);
  private static Block ebMixFillBlock =
      (EnhancedBiomesMod.useNewStone == 1)
          ? EnhancedBiomesBlocks.stoneCobbleEB
          : Blocks.cobblestone;
  private static byte ebMixFillByte = EBAPI.ebStonify(EBAPI.BASALT, (byte) 0);
  private static Block ebCliff1Block = EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone);
  private static byte ebCliff1Byte = EBAPI.ebStonify(EBAPI.BASALT, (byte) 0);
  private static Block ebCliff2Block =
      (EnhancedBiomesMod.useNewStone == 1)
          ? EnhancedBiomesBlocks.stoneCobbleEB
          : Blocks.cobblestone;
  private static byte ebCliff2Byte = EBAPI.ebStonify(EBAPI.BASALT, (byte) 0);

  private static SurfaceBase surface =
      new SurfaceEBVolcanoM(
          ebTopBlock, // Block top
          ebTopByte, // byte topByte
          ebFillBlock, // Block filler,
          ebFillByte, // byte fillerByte
          ebMixTopBlock, // Block mixTop,
          ebMixTopByte, // byte mixTopByte,
          ebMixFillBlock, // Block mixFill,
          ebMixFillByte, // byte mixFillByte,
          ebCliff1Block, // Block cliff1,
          ebCliff1Byte, // byte cliff1Byte,
          ebCliff2Block, // Block cliff2,
          ebCliff2Byte, // byte cliff2Byte,
          80f, // float mixWidth,
          -0.15f, // float mixHeight,
          10f, // float smallWidth,
          0.5f // float smallStrength
          );

  private static SurfaceBase riverSurface = new SurfaceRiverOasis();

  public RealisticBiomeEBVolcanoM(BiomeGenBase ebBiome) {
    super(
        ebBiome,
        BiomeBase.climatizedBiome(BiomeGenBase.river, Climate.HOT),
        new TerrainEBVolcanoM(),
        surface);

    this.setRealisticBiomeName("EB Volcano M");
    this.biomeSize = BiomeSize.NORMAL;
    this.biomeWeight = ConfigEB.weightEBVolcanoM;
    this.generateVillages = ConfigEB.villageEBVolcanoM;
  }

  @Override
  public void rDecorate(
      World world,
      Random rand,
      int chunkX,
      int chunkY,
      OpenSimplexNoise simplex,
      CellNoise cell,
      float strength,
      float river) {

    /**
     * Using rDecorateSeedBiome() to partially decorate the biome? If so, then comment out this
     * method.
     */
    rOreGenSeedBiome(world, rand, chunkX, chunkY, simplex, cell, strength, river, baseBiome);

    for (int l14 = 0; l14 < 15; l14++) {
      int l19 = chunkX + rand.nextInt(16) + 8;
      int k22 = rand.nextInt(128);
      int j24 = chunkY + rand.nextInt(16) + 8;

      if (rand.nextInt(3) == 0) {
        (new WorldGenGrass(Blocks.double_plant, 2)).generate(world, rand, l19, k22, j24);
      } else {
        (new WorldGenGrass(Blocks.tallgrass, 1)).generate(world, rand, l19, k22, j24);
      }
    }
  }

  @Override
  public void rMapGen(
      Block[] blocks,
      byte[] metadata,
      World world,
      WorldChunkManagerRTG cmr,
      Random mapRand,
      int baseX,
      int baseY,
      int chunkX,
      int chunkY,
      OpenSimplexNoise simplex,
      CellNoise cell,
      float noise[]) {

    if (baseX % 4 == 0 && baseY % 4 == 0 && mapRand.nextInt(6) == 0) {
      float river = cmr.getRiverStrength(baseX * 16, baseY * 16) + 1f;
      if (river > 0.98f && cmr.isBorderlessAt(baseX * 16, baseY * 16)) {
        long i1 = mapRand.nextLong() / 2L * 2L + 1L;
        long j1 = mapRand.nextLong() / 2L * 2L + 1L;
        mapRand.setSeed((long) chunkX * i1 + (long) chunkY * j1 ^ world.getSeed());

        WorldGenVolcano.build(
            blocks, metadata, world, mapRand, baseX, baseY, chunkX, chunkY, simplex, cell, noise);
      }
    }
  }

  @Override
  public void rReplace(
      Block[] blocks,
      byte[] metadata,
      int i,
      int j,
      int x,
      int y,
      int depth,
      World world,
      Random rand,
      OpenSimplexNoise simplex,
      CellNoise cell,
      float[] noise,
      float river,
      BiomeGenBase[] base) {

    surface.paintTerrain(
        blocks, metadata, i, j, x, y, depth, world, rand, simplex, cell, noise, river, base);
    riverSurface.paintTerrain(
        blocks, metadata, i, j, x, y, depth, world, rand, simplex, cell, noise, river, base);
  }
}
public class RealisticBiomeEBForestedValley extends RealisticBiomeEBBase {
  public static Block[] ebDominantStoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone)
      };

  public static byte[] ebDominantStoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.SLATE, (byte) 0), EBAPI.ebStonify(EBAPI.DOLOMITE, (byte) 0)
      };

  public static Block[] ebDominantCobblestoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone)
      };

  public static byte[] ebDominantCobblestoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.SLATE, (byte) 0), EBAPI.ebStonify(EBAPI.DOLOMITE, (byte) 0)
      };

  private static Block ebTopBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.grassEB, Blocks.grass);
  private static byte ebTopByte = EBAPI.ebGrassify(EBAPI.ALFISOL, (byte) 0);
  private static Block ebFillBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.dirtEB, Blocks.dirt);
  private static byte ebFillByte = EBAPI.ebGrassify(EBAPI.ALFISOL, (byte) 0);
  private static Block ebMixTopBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.grassEB, Blocks.grass);
  private static byte ebMixTopByte = EBAPI.ebGrassify(EBAPI.ALFISOL, (byte) 0);
  private static Block ebMixFillBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.dirtEB, Blocks.dirt);
  private static byte ebMixFillByte = EBAPI.ebGrassify(EBAPI.ALFISOL, (byte) 0);
  private static Block ebCliff1Block = EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone);
  private static byte ebCliff1Byte = EBAPI.ebStonify(EBAPI.SLATE, (byte) 0);
  private static Block ebCliff2Block =
      (EnhancedBiomesMod.useNewStone == 1)
          ? EnhancedBiomesBlocks.stoneCobbleEB
          : Blocks.cobblestone;
  private static byte ebCliff2Byte = EBAPI.ebStonify(EBAPI.SLATE, (byte) 0);

  public RealisticBiomeEBForestedValley(BiomeGenBase ebBiome, BiomeConfig config) {
    super(
        ebBiome,
        BiomeBase.climatizedBiome(BiomeGenBase.river, Climate.TEMPERATE),
        new TerrainEBForestedValley(),
        new SurfaceEBForestedValley(
            ebTopBlock, // Block top
            ebTopByte, // byte topByte
            ebFillBlock, // Block filler,
            ebFillByte, // byte fillerByte
            ebMixTopBlock, // Block mixTop,
            ebMixTopByte, // byte mixTopByte,
            ebMixFillBlock, // Block mixFill,
            ebMixFillByte, // byte mixFillByte,
            ebCliff1Block, // Block cliff1,
            ebCliff1Byte, // byte cliff1Byte,
            ebCliff2Block, // Block cliff2,
            ebCliff2Byte, // byte cliff2Byte,
            1f, // float mixWidth,
            -0.15f, // float mixHeight,
            2f, // float smallWidth,
            0.5f // float smallStrength
            ));

    this.config = config;
  }

  @Override
  public void rDecorate(
      World world,
      Random rand,
      int chunkX,
      int chunkY,
      OpenSimplexNoise simplex,
      CellNoise cell,
      float strength,
      float river) {

    /**
     * Using rDecorateSeedBiome() to partially decorate the biome? If so, then comment out this
     * method.
     */
    rOreGenSeedBiome(world, rand, chunkX, chunkY, simplex, cell, strength, river, baseBiome);

    float l = simplex.noise2(chunkX / 80f, chunkY / 80f) * 60f - 15f;

    for (int b1 = 0; b1 < 2 * strength; b1++) {
      if (rand.nextInt(2) == 0) {
        int j6 = chunkX + rand.nextInt(16) + 8;
        int k10 = chunkY + rand.nextInt(16) + 8;
        int z52 = world.getHeightValue(j6, k10);

        if (z52 < 230) {
          if (rand.nextInt(32) == 0) {
            WorldGenerator worldgenerator = TreeGen.greatOak(rand);
            worldgenerator.setScale(1.0D, 1.0D, 1.0D);
            worldgenerator.generate(world, rand, j6, z52, k10);
          } else {
            WorldGenerator worldgenerator = TreeGen.birch();
            worldgenerator.setScale(1.0D, 1.0D, 1.0D);
            worldgenerator.generate(world, rand, j6, z52, k10);
          }
        }
      }
    }

    if (l > 5f) {
      for (int b2 = 0; b2 < 4f * strength; b2++) {
        int j6 = chunkX + rand.nextInt(16) + 8;
        int k10 = chunkY + rand.nextInt(16) + 8;
        int z52 = world.getHeightValue(j6, k10);

        if (z52 < 220) {
          WorldGenerator worldgenerator =
              rand.nextInt(2) == 0
                  ? TreeGen.birch()
                  : rand.nextInt(10) != 0
                      ? new WorldGenTrees(false)
                      : new WorldGenForest(false, false);
          worldgenerator.setScale(1.0D, 1.0D, 1.0D);
          worldgenerator.generate(world, rand, j6, z52, k10);
        }
      }
    }

    if (rand.nextInt((int) (32f / strength)) == 0) {
      int x22 = chunkX + rand.nextInt(16) + 8;
      int z22 = chunkY + rand.nextInt(16) + 8;
      int y22 = world.getHeightValue(x22, z22);
      if (y22 < 100) {
        if (rand.nextBoolean()) {
          (new WorldGenLog(Blocks.log, 0, Blocks.leaves, -1, 3 + rand.nextInt(4)))
              .generate(world, rand, x22, y22, z22);
        } else {
          (new WorldGenLog(Blocks.log, 2, Blocks.leaves, -1, 3 + rand.nextInt(4)))
              .generate(world, rand, x22, y22, z22);
        }
      }
    }

    for (int f24 = 0; f24 < 3f * strength; f24++) {
      int i1 = chunkX + rand.nextInt(16) + 8;
      int j1 = chunkY + rand.nextInt(16) + 8;
      int k1 = world.getHeightValue(i1, j1);
      if (k1 < 110) {
        (new WorldGenTreeShrub(rand.nextInt(4) + 1, 0, rand.nextInt(3)))
            .generate(world, rand, i1, k1, j1);
      }
    }

    for (int f23 = 0; f23 < 8f * strength; f23++) {
      int j15 = chunkX + rand.nextInt(16) + 8;
      int j17 = rand.nextInt(128);
      int j20 = chunkY + rand.nextInt(16) + 8;
      (new WorldGenFlowers(new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}))
          .generate(world, rand, j15, j17, j20);
    }

    for (int l14 = 0; l14 < 12f * strength; l14++) {
      int l19 = chunkX + rand.nextInt(16) + 8;
      int k22 = rand.nextInt(128);
      int j24 = chunkY + rand.nextInt(16) + 8;
      (new WorldGenGrass(Blocks.tallgrass, 1)).generate(world, rand, l19, k22, j24);
    }
  }
}
public class RealisticBiomeEBBorealPlateauM extends RealisticBiomeEBBase {
  public static Block[] ebDominantStoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone)
      };

  public static byte[] ebDominantStoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.DOLOMITE, (byte) 0), EBAPI.ebStonify(EBAPI.SLATE, (byte) 0)
      };

  public static Block[] ebDominantCobblestoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone)
      };

  public static byte[] ebDominantCobblestoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.DOLOMITE, (byte) 0), EBAPI.ebStonify(EBAPI.SLATE, (byte) 0)
      };

  private static Block ebTopBlock = Blocks.grass;
  private static byte ebTopByte = (byte) 0;
  private static Block ebFillBlock = Blocks.dirt;
  private static byte ebFillByte = (byte) 0;
  private static Block ebMixTopBlock = Blocks.grass;
  private static byte ebMixTopByte = (byte) 0;
  private static Block ebMixFillBlock = Blocks.dirt;
  private static byte ebMixFillByte = (byte) 0;
  private static Block ebCliff1Block = EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone);
  private static byte ebCliff1Byte = EBAPI.ebStonify(EBAPI.DOLOMITE, (byte) 0);
  private static Block ebCliff2Block =
      (EnhancedBiomesMod.useNewStone == 1)
          ? EnhancedBiomesBlocks.stoneCobbleEB
          : Blocks.cobblestone;
  private static byte ebCliff2Byte = EBAPI.ebStonify(EBAPI.DOLOMITE, (byte) 0);

  public RealisticBiomeEBBorealPlateauM(BiomeGenBase ebBiome) {
    super(
        ebBiome,
        BiomeBase.climatizedBiome(BiomeGenBase.river, Climate.COLD),
        new TerrainEBBorealPlateauM(70f, 180f, 7f, 100f, 38f, 260f, 68f),
        new SurfaceEBBorealPlateauM(
            ebTopBlock, // Block top
            ebTopByte, // byte topByte
            ebFillBlock, // Block filler,
            ebFillByte, // byte fillerByte
            ebMixTopBlock, // Block mixTop,
            ebMixTopByte, // byte mixTopByte,
            ebMixFillBlock, // Block mixFill,
            ebMixFillByte, // byte mixFillByte,
            ebCliff1Block, // Block cliff1,
            ebCliff1Byte, // byte cliff1Byte,
            ebCliff2Block, // Block cliff2,
            ebCliff2Byte, // byte cliff2Byte,
            1f, // float mixWidth,
            -0.15f, // float mixHeight,
            2f, // float smallWidth,
            0.5f // float smallStrength
            ));

    this.setRealisticBiomeName("EB Boreal Plateau M");
    this.biomeSize = BiomeSize.NORMAL;
    this.biomeWeight = ConfigEB.weightEBBorealPlateauM;
    this.generateVillages = ConfigEB.villageEBBorealPlateauM;
  }
}
public class RealisticBiomeEBBadlands extends RealisticBiomeEBBase {
  public static Block[] ebDominantStoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.stone)
      };

  public static byte[] ebDominantStoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.HARDENED_SANDSTONE, (byte) 0), EBAPI.ebStonify(EBAPI.MARBLE, (byte) 0)
      };

  public static Block[] ebDominantCobblestoneBlock =
      new Block[] {
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone),
        EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.cobblestone)
      };

  public static byte[] ebDominantCobblestoneMeta =
      new byte[] {
        EBAPI.ebStonify(EBAPI.HARDENED_SANDSTONE, (byte) 0), EBAPI.ebStonify(EBAPI.MARBLE, (byte) 0)
      };

  private static Block ebTopBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.grassEB, Blocks.grass);
  private static byte ebTopByte = EBAPI.ebGrassify(EBAPI.OXISOL, (byte) 0);
  private static Block ebFillBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.dirtEB, Blocks.dirt);
  private static byte ebFillByte = EBAPI.ebGrassify(EBAPI.OXISOL, (byte) 0);
  private static Block ebMixTopBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.grassEB, Blocks.grass);
  private static byte ebMixTopByte = EBAPI.ebGrassify(EBAPI.OXISOL, (byte) 0);
  private static Block ebMixFillBlock = EBAPI.ebGrassify(EnhancedBiomesBlocks.dirtEB, Blocks.dirt);
  private static byte ebMixFillByte = EBAPI.ebGrassify(EBAPI.OXISOL, (byte) 0);
  private static Block ebCliff1Block =
      EBAPI.ebStonify(EnhancedBiomesBlocks.stoneEB, Blocks.sandstone);
  private static byte ebCliff1Byte = EBAPI.ebStonify(EBAPI.HARDENED_SANDSTONE, (byte) 0);
  private static Block ebCliff2Block =
      EBAPI.ebStonify(EnhancedBiomesBlocks.stoneCobbleEB, Blocks.sandstone);
  private static byte ebCliff2Byte = EBAPI.ebStonify(EBAPI.HARDENED_SANDSTONE, (byte) 0);

  public RealisticBiomeEBBadlands(BiomeGenBase ebBiome) {
    super(
        ebBiome,
        BiomeBase.climatizedBiome(BiomeGenBase.river, Climate.HOT),
        new TerrainEBBadlands(),
        new SurfaceEBBadlands(
            ebTopBlock, // Block top
            ebTopByte, // byte topByte
            ebFillBlock, // Block filler,
            ebFillByte, // byte fillerByte
            ebMixTopBlock, // Block mixTop,
            ebMixTopByte, // byte mixTopByte,
            ebMixFillBlock, // Block mixFill,
            ebMixFillByte, // byte mixFillByte,
            ebCliff1Block, // Block cliff1,
            ebCliff1Byte, // byte cliff1Byte,
            ebCliff2Block, // Block cliff2,
            ebCliff2Byte, // byte cliff2Byte,
            80f, // float mixWidth,
            -0.15f, // float mixHeight,
            10f, // float smallWidth,
            0.5f // float smallStrength
            ));

    this.setRealisticBiomeName("EB Badlands");
    this.biomeSize = BiomeSize.NORMAL;
    this.biomeWeight = ConfigEB.weightEBBadlands;
    this.generateVillages = ConfigEB.villageEBBadlands;
  }
}