@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;
  }
Пример #2
0
  private void createClump(World world, Material oreType, int size, int x, int y, int z) {
    float f = this.random.nextFloat() * 3.141593F;

    double d1 = x + 8 + Math.sin(f) * size / 8.0F;
    double d2 = x + 8 - Math.sin(f) * size / 8.0F;
    double d3 = z + 8 + Math.cos(f) * size / 8.0F;
    double d4 = z + 8 - Math.cos(f) * size / 8.0F;

    double d5 = y + this.random.nextInt(3) - 2;
    double d6 = y + this.random.nextInt(3) - 2;

    for (int i = 0; i <= size; i++) {
      double d7 = d1 + (d2 - d1) * i / size;
      double d8 = d5 + (d6 - d5) * i / size;
      double d9 = d3 + (d4 - d3) * i / size;

      double d10 = this.random.nextDouble() * size / 16.0D;
      double d11 = (Math.sin(i * 3.141593F / size) + 1.0F) * d10 + 1.0D;
      double d12 = (Math.sin(i * 3.141593F / size) + 1.0F) * d10 + 1.0D;

      int j = (int) Math.floor(d7 - d11 / 2.0D);
      int k = (int) Math.floor(d8 - d12 / 2.0D);
      int m = (int) Math.floor(d9 - d11 / 2.0D);

      int n = (int) Math.floor(d7 + d11 / 2.0D);
      int i1 = (int) Math.floor(d8 + d12 / 2.0D);
      int i2 = (int) Math.floor(d9 + d11 / 2.0D);

      for (int i3 = j; i3 <= n; i3++) {
        double d13 = (i3 + 0.5D - d7) / (d11 / 2.0D);

        if (d13 * d13 < 1.0D) {
          for (int i4 = k; i4 <= i1; i4++) {
            double d14 = (i4 + 0.5D - d8) / (d12 / 2.0D);

            if (d13 * d13 + d14 * d14 < 1.0D) {
              for (int i5 = m; i5 <= i2; i5++) {
                double d15 = (i5 + 0.5D - d9) / (d11 / 2.0D);

                if ((d13 * d13 + d14 * d14 + d15 * d15 >= 1.0D)
                    || (world.getBlockTypeIdAt(i3, i4, i5) != Material.STONE.getId())) {
                  continue;
                }

                world.getBlockAt(i3, i4, i5).setType(oreType);
              }
            }
          }
        }
      }
    }
  }
Пример #3
0
 protected void randomizeMaterials() {
   switch (random.nextInt(5)) {
     case 0:
       // lava, sand/sandstone/stone, mushroom stalks
       byteLiquid = (byte) Material.STATIONARY_LAVA.getId();
       byteStone = (byte) Material.STONE.getId();
       byteDirt = (byte) Material.SANDSTONE.getId();
       byteGrass = (byte) Material.SAND.getId();
       intTreeTrunk = Material.HUGE_MUSHROOM_1.getId();
       intTreeLeaves = intAir;
       byteTreeData = (byte) (random.nextInt(2) == 0 ? 10 : 1);
       break;
     case 1:
       // air, sand/sandstone/stone, cactus
       byteLiquid = (byte) Material.AIR.getId();
       byteStone = (byte) Material.STONE.getId();
       byteDirt = (byte) Material.SANDSTONE.getId();
       byteGrass = (byte) Material.SAND.getId();
       intTreeTrunk = Material.CACTUS.getId();
       intTreeLeaves = intAir;
       minTreeHeight = 2;
       maxTreeHeight = 4;
       break;
     case 3:
       // water, glass/glowstone/endstone, crystals
       byteLiquid = (byte) Material.STATIONARY_WATER.getId();
       byteStone = (byte) Material.ENDER_STONE.getId();
       byteDirt = (byte) Material.SOUL_SAND.getId();
       byteGrass = (byte) Material.MYCEL.getId();
       intTreeTrunk = Material.GLOWSTONE.getId();
       intTreeLeaves = Material.THIN_GLASS.getId();
       break;
     default:
       // water, grass/dirt/stone, normal trees are the default
       byteTreeData = (byte) random.nextInt(3);
       break;
   }
 }
