@Override
  public byte[][] generateBlockSections(
      World world, Random random, int cx, int cz, BiomeGrid biomes) {
    byte[][] result = new byte[16][];

    for (int x = 0; x < 16; x++)
      for (int z = 0; z < 16; z++) {

        for (int y = 63; y < world.getMaxHeight(); y++) setBlock(result, x, y, z, (short) 0);

        for (int y = 0; y < 64; y++) setBlock(result, x, y, z, (short) Material.WATER.getId());

        setBlock(result, x, 0, z, (short) Material.BEDROCK.getId());

        int height = getHeight(cx * 16 + x, cz * 16 + z);
        for (int y = 0; y < height; y++) {
          setBlock(result, x, y, z, (short) Material.STONE.getId());
        }

        if (height < 64) world.setBiome(cx * 16 + x, cz * 16 + z, Biome.OCEAN);
        else if (height < 85) world.setBiome(cx * 16 + x, cz * 16 + z, Biome.PLAINS);
        else if (height < 128) world.setBiome(cx * 16 + x, cz * 16 + z, Biome.EXTREME_HILLS);
        else world.setBiome(cx * 16 + x, cz * 16 + z, Biome.SMALL_MOUNTAINS);
      }

    return result;
  }
Example #2
0
 private static void initTransparentBlocks() {
   transparentBlocks.add(((Integer) Material.AIR.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.BREWING_STAND.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.BROWN_MUSHROOM.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.CAKE.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.CROPS.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.DETECTOR_RAIL.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.DIODE_BLOCK_ON.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.DIODE_BLOCK_OFF.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.LADDER.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.LAVA.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.LEVER.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.LONG_GRASS.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.MELON_STEM.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.NETHER_STALK.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.PAINTING.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.PORTAL.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.POWERED_RAIL.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.PUMPKIN_STEM.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.RAILS.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.RED_MUSHROOM.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.RED_ROSE.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.REDSTONE_TORCH_ON.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.REDSTONE_TORCH_OFF.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.REDSTONE_WIRE.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.SAPLING.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.SIGN_POST.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.SNOW.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.TORCH.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.VINE.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.WALL_SIGN.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.WATER.getId()).byteValue());
   transparentBlocks.add(((Integer) Material.YELLOW_FLOWER.getId()).byteValue());
 }
Example #3
0
public abstract class PlatLot {

  // extremes
  private CachedYs blockYs;
  protected int averageHeight;
  protected int minHeight = Integer.MAX_VALUE;
  protected int minHeightX = 0;
  protected int minHeightZ = 0;
  protected int maxHeight = Integer.MIN_VALUE;
  protected int maxHeightX = 0;
  protected int maxHeightZ = 0;

  protected Random platmapRandom;
  protected Random chunkRandom;

  // styling!
  public enum LotStyle {
    NATURE,
    STRUCTURE,
    ROAD,
    ROUNDABOUT
  };

  public LotStyle style;

  public PlatLot(PlatMap platmap, int chunkX, int chunkZ) {
    super();
    initializeDice(platmap, chunkX, chunkZ);

    style = LotStyle.NATURE;
  }