Пример #4
0
  public byte[] generate(World world, Random rand, int chunkX, int chunkZ) {
    byte[] blocks = new byte[32768];
    int x, y, z;

    for (x = 0; x < 16; x++) {
      for (z = 0; z < 16; z++) {
        blocks[this.coordsToInt(x, 0, z)] = (byte) Material.BEDROCK.getId();

        for (y = 1; y < 20; y++) {
          blocks[this.coordsToInt(x, y, z)] = (byte) Material.DIRT.getId();
        }

        // this will make a checkerboard
        if ((x + z) % 2 == 1) blocks[this.coordsToInt(x, 20, z)] = (byte) Material.OBSIDIAN.getId();
        else blocks[this.coordsToInt(x, 20, z)] = (byte) Material.WOOL.getId();

        // chess pieces, randomly per side
        if (rand.nextInt(20) < 2) {
          if (rand.nextInt(20) < 10) {
            blocks[this.coordsToInt(x, 21, z)] = (byte) Material.STONE.getId();
            blocks[this.coordsToInt(x, 22, z)] = (byte) Material.STONE.getId();
            blocks[this.coordsToInt(x, 23, z)] = (byte) Material.STONE.getId();
          } else {
            blocks[this.coordsToInt(x, 21, z)] = (byte) Material.SAND.getId();
            blocks[this.coordsToInt(x, 22, z)] = (byte) Material.SAND.getId();
            blocks[this.coordsToInt(x, 23, z)] = (byte) Material.SAND.getId();
          }
        }

        // lava/glass ceiling
        blocks[this.coordsToInt(x, 40, z)] = (byte) Material.GLASS.getId();
        blocks[this.coordsToInt(x, 41, z)] = (byte) Material.LAVA.getId();
      }
    }

    return blocks;
  }
Пример #5
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;
      }
    }
  }
Пример #7
0
  // Generate a chunk
  @Override
  public byte[] generate(World world, Random rand, int chunkx, int chunkz) {
    // Create a byte variable to write the chunk inside and return this variable
    byte[] result = new byte[32768];

    // This will set the whole floor to stone (the floor of each chunk)
    for (int y = 30 + 3; y > 0; y--)
      for (int x = 0; x < 16; x++)
        for (int z = 0; z < 16; z++) result[xyzToByte(x, y, z)] = (byte) Material.STONE.getId();

    // Set the lowest layer to bedrock
    for (int x = 0; x < 16; x++)
      for (int z = 0; z < 16; z++) result[xyzToByte(x, 0, z)] = (byte) Material.BEDROCK.getId();

    // The layers for each 5 rooms in the variable y
    for (int y = 30; y < 30 + (7 * 6); y += 6) {

      // The 4 rooms on each layer saved in the variables x and z
      for (int x = 0; x < 16; x += 8) {
        for (int z = 0; z < 16; z += 8) {

          int xr = (rand.nextInt(3) - 1) * (x + 7);
          int zr = (rand.nextInt(3) - 1) * (z + 7);

          int yfloor = rand.nextInt(2);

          // All the y of the room in the variable y2
          for (int y2 = y + yfloor; y2 < y + 8; y2++) {

            // All the x of the room in the variable x2
            for (int x2 = x; x2 < x + 8; x2++) {

              // All the z of the room in the variable z2
              for (int z2 = z; z2 < z + 8; z2++) {

                // Make the bottom of the room
                if (y2 == y + yfloor)
                  for (int xb = x; xb < x + 8; xb++)
                    for (int zb = z; zb < z + 8; zb++)
                      result[xyzToByte(xb, y2, zb)] = (byte) Material.COBBLESTONE.getId();

                // Fill the walls of the place with cobblestone
                if ((x2 == x || x2 == x + 7) && (z2 == z || z2 == z + 7))
                  result[xyzToByte(x2, y2, z2)] = (byte) 98;
                else if (xr == x2) result[xyzToByte(x2, y2, z2)] = (byte) 98;
                else if (zr == z2) result[xyzToByte(x2, y2, z2)] = (byte) 98;
                else result[xyzToByte(x2, y2, z2)] = (byte) Material.AIR.getId();
              }
            }
          }
        }
      }
    }

    // Create the nose generator which generates wave formes to use for the surface.
    Random random = new Random(world.getSeed());
    SimplexOctaveGenerator octave = new SimplexOctaveGenerator(random, 8);
    octave.setScale(1 / 48.0);

    // Generate the ceiling and the grass land
    for (int x = 0; x < 16; x++) {
      for (int z = 0; z < 16; z++) {
        /*int height = getHeight(world, chunkx + x * 0.0625, chunkz + z * 0.0625, 2) + 30+(7*6) + 7;*/
        double height = octave.noise(x + chunkx * 16, z + chunkz * 16, 0.5, 0.5) * 4 + 9;

        result[xyzToByte(x, 30 + (7 * 6), z)] = (byte) Material.COBBLESTONE.getId();
        for (int y = 30 + (7 * 6) + 1; y < 30 + (7 * 6) + 4; y++)
          result[xyzToByte(x, y, z)] = (byte) Material.STONE.getId();

        // Get the current biome
        Biome biome = world.getBiome((chunkx * 16) + x, (chunkz * 16) + z);

        if (biome.equals(Biome.DESERT) || biome.equals(Biome.DESERT_HILLS)) {
          for (int y = 30 + (7 * 6) + 4; y < 30 + (7 * 6) + 2 + height; y++)
            result[xyzToByte(x, y, z)] = (byte) Material.SAND.getId();

        } else if (biome.equals(Biome.MUSHROOM_ISLAND) || biome.equals(Biome.MUSHROOM_ISLAND)) {
          for (int y = 30 + (7 * 6) + 4; y < 30 + (7 * 6) + 2 + height; y++)
            result[xyzToByte(x, y, z)] = (byte) Material.DIRT.getId();
          result[xyzToByte(x, (int) (30 + (7 * 6) + 2 + height), z)] =
              (byte) Material.MYCEL.getId();

        } else {
          for (int y = 30 + (7 * 6) + 4; y < 30 + (7 * 6) + 2 + height; y++)
            result[xyzToByte(x, y, z)] = (byte) Material.DIRT.getId();
          result[xyzToByte(x, (int) (30 + (7 * 6) + 2 + height), z)] =
              (byte) Material.GRASS.getId();
        }
      }
    }

    return result;
  }
Пример #8
0
public abstract class BananaWellArchetype extends WellArchetype {

  // normal materials
  protected byte byteLiquid = (byte) Material.STATIONARY_WATER.getId();
  protected byte byteStone = (byte) Material.STONE.getId();
  protected byte byteDirt = (byte) Material.DIRT.getId();
  protected byte byteGrass = (byte) Material.GRASS.getId();
  protected byte byteLog = (byte) Material.LOG.getId();
  protected byte byteLeaves = (byte) Material.LEAVES.getId();
  protected byte byteAir = (byte) Material.AIR.getId();
  protected int intOre = byteStone;
  protected int intTreeBase = byteGrass;
  protected int intTreeTrunk = byteLog;
  protected int intTreeLeaves = byteLeaves;

  protected byte byteTreeData = 0;
  protected int intAir = Material.AIR.getId();
  protected int minTreeHeight = 5;
  protected int maxTreeHeight = 5;

  public BananaWellArchetype(World world, long seed, int wellX, int wellZ) {
    super(world, seed, wellX, wellZ);

    // figure out materials
    calculateMaterials();
  }