  protected static final byte airId = (byte) Material.AIR.getId();
  protected static final byte stoneId = (byte) Material.STONE.getId();
  protected static final byte dirtId = (byte) Material.DIRT.getId();
  protected static final byte grassId = (byte) Material.GRASS.getId();
  protected static final byte snowId = (byte) Material.SNOW_BLOCK.getId();
  protected static final byte sandId = (byte) Material.SAND.getId();
  protected static final byte sandstoneId = (byte) Material.SANDSTONE.getId();
  protected static final byte bedrockId = (byte) Material.BEDROCK.getId();
  protected static final byte fenceId = (byte) Material.FENCE.getId();
  protected static final byte cobbleId = (byte) Material.COBBLESTONE.getId();
  protected static final byte stillWaterId = (byte) Material.STATIONARY_WATER.getId();
  protected static final byte stillLavaId = (byte) Material.STATIONARY_LAVA.getId();
  protected static final byte waterId = (byte) Material.WATER.getId();
  protected static final byte lavaId = (byte) Material.LAVA.getId();
  protected static final byte leavesId = (byte) Material.LEAVES.getId();
  protected static final byte glassId = (byte) Material.GLASS.getId();
  protected static final byte paneId = (byte) Material.THIN_GLASS.getId();
  protected static final byte logId = (byte) Material.LOG.getId();
  protected static final byte glowId = (byte) Material.GLOWSTONE.getId();
  protected static final byte stepId = (byte) Material.STEP.getId();
  protected static final byte clayId = (byte) Material.CLAY.getId();
  protected static final byte ironFenceId = (byte) Material.IRON_FENCE.getId();
  protected static final byte endId = (byte) Material.ENDER_STONE.getId();
  protected static final byte netherrackId = (byte) Material.NETHERRACK.getId();
  protected static final byte soulsandId = (byte) Material.SOUL_SAND.getId();

  protected static final int snowMaterialId = Material.SNOW.getId();
  protected static final Material snowMaterial = Material.SNOW;
  protected static final Material airMaterial = Material.AIR;
  protected static final Material stoneMaterial = Material.STONE;
  protected static final Material rootMaterial = Material.GRASS;

  public abstract long getConnectedKey();

  public abstract boolean makeConnected(PlatLot relative);

  public abstract boolean isConnectable(PlatLot relative);

  public abstract boolean isConnected(PlatLot relative);

  protected abstract void generateActualChunk(
      WorldGenerator generator,
      PlatMap platmap,
      ByteChunk chunk,
      BiomeGrid biomes,
      DataContext context,
      int platX,
      int platZ);

  protected abstract void generateActualBlocks(
      WorldGenerator generator,
      PlatMap platmap,
      RealChunk chunk,
      DataContext context,
      int platX,
      int platZ);

  public Biome getChunkBiome() {
    return Biome.PLAINS;
  }

  public boolean isPlaceableAt(WorldGenerator generator, int chunkX, int chunkZ) {
    return generator.settings.inCityRange(chunkX, chunkZ);
  }

  private void initializeDice(PlatMap platmap, int chunkX, int chunkZ) {

    // reset and pick up the dice
    platmapRandom = platmap.getRandomGenerator();
    chunkRandom = platmap.getChunkRandomGenerator(chunkX, chunkZ);
  }

  protected void initializeContext(WorldGenerator generator, SupportChunk chunk) {
    if (blockYs == null) {
      blockYs = new CachedYs(generator, chunk);

      // what was the average height
      minHeight = blockYs.minHeight;
      minHeightX = blockYs.minHeightX;
      minHeightZ = blockYs.minHeightZ;
      maxHeight = blockYs.maxHeight;
      maxHeightX = blockYs.maxHeightX;
      maxHeightZ = blockYs.maxHeightZ;
      averageHeight = blockYs.averageHeight;
    }
  }

  private void deinitializeContext() {
    blockYs = null;
  }

  protected int getBlockY(int x, int z) {
    return blockYs == null ? 0 : blockYs.getBlockY(x, z);
  }

  protected double getPerciseY(int x, int z) {
    return blockYs == null ? 0 : blockYs.getPerciseY(x, z);
  }

  public abstract int getBottomY(WorldGenerator generator);

  public void generateChunk(
      WorldGenerator generator,
      PlatMap platmap,
      ByteChunk chunk,
      BiomeGrid biomes,
      DataContext context,
      int platX,
      int platZ) {
    initializeDice(platmap, chunk.chunkX, chunk.chunkZ);
    initializeContext(generator, chunk);

    // what do we need to first?
    generator.shapeProvider.preGenerateChunk(generator, this, chunk, biomes, blockYs);

    // let the specialized platlot do it's thing
    generateActualChunk(generator, platmap, chunk, biomes, context, platX, platZ);

    // polish things off
    generator.shapeProvider.postGenerateChunk(generator, this, chunk, blockYs);
  }