  // override this if you want something special
  protected void calculateMaterials() {
    randomizeMaterials();

    //  copy over the "seed" materials used by populateOres and populateFoliage
    intOre = byteStone;
    intTreeBase = byteGrass;
  }

  protected void randomizeMaterials() {
    switch (random.nextInt(5)) {
      case 0:
        // lava, sand/sandstone/stone, mushroom stalks
        byteLiquid = (byte) Material.STATIONARY_LAVA.getId();
        byteStone = (byte) Material.STONE.getId();
        byteDirt = (byte) Material.SANDSTONE.getId();
        byteGrass = (byte) Material.SAND.getId();
        intTreeTrunk = Material.HUGE_MUSHROOM_1.getId();
        intTreeLeaves = intAir;
        byteTreeData = (byte) (random.nextInt(2) == 0 ? 10 : 1);
        break;
      case 1:
        // air, sand/sandstone/stone, cactus
        byteLiquid = (byte) Material.AIR.getId();
        byteStone = (byte) Material.STONE.getId();
        byteDirt = (byte) Material.SANDSTONE.getId();
        byteGrass = (byte) Material.SAND.getId();
        intTreeTrunk = Material.CACTUS.getId();
        intTreeLeaves = intAir;
        minTreeHeight = 2;
        maxTreeHeight = 4;
        break;
      case 3:
        // water, glass/glowstone/endstone, crystals
        byteLiquid = (byte) Material.STATIONARY_WATER.getId();
        byteStone = (byte) Material.ENDER_STONE.getId();
        byteDirt = (byte) Material.SOUL_SAND.getId();
        byteGrass = (byte) Material.MYCEL.getId();
        intTreeTrunk = Material.GLOWSTONE.getId();
        intTreeLeaves = Material.THIN_GLASS.getId();
        break;
      default:
        // water, grass/dirt/stone, normal trees are the default
        byteTreeData = (byte) random.nextInt(3);
        break;
    }
  }

  @Override
  public void populateBlocks(Chunk chunk, int chunkX, int chunkZ) {
    // ores
    populateOres(chunk);

    // foliage
    populateFoliage(chunk);
  }

  /**
   * Populates the world with ores.
   *
   * @author Nightgunner5
   * @author Markus Persson
   */
  private static final int[] iterations = new int[] {10, 20, 20, 2, 8, 1, 1, 1};

  private static final int[] amount = new int[] {32, 16, 8, 8, 7, 7, 6};
  private static final int[] type =
      new int[] {
        Material.GRAVEL.getId(),
        Material.COAL_ORE.getId(),
        Material.IRON_ORE.getId(),
        Material.GOLD_ORE.getId(),
        Material.REDSTONE_ORE.getId(),
        Material.DIAMOND_ORE.getId(),
        Material.LAPIS_ORE.getId()
      };
  private static final int[] maxHeight = new int[] {128, 128, 128, 128, 128, 64, 32, 16, 16, 32};

  protected void populateOres(Chunk chunk) {
    // ores
    for (int i = 0; i < type.length; i++) {
      for (int j = 0; j < iterations[i]; j++) {
        placeOre(
            chunk,
            random.nextInt(16),
            random.nextInt(maxHeight[i]),
            random.nextInt(16),
            amount[i],
            type[i]);
      }
    }
  }

  private void placeOre(Chunk source, int originX, int originY, int originZ, int amount, int type) {
    for (int i = 0; i < amount; i++) {
      int x = originX + random.nextInt(amount / 2) - amount / 4;
      int y = originY + random.nextInt(amount / 4) - amount / 8;
      int z = originZ + random.nextInt(amount / 2) - amount / 4;
      x &= 0xf;
      z &= 0xf;
      if (y > 127 || y < 0) {
        continue;
      }
      Block block = source.getBlock(x, y, z);
      if (block.getTypeId() == intOre) {
        block.setTypeId(type, false);
      }
    }
  }

  private static final int chanceRange = 150;

  protected void populateFoliage(Chunk chunk) {

    //		int centerX = (chunk.getX() << 4) + random.nextInt(16);
    //		int centerZ = (chunk.getZ() << 4) + random.nextInt(16);
    //		if (random.nextBoolean()) {
    //			data = 2;
    //			height = 5 + random.nextInt(3);
    //		}
    //
    //		//EC: tweaked the biome logic a bit
    //		switch (getBiome()) {
    //		case FOREST:
    //			chance = 160;
    //			multiplier = 10;
    //			break;
    //		case PLAINS:
    //			chance = 40;
    //			break;
    //		case RAINFOREST:
    //			chance = 160;
    //			multiplier = 10;
    //			break;
    //		case SAVANNA:
    //			chance = 20;
    //			break;
    //		case SEASONAL_FOREST:
    //			chance = 140;
    //			multiplier = 8;
    //			break;
    //		case SHRUBLAND:
    //			chance = 60;
    //			break;
    //		case SWAMPLAND:
    //			chance = 120;
    //			break;
    //		case TAIGA:
    //			chance = 120;
    //			data = 1;
    //			height = 8 + random.nextInt(3);
    //			multiplier = 3;
    //			break;
    //		case TUNDRA:
    //			chance = 10;
    //			data = 1;
    //			height = 7 + random.nextInt(3);
    //			break;
    //		case SKY:
    //		case DESERT:
    //		case HELL:
    //		case ICE_DESERT:
    //			chance = 5;
    //			return;
    //		}

    byte data = (byte) random.nextInt(3);
    int chance = chanceRange / 2;
    int height = minTreeHeight + random.nextInt(maxTreeHeight);
    int multiplier = 3 + random.nextInt(7);

    for (int i = 0; i < multiplier; i++) {
      int centerX = (chunk.getX() << 4) + random.nextInt(16);
      int centerZ = (chunk.getZ() << 4) + random.nextInt(16);
      if (random.nextInt(chanceRange) < chance) {
        int centerY = world.getHighestBlockYAt(centerX, centerZ) - 1;
        Block sourceBlock = world.getBlockAt(centerX, centerY, centerZ);

        // found a place to put it?
        if (sourceBlock.getTypeId() == intTreeBase) {

          // leaves or leave?
          if (intTreeLeaves != intAir) {
            setBlock(centerX, centerY + height + 1, centerZ, intTreeLeaves, data);
            // world.getBlockAt(centerX, centerY + height + 1, centerZ).setTypeIdAndData(intLeaves,
            // data, true);
            for (int j = 0; j < 4; j++) {
              setBlock(centerX, centerY + height + 1 - j, centerZ - 1, intTreeLeaves, data);
              setBlock(centerX, centerY + height + 1 - j, centerZ + 1, intTreeLeaves, data);
              setBlock(centerX - 1, centerY + height + 1 - j, centerZ, intTreeLeaves, data);
              setBlock(centerX + 1, centerY + height + 1 - j, centerZ, intTreeLeaves, data);
              // world.getBlockAt(centerX, centerY + height + 1 - j, centerZ -
              // 1).setTypeIdAndData(intLeaves, data, true);
              // world.getBlockAt(centerX, centerY + height + 1 - j, centerZ +
              // 1).setTypeIdAndData(intLeaves, data, true);
              // world.getBlockAt(centerX - 1, centerY + height + 1 - j,
              // centerZ).setTypeIdAndData(intLeaves, data, true);
              // world.getBlockAt(centerX + 1, centerY + height + 1 - j,
              // centerZ).setTypeIdAndData(intLeaves, data, true);
            }

            if (random.nextBoolean()) {
              setBlock(centerX + 1, centerY + height, centerZ + 1, intTreeLeaves, data);
              // world.getBlockAt(centerX + 1, centerY + height, centerZ +
              // 1).setTypeIdAndData(intLeaves, data, true);
            }
            if (random.nextBoolean()) {
              setBlock(centerX + 1, centerY + height, centerZ - 1, intTreeLeaves, data);
              // world.getBlockAt(centerX + 1, centerY + height, centerZ -
              // 1).setTypeIdAndData(intLeaves, data, true);
            }
            if (random.nextBoolean()) {
              setBlock(centerX - 1, centerY + height, centerZ + 1, intTreeLeaves, data);
              // world.getBlockAt(centerX - 1, centerY + height, centerZ +
              // 1).setTypeIdAndData(intLeaves, data, true);
            }
            if (random.nextBoolean()) {
              setBlock(centerX - 1, centerY + height, centerZ - 1, intTreeLeaves, data);
              // world.getBlockAt(centerX - 1, centerY + height, centerZ -
              // 1).setTypeIdAndData(intLeaves, data, true);
            }

            setBlock(centerX + 1, centerY + height - 1, centerZ + 1, intTreeLeaves, data);
            setBlock(centerX + 1, centerY + height - 1, centerZ - 1, intTreeLeaves, data);
            setBlock(centerX - 1, centerY + height - 1, centerZ + 1, intTreeLeaves, data);
            setBlock(centerX - 1, centerY + height - 1, centerZ - 1, intTreeLeaves, data);
            setBlock(centerX + 1, centerY + height - 2, centerZ + 1, intTreeLeaves, data);
            setBlock(centerX + 1, centerY + height - 2, centerZ - 1, intTreeLeaves, data);
            setBlock(centerX - 1, centerY + height - 2, centerZ + 1, intTreeLeaves, data);
            setBlock(centerX - 1, centerY + height - 2, centerZ - 1, intTreeLeaves, data);
            // world.getBlockAt(centerX + 1, centerY + height - 1, centerZ +
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX + 1, centerY + height - 1, centerZ -
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX - 1, centerY + height - 1, centerZ +
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX - 1, centerY + height - 1, centerZ -
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX + 1, centerY + height - 2, centerZ +
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX + 1, centerY + height - 2, centerZ -
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX - 1, centerY + height - 2, centerZ +
            // 1).setTypeIdAndData(intLeaves, data, true);
            // world.getBlockAt(centerX - 1, centerY + height - 2, centerZ -
            // 1).setTypeIdAndData(intLeaves, data, true);

            for (int j = 0; j < 2; j++) {
              for (int k = -2; k <= 2; k++) {
                for (int l = -2; l <= 2; l++) {
                  setBlock(centerX + k, centerY + height - 1 - j, centerZ + l, intTreeLeaves, data);
                  // world.getBlockAt(centerX + k, centerY + height
                  //	- 1 - j, centerZ + l).setTypeIdAndData(intLeaves, data, true);
                }
              }
            }

            for (int j = 0; j < 2; j++) {
              if (random.nextBoolean())
                clearBlock(centerX + 2, centerY + height - 1 - j, centerZ + 2);
              if (random.nextBoolean())
                clearBlock(centerX + 2, centerY + height - 1 - j, centerZ - 2);
              if (random.nextBoolean())
                clearBlock(centerX - 2, centerY + height - 1 - j, centerZ + 2);
              if (random.nextBoolean())
                clearBlock(centerX - 2, centerY + height - 1 - j, centerZ - 2);
              // if (random.nextBoolean()) {
              //	world.getBlockAt(centerX + 2, centerY + height - 1
              //		- j, centerZ + 2).setTypeIdAndData(intAir, (byte) 0, true);
              // }
              // if (random.nextBoolean()) {
              //	world.getBlockAt(centerX + 2, centerY + height - 1
              //		- j, centerZ - 2).setTypeIdAndData(intAir, (byte) 0, true);
              // }
              // if (random.nextBoolean()) {
              //	world.getBlockAt(centerX - 2, centerY + height - 1
              //		- j, centerZ + 2).setTypeIdAndData(intAir, (byte) 0, true);
              // }
              // if (random.nextBoolean()) {
              //	world.getBlockAt(centerX - 2, centerY + height - 1
              //		- j, centerZ - 2).setTypeIdAndData(intAir, (byte) 0, true);
              // }
            }
          }

          // Trunk
          for (int y = 1; y <= height; y++) {
            world
                .getBlockAt(centerX, centerY + y, centerZ)
                .setTypeIdAndData(intTreeTrunk, data, false);
          }
        }
      }
    }
  }
}
public class ShapeProvider_Floating extends ShapeProvider_Normal {