  public void generateBlocks(
      WorldGenerator generator,
      PlatMap platmap,
      RealChunk chunk,
      DataContext context,
      int platX,
      int platZ) {
    initializeDice(platmap, chunk.chunkX, chunk.chunkZ);
    initializeContext(generator, chunk);

    // what do we need to first?
    generator.shapeProvider.preGenerateBlocks(generator, this, chunk, blockYs);

    // let the specialized platlot do it's thing
    generateActualBlocks(generator, platmap, chunk, context, platX, platZ);

    // polish things off
    generator.shapeProvider.postGenerateBlocks(generator, this, chunk, blockYs);

    // all done
    deinitializeContext();
  }

  private static final int lowestMineSegment = 16;

  public void generateMines(WorldGenerator generator, ByteChunk chunk) {

    // get shafted! (this builds down to keep the support poles happy)
    if (generator.settings.includeMines)
      for (int y = (minHeight / 16 - 1) * 16; y >= lowestMineSegment; y -= 16) {
        if (isShaftableLevel(generator, y)) generateHorizontalMineLevel(generator, chunk, y);
      }
  }

  protected int findHighestShaftableLevel(
      WorldGenerator generator, DataContext context, SupportChunk chunk) {

    // keep going down until we find what we are looking for
    for (int y = (minHeight / 16 - 1) * 16; y >= lowestMineSegment; y -= 16) {
      if (isShaftableLevel(generator, y)
          && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ))
        return y + 7;
    }