  public ShapeProvider_Floating(WorldGenerator generator, Odds odds) {
    super(generator, odds);
    long seed = generator.getWorldSeed();

    terrainShape = new SimplexNoiseGenerator(seed + 3);
    noiseShape = new SimplexNoiseGenerator(seed + 4);

    // streetLevel = height / 8 * 3;
    constructMin = seaLevel + landRange + 32;
    constructRange = height - 32 - constructMin;
  }

  @Override
  protected void allocateContexts(WorldGenerator generator) {
    if (!contextInitialized) {
      natureContext = new FloatingNatureContext(generator);
      roadContext = new FloatingRoadContext(generator);

      parkContext = new ParkContext(generator);
      highriseContext = new HighriseContext(generator);
      constructionContext = new ConstructionContext(generator);
      midriseContext = new MidriseContext(generator);
      municipalContext = new MunicipalContext(generator);
      industrialContext = new IndustrialContext(generator);
      lowriseContext = new LowriseContext(generator);
      neighborhoodContext = new NeighborhoodContext(generator);
      farmContext = new FarmContext(generator);

      contextInitialized = true;
    }
  }

  @Override
  public String getCollectionName() {
    return "Floating";
  }

  @Override
  protected void validateLots(WorldGenerator generator, PlatMap platmap) {
    // find blimp moorings
    for (int x = 0; x < PlatMap.Width; x++) {
      for (int z = 0; z < PlatMap.Width; z++) {
        if (needBlimpLot(platmap, x, z))
          platmap.setLot(
              x, z, new FloatingBlimpLot(platmap, platmap.originX + x, platmap.originZ + z));
      }
    }
  }

  private boolean needBlimpLot(PlatMap platmap, int x, int z) {
    if (platmap.isNaturalLot(x, z)) {
      return platmap.isStructureLot(x - 1, z)
          || platmap.isStructureLot(x + 1, z)
          || platmap.isStructureLot(x, z - 1)
          || platmap.isStructureLot(x, z + 1);
    } else return false;
  }

  // private int streetLevel;
  private SimplexNoiseGenerator terrainShape;
  private SimplexNoiseGenerator noiseShape;

  public static final int seaBed = 8;
  public static final int gapRange = 8;
  public static final int landRange = 16;
  public static final int seaLevel = seaBed + gapRange;
  public static final int deepSeaLevel = seaLevel - gapRange / 2;

  public static final int noiseRange = seaBed / 2;
  public static final int midRange = (gapRange + landRange) / 2;
  public static final int midPoint = seaBed + midRange;
  public static final int snowPoint = midPoint + midRange - 2;

  private static final double terrainScale = 1.0 / 281.0;
  private static final double noiseScale = 1.0 / 23.0;

  @Override
  public int getStreetLevel() {
    return super.getStreetLevel() / 2 * 3;
  }

  @Override
  public int getStructureLevel() {
    return super.getStreetLevel();
  }

  @Override
  public int findGroundY(WorldGenerator generator, int blockX, int blockZ) {

    // calculator the way down there bits
    double terrainAt = terrainShape.noise(blockX * terrainScale, blockZ * terrainScale) * midRange;
    double noiseAt = noiseShape.noise(blockX * noiseScale, blockZ * noiseScale) * noiseRange;
    return NoiseGenerator.floor(terrainAt + noiseAt) + midPoint;
  }