    // nothing found
    return 0;
  }

  protected boolean isShaftableLevel(WorldGenerator generator, int y) {
    return y >= lowestMineSegment && y < minHeight && minHeight > generator.seaLevel;
  }

  private void generateHorizontalMineLevel(WorldGenerator generator, ByteChunk chunk, int y) {
    int y1 = y + 6;
    int y2 = y1 + 1;

    // draw the shafts/walkways
    boolean pathFound = false;
    if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ)) {
      generateMineShaftSpace(chunk, 6, 10, y1, y1 + 4, 0, 6);
      generateMineNSSupport(chunk, 6, y2, 1);
      generateMineNSSupport(chunk, 6, y2, 4);
      generateMineShaftSpace(chunk, 6, 10, y1, y1 + 4, 10, 16);
      generateMineNSSupport(chunk, 6, y2, 11);
      generateMineNSSupport(chunk, 6, y2, 14);
      pathFound = true;
    }
    if (generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)) {
      generateMineShaftSpace(chunk, 0, 6, y1, y1 + 4, 6, 10);
      generateMineWESupport(chunk, 1, y2, 6);
      generateMineWESupport(chunk, 4, y2, 6);
      generateMineShaftSpace(chunk, 10, 16, y1, y1 + 4, 6, 10);
      generateMineWESupport(chunk, 11, y2, 6);
      generateMineWESupport(chunk, 14, y2, 6);
      pathFound = true;
    }

    // draw the center bit
    if (pathFound) generateMineShaftSpace(chunk, 6, 10, y1, y1 + 4, 6, 10);
  }

  private static final byte shaftBridgeId = (byte) Material.WOOD.getId();
  private static final byte shaftSupportId = (byte) Material.FENCE.getId();
  private static final byte shaftBeamId = (byte) Material.WOOD.getId();

  private void generateMineShaftSpace(
      ByteChunk chunk, int x1, int x2, int y1, int y2, int z1, int z2) {
    chunk.setEmptyBlocks(x1, x2, y1, z1, z2, shaftBridgeId);
    chunk.setBlocks(x1, x2, y1 + 1, y2, z1, z2, airId);
  }

  private void generateMineNSSupport(ByteChunk chunk, int x, int y, int z) {

    // on a bridge
    if (chunk.getBlock(x, y - 1, z) == shaftBridgeId
        && chunk.getBlock(x + 3, y - 1, z) == shaftBridgeId) {

      // place supports
      generateMineSupport(chunk, x, y - 1, z);
      generateMineSupport(chunk, x + 3, y - 1, z);

      // in a tunnel
    } else {
      chunk.setBlock(x, y, z, shaftSupportId);
      chunk.setBlock(x, y + 1, z, shaftSupportId);
      chunk.setBlock(x + 3, y, z, shaftSupportId);
      chunk.setBlock(x + 3, y + 1, z, shaftSupportId);
      chunk.setBlocks(x, x + 4, y + 2, z, z + 1, shaftBeamId);
    }
  }

  private void generateMineWESupport(ByteChunk chunk, int x, int y, int z) {
    // on a bridge
    if (chunk.getBlock(x, y - 1, z) == shaftBridgeId
        && chunk.getBlock(x, y - 1, z + 3) == shaftBridgeId) {

      // place supports
      generateMineSupport(chunk, x, y - 1, z);
      generateMineSupport(chunk, x, y - 1, z + 3);

      // in a tunnel
    } else {
      chunk.setBlock(x, y, z, shaftSupportId);
      chunk.setBlock(x, y + 1, z, shaftSupportId);
      chunk.setBlock(x, y, z + 3, shaftSupportId);
      chunk.setBlock(x, y + 1, z + 3, shaftSupportId);
      chunk.setBlocks(x, x + 1, y + 2, z, z + 4, shaftBeamId);
    }
  }

  private void generateMineSupport(ByteChunk chunk, int x, int y, int z) {
    int aboveSupport = chunk.findLastEmptyAbove(x, y, z);
    if (aboveSupport < maxHeight) chunk.setBlocks(x, y + 1, aboveSupport + 1, z, shaftSupportId);
  }

  public void generateMines(WorldGenerator generator, RealChunk chunk) {

    // get shafted!
    if (generator.settings.includeMines)
      for (int y = 0; y + 16 < minHeight; y += 16) {
        if (isShaftableLevel(generator, y)) generateVerticalMineLevel(generator, chunk, y);
      }
  }

  private void generateVerticalMineLevel(WorldGenerator generator, RealChunk chunk, int y) {
    int y1 = y + 6;
    boolean stairsFound = false;

    // going down?
    if (isShaftableLevel(generator, y - 16)) {
      if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ)
          && generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y - 16, chunk.chunkZ)) {

        // draw the going down bit
        placeMineStairBase(chunk, 10, y1, 15);
        placeMineStairStep(chunk, 10, y1, 14, Stair.SOUTH, Stair.NORTHFLIP);
        placeMineStairStep(chunk, 10, y1 - 1, 13, Stair.SOUTH, Stair.NORTHFLIP);
        placeMineStairStep(chunk, 10, y1 - 2, 12, Stair.SOUTH, Stair.NORTHFLIP);
        placeMineStairStep(chunk, 10, y1 - 3, 11, Stair.SOUTH, Stair.NORTHFLIP);
        placeMineStairStep(chunk, 10, y1 - 4, 10, Stair.SOUTH, Stair.NORTHFLIP);
        placeMineStairStep(chunk, 10, y1 - 5, 9, Stair.SOUTH, Stair.NORTHFLIP);
        placeMineStairStep(chunk, 10, y1 - 6, 8, Stair.SOUTH, Stair.NORTHFLIP);
        stairsFound = true;
      }

      if (!stairsFound
          && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)
          && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y - 16, chunk.chunkZ)) {

        // draw the going down bit
        placeMineStairBase(chunk, 15, y1, 10);
        placeMineStairStep(chunk, 14, y1, 10, Stair.EAST, Stair.WESTFLIP);
        placeMineStairStep(chunk, 13, y1 - 1, 10, Stair.EAST, Stair.WESTFLIP);
        placeMineStairStep(chunk, 12, y1 - 2, 10, Stair.EAST, Stair.WESTFLIP);
        placeMineStairStep(chunk, 11, y1 - 3, 10, Stair.EAST, Stair.WESTFLIP);
        placeMineStairStep(chunk, 10, y1 - 4, 10, Stair.EAST, Stair.WESTFLIP);
        placeMineStairStep(chunk, 9, y1 - 5, 10, Stair.EAST, Stair.WESTFLIP);
        placeMineStairStep(chunk, 8, y1 - 6, 10, Stair.EAST, Stair.WESTFLIP);
      }
    }

    // reset the stairs flag
    stairsFound = false;

    // going up?
    if (isShaftableLevel(generator, y + 32)) {
      if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ)
          && generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y + 16, chunk.chunkZ)) {

        // draw the going up bit
        placeMineStairBase(chunk, 5, y1, 15);
        placeMineStairStep(chunk, 5, y1 + 1, 14, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 2, 13, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 3, 12, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 4, 11, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 5, 10, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 6, 9, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 7, 8, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairStep(chunk, 5, y1 + 8, 7, Stair.NORTH, Stair.SOUTHFLIP);
        placeMineStairBase(chunk, 5, y1 + 8, 6);
        placeMineStairBase(chunk, 6, y1 + 8, 6);
        placeMineStairBase(chunk, 7, y1 + 8, 6);
        placeMineStairBase(chunk, 8, y1 + 8, 6);
        placeMineStairBase(chunk, 9, y1 + 8, 6);
        placeMineStairBase(chunk, 10, y1 + 8, 6);
        placeMineStairStep(chunk, 10, y1 + 9, 7, Stair.SOUTH, Stair.NORTHFLIP);

        generateMineSupport(chunk, 6, y1 + 7, 7);
        generateMineSupport(chunk, 9, y1 + 7, 7);

        stairsFound = true;
      }

      if (!stairsFound
          && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)
          && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y + 16, chunk.chunkZ)) {

        // draw the going up bit
        placeMineStairBase(chunk, 15, y1, 5);
        placeMineStairStep(chunk, 14, y1 + 1, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 13, y1 + 2, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 12, y1 + 3, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 11, y1 + 4, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 10, y1 + 5, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 9, y1 + 6, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 8, y1 + 7, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairStep(chunk, 7, y1 + 8, 5, Stair.WEST, Stair.EASTFLIP);
        placeMineStairBase(chunk, 6, y1 + 8, 5);
        placeMineStairBase(chunk, 6, y1 + 8, 6);
        placeMineStairBase(chunk, 6, y1 + 8, 7);
        placeMineStairBase(chunk, 6, y1 + 8, 8);
        placeMineStairBase(chunk, 6, y1 + 8, 9);
        placeMineStairBase(chunk, 6, y1 + 8, 10);
        placeMineStairStep(chunk, 7, y1 + 9, 10, Stair.EAST, Stair.WESTFLIP);

        generateMineSupport(chunk, 7, y1 + 7, 6);
        generateMineSupport(chunk, 7, y1 + 7, 9);
      }
    }

    // make the ceiling pretty
    boolean pathFound = false;
    if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ)) {
      generateMineCeiling(chunk, 6, 10, y1 + 3, 0, 6);
      generateMineCeiling(chunk, 6, 10, y1 + 3, 10, 16);

      generateMineAlcove(generator, chunk, 4, y1, 2, 4, 2);
      generateMineAlcove(generator, chunk, 10, y1, 2, 11, 3);

      pathFound = true;
    }
    if (generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)) {
      generateMineCeiling(chunk, 0, 6, y1 + 3, 6, 10);
      generateMineCeiling(chunk, 10, 16, y1 + 3, 6, 10);

      generateMineAlcove(generator, chunk, 2, y1, 4, 2, 4);
      generateMineAlcove(generator, chunk, 2, y1, 10, 3, 11);

      pathFound = true;
    }

    // draw the center bit
    if (pathFound) generateMineCeiling(chunk, 6, 10, y1 + 3, 6, 10);
  }

  private void generateMineAlcove(
      WorldGenerator generator, RealChunk chunk, int x, int y, int z, int prizeX, int prizeZ) {
    if (chunkRandom.nextDouble() < 0.66) {
      if (!chunk.isEmpty(x, y, z)
          && !chunk.isEmpty(x + 1, y, z)
          && !chunk.isEmpty(x, y, z + 1)
          && !chunk.isEmpty(x + 1, y, z + 1)) {
        chunk.setBlocks(x, x + 2, y + 1, y + 4, z, z + 2, Material.AIR);
        generateMineCeiling(chunk, x, x + 2, y + 3, z, z + 2);
        if (chunkRandom.nextDouble() < 0.66) {
          if (chunkRandom.nextDouble() < 0.33)
            generateMineTreat(generator, chunk, prizeX, y + 1, prizeZ);
          else generateMineTrick(generator, chunk, prizeX, y + 1, prizeZ);
        }
      }
    }
  }

  private void generateMineCeiling(RealChunk chunk, int x1, int x2, int y, int z1, int z2) {
    for (int x = x1; x < x2; x++) {
      for (int z = z1; z < z2; z++) {
        if (chunkRandom.nextBoolean())
          if (!chunk.isEmpty(x, y + 1, z) && chunk.isEmpty(x, y, z))
            chunk.setStoneSlab(x, y, z, Direction.StoneSlab.COBBLESTONEFLIP);
      }
    }
  }

  private void generateMineSupport(RealChunk chunk, int x, int y, int z) {
    int aboveSupport = chunk.findLastEmptyAbove(x, y, z);
    if (aboveSupport < maxHeight) chunk.setBlocks(x, y + 1, aboveSupport + 1, z, Material.FENCE);
  }

  private void placeMineStairBase(RealChunk chunk, int x, int y, int z) {
    chunk.setBlocks(x, y + 1, y + 4, z, Material.AIR);
    chunk.setEmptyBlock(x, y, z, Material.WOOD);
  }

  private void placeMineStairStep(
      RealChunk chunk, int x, int y, int z, Stair direction, Stair flipDirection) {
    chunk.setBlocks(x, y + 1, y + 4, z, Material.AIR);
    chunk.setStair(x, y, z, Material.WOOD_STAIRS, direction);
    if (chunk.isEmpty(x, y - 1, z))
      chunk.setStair(x, y - 1, z, Material.WOOD_STAIRS, flipDirection);
  }

  private void generateMineTreat(WorldGenerator generator, RealChunk chunk, int x, int y, int z) {

    // cool stuff?
    if (generator.settings.treasuresInMines
        && chunkRandom.nextDouble() <= generator.settings.oddsOfTreasureInMines) {
      chunk.setChest(
          x,
          y,
          z,
          Direction.General.SOUTH,
          generator.lootProvider.getItems(generator, chunkRandom, LootLocation.MINE));
    }
  }

  private void generateMineTrick(WorldGenerator generator, RealChunk chunk, int x, int y, int z) {
    // not so cool stuff?
    if (generator.settings.spawnersInMines
        && chunkRandom.nextDouble() <= generator.settings.oddsOfSpawnerInMines) {
      chunk.setSpawner(
          x, y, z, generator.spawnProvider.getEntity(generator, chunkRandom, SpawnerLocation.MINE));
    }
  }

  public boolean isValidStrataY(WorldGenerator generator, int blockX, int blockY, int blockZ) {
    return true;
  }

  public void generateOres(WorldGenerator generator, RealChunk chunk) {

    // shape the world
    if (generator.settings.includeOres || generator.settings.includeUndergroundFluids)
      generator.oreProvider.sprinkleOres(
          generator, this, chunk, blockYs, chunkRandom, OreLocation.CRUST);
  }

  // TODO move this logic to SurroundingLots, add to it the ability to produce SurroundingHeights
  // and SurroundingDepths
  public PlatLot[][] getNeighborPlatLots(
      PlatMap platmap, int platX, int platZ, boolean onlyConnectedNeighbors) {
    PlatLot[][] miniPlatMap = new PlatLot[3][3];

    // populate the results
    for (int x = 0; x < 3; x++) {
      for (int z = 0; z < 3; z++) {

        // which platchunk are we looking at?
        int atX = platX + x - 1;
        int atZ = platZ + z - 1;

        // is it in bounds?
        if (!(atX < 0 || atX > PlatMap.Width - 1 || atZ < 0 || atZ > PlatMap.Width - 1)) {
          PlatLot relative = platmap.getLot(atX, atZ);

          if (!onlyConnectedNeighbors || isConnected(relative)) {
            miniPlatMap[x][z] = relative;
          }
        }
      }
    }

    return miniPlatMap;
  }

  public void generateSurface(WorldGenerator generator, RealChunk chunk, boolean includeTrees) {

    // plant grass or snow
    generator.surfaceProvider.generateSurface(generator, this, chunk, blockYs, includeTrees);
  }
}
  protected void a(
      Random rand,
      int i,
      int j,
      byte abyte0[],
      double d,
      double d1,
      double d2,
      float f,
      float f1,
      float f2,
      int k,
      int l,
      double d3) {
    if (generator != null) {
      generator.setNoise(i, j);
    }
    double d4 = i * 16 + 8;
    double d5 = j * 16 + 8;
    float f3 = 0.0F;
    float f4 = 0.0F;
    Random random = new Random(rand.nextLong());
    if (l <= 0) {
      int i1 = 8 * 16 - 16;
      l = i1 - random.nextInt(i1 / 4);
    }
    boolean flag = false;
    if (k == -1) {
      k = l / 2;
      flag = true;
    }
    int j1 = random.nextInt(l / 2) + l / 4;
    boolean flag1 = random.nextInt(6) == 0;
    for (; k < l; k++) {

      double d6 = 1.5D + (double) (MathHelper.sin(((float) k * 3.141593F) / (float) l) * f * 1.0F);
      double d7 = d6 * d3;
      float f5 = MathHelper.cos(f2);
      float f6 = MathHelper.sin(f2);
      d += MathHelper.cos(f1) * f5;
      d1 += f6;
      d2 += MathHelper.sin(f1) * f5;
      if (flag1) {
        f2 *= 0.92F;
      } else {
        f2 *= 0.7F;
      }
      f2 += f4 * 0.1F;
      f1 += f3 * 0.1F;
      f4 *= 0.9F;
      f3 *= 0.75F;
      f4 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 2.0F;
      f3 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 4F;
      if (!flag && k == j1 && f > 1.0F) {
        a(
            rand,
            i,
            j,
            abyte0,
            d,
            d1,
            d2,
            random.nextFloat() * 0.5F + 0.5F,
            f1 - 1.570796F,
            f2 / 3F,
            k,
            l,
            1.0D);
        a(
            rand,
            i,
            j,
            abyte0,
            d,
            d1,
            d2,
            random.nextFloat() * 0.5F + 0.5F,
            f1 + 1.570796F,
            f2 / 3F,
            k,
            l,
            1.0D);
        return;
      }
      if (!flag && random.nextInt(4) == 0) {
        continue;
      }
      double d8 = d - d4;
      double d9 = d2 - d5;
      double d10 = l - k;
      double d11 = f + 2.0F + 16F;
      if ((d8 * d8 + d9 * d9) - d10 * d10 > d11 * d11) {
        return;
      }
      if (d < d4 - 16D - d6 * 2D
          || d2 < d5 - 16D - d6 * 2D
          || d > d4 + 16D + d6 * 2D
          || d2 > d5 + 16D + d6 * 2D) {
        continue;
      }
      int k1 = MathHelper.floor_double(d - d6) - i * 16 - 1;
      int l1 = (MathHelper.floor_double(d + d6) - i * 16) + 1;
      int i2 = MathHelper.floor_double(d1 - d7) - 1;
      int j2 = MathHelper.floor_double(d1 + d7) + 1;
      int k2 = MathHelper.floor_double(d2 - d6) - j * 16 - 1;
      int l2 = (MathHelper.floor_double(d2 + d6) - j * 16) + 1;
      if (k1 < 0) {
        k1 = 0;
      }
      if (l1 > 16) {
        l1 = 16;
      }
      if (i2 < 1) {
        i2 = 1;
      }
      if (j2 > 120) {
        j2 = 120;
      }
      if (k2 < 0) {
        k2 = 0;
      }
      if (l2 > 16) {
        l2 = 16;
      }
      boolean flag2 = false;
      for (int k3 = k1; !flag2 && k3 < l1; k3++) {
        for (int i4 = k2; !flag2 && i4 < l2; i4++) {
          for (int j4 = j2 + 1; !flag2 && j4 >= i2 - 1; j4--) {
            int i3 = (k3 * 16 + i4) * 128 + j4;
            if (j4 >= 0 && j4 < 128) {
              if (abyte0[i3] == Material.WATER.getId()
                  || abyte0[i3] == Material.STATIONARY_WATER.getId()
                  || abyte0[i3] == Material.LAVA.getId()
                  || abyte0[i3] == Material.STATIONARY_LAVA.getId()) {
                flag2 = true;
              }
              if (j4 != i2 - 1 && k3 != k1 && k3 != l1 - 1 && i4 != k2 && i4 != l2 - 1) {
                j4 = i2;
              }
            }
          }
        }
      }

      if (flag2) {
        continue;
      }
      for (int l3 = k1; l3 < l1; l3++) {
        double d12 = (((double) (l3 + i * 16) + 0.5D) - d) / d6;
        for (int j3 = k2; j3 < l2; j3++) {
          generator.midY = generator.getSurfaceLevel(l3, j3);
          double d13 = (((double) (j3 + j * 16) + 0.5D) - d2) / d6;
          int k4 = (l3 * 16 + j3) * 128 + j2;
          for (int l4 = j2 - 1; l4 >= i2; l4--) {
            double d14 = (((double) l4 + 0.5D) - d1) / d7;
            if (d14 > -0.69999999999999996D && d12 * d12 + d14 * d14 + d13 * d13 < 1.0D) {
              byte byte0 = abyte0[k4];
              if (byte0 == Material.STONE.getId()
                  || byte0 == Material.SAND.getId()
                  || byte0 == Material.GRAVEL.getId()
                  || byte0 == Material.DIAMOND_ORE.getId()
                  || byte0 == Material.LAPIS_ORE.getId()) {
                double d15 =
                    generator.getMainDistance(
                        (int) Math.round((d4 + (double) l3) - 8D),
                        l4 - 1,
                        (int) Math.round((d5 + (double) j3) - 8D));
                if (l4 < BiosphereGenerator.LAVA_LEVEL) {
                  if (generator != null) {
                    if (d15 >= generator.sphereRadius && d15 < generator.sphereRadius + 5D) {
                      abyte0[k4] = (byte) Material.BEDROCK.getId();
                    } else if (d15 < generator.sphereRadius) {
                      abyte0[k4] = (byte) Material.LAVA.getId();
                    }
                  } else {
                    abyte0[k4] = (byte) Material.LAVA.getId();
                  }
                } else if ((l4 < generator.midY - 2 || l4 > generator.midY - 1)
                    && (d15 <= 2 + generator.sphereRadius)) {
                  abyte0[k4] = 0;
                }
              }
            }
            k4--;
          }
        }
      }

      if (flag) {
        break;
      }
    }
  }