  @Override
  public void preGenerateChunk(
      WorldGenerator generator, PlatLot lot, ByteChunk chunk, BiomeGrid biomes, CachedYs blockYs) {
    Biome resultBiome = lot.getChunkBiome();
    OreProvider ores = generator.oreProvider;

    // shape the world
    for (int x = 0; x < chunk.width; x++) {
      for (int z = 0; z < chunk.width; z++) {
        if (generator.settings.includeFloatingSubsurface) {

          // where is the ground?
          int groundY = findGroundY(generator, chunk.getBlockX(x), chunk.getBlockZ(z));

          // make the base
          chunk.setBlock(x, 0, z, ores.substratumId);

          // place the way down there bits
          chunk.setBlocks(x, 1, groundY - 1, z, ores.stratumId);

          // seas?
          if (groundY < seaLevel) {
            chunk.setBlock(x, groundY - 1, z, ores.fluidSubsurfaceId);
            chunk.setBlock(x, groundY, z, ores.fluidSurfaceId);
            if (generator.settings.includeAbovegroundFluids) {
              if (generator.settings.includeDecayedNature)
                chunk.setBlocks(x, groundY + 1, deepSeaLevel, z, ores.fluidId);
              else chunk.setBlocks(x, groundY + 1, seaLevel, z, ores.fluidId);
            }
          } else {
            chunk.setBlock(x, groundY - 1, z, ores.subsurfaceId);
            chunk.setBlock(x, groundY, z, ores.surfaceId);
          }
        }

        // set biome for block
        biomes.setBiome(x, z, generator.oreProvider.remapBiome(resultBiome));
      }
    }
  }

  private static final double underworldOdds = 0.50;
  private static final int underworldLength = 6;
  private static final byte stoneId = (byte) Material.STONE.getId();

  @Override
  public void postGenerateChunk(
      WorldGenerator generator, PlatLot lot, ByteChunk chunk, CachedYs blockYs) {
    OreProvider ores = generator.oreProvider;
    int lotBottomY = lot.getBottomY(generator);
    if (lotBottomY != 0) {

      // shape the underworld
      if (lot.style == LotStyle.STRUCTURE || lot.style == LotStyle.ROAD) {
        for (int x = 0; x < chunk.width; x++) {
          for (int z = 0; z < chunk.width; z++) {
            if (odds.playOdds(underworldOdds)) {
              int y = lotBottomY - odds.getRandomInt(underworldLength);
              if (!chunk.isEmpty(x, lotBottomY, z))
                chunk.setBlocks(x, y, lotBottomY, z, ores.subsurfaceId);
            }
          }
        }
      }

      // cross beams
      chunk.setBlocks(7, 9, lotBottomY - 2, lotBottomY, 0, 16, stoneId);
      chunk.setBlocks(0, 16, lotBottomY - 2, lotBottomY, 7, 9, stoneId);
    }
  }

  @Override
  public void preGenerateBlocks(
      WorldGenerator generator, PlatLot lot, RealChunk chunk, CachedYs blockYs) {}

  @Override
  public void postGenerateBlocks(
      WorldGenerator generator, PlatLot lot, RealChunk chunk, CachedYs blockYs) {
    // there is always something to plant!
    lot.generateSurface(generator, chunk, true);
  }

  @Override
  public boolean isHorizontalNSShaft(int chunkX, int chunkY, int chunkZ) {
    return false;
  }

  @Override
  public boolean isHorizontalWEShaft(int chunkX, int chunkY, int chunkZ) {
    return false;
  }

  @Override
  public boolean isVerticalShaft(int chunkX, int chunkY, int chunkZ) {
    return false;
  }

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