@Override
  public void spawn(LocalWorld world, Random rand, boolean villageInChunk, int x, int z) {
    int y = rand.nextInt(maxAltitude - minAltitude) + minAltitude;

    for (int i = 0; i < 10; i++) {
      int cactusX = x + rand.nextInt(8) - rand.nextInt(8);
      int cactusBaseY = y + rand.nextInt(4) - rand.nextInt(4);
      int cactusZ = z + rand.nextInt(8) - rand.nextInt(8);

      // Check position
      if (!world.isEmpty(cactusX, cactusBaseY, cactusZ)) continue;

      // Check foundation
      LocalMaterialData foundationMaterial = world.getMaterial(cactusX, cactusBaseY - 1, cactusZ);
      if (!sourceBlocks.contains(foundationMaterial)) continue;

      // Check neighbors
      if (!world.isEmpty(cactusX - 1, cactusBaseY, cactusZ)) continue;
      if (!world.isEmpty(cactusX + 1, cactusBaseY, cactusZ)) continue;
      if (!world.isEmpty(cactusX, cactusBaseY, cactusZ + 1)) continue;
      if (!world.isEmpty(cactusX, cactusBaseY, cactusZ + 1)) continue;

      // Spawn cactus
      int cactusHeight = 1 + rand.nextInt(rand.nextInt(3) + 1);
      for (int dY = 0; dY < cactusHeight; dY++) {
        world.setBlock(cactusX, cactusBaseY + dY, cactusZ, material);
      }
    }
  }
  @Override
  public void spawn(LocalWorld world, Random rand, boolean villageInChunk, int x, int z) {
    int y = rand.nextInt(maxAltitude - minAltitude) + minAltitude;

    if (!sourceBlocks.contains(world.getMaterial(x, y + 1, z))) return;
    if (!sourceBlocks.contains(world.getMaterial(x, y - 1, z))) return;

    if (!world.isEmpty(x, y, z) && (!sourceBlocks.contains(world.getMaterial(x, y, z)))) return;

    int i = 0;
    int j = 0;

    LocalMaterialData tempBlock = world.getMaterial(x - 1, y, z);

    i = (sourceBlocks.contains(tempBlock)) ? i + 1 : i;
    j = (tempBlock.isMaterial(DefaultMaterial.AIR)) ? j + 1 : j;

    tempBlock = world.getMaterial(x + 1, y, z);

    i = (sourceBlocks.contains(tempBlock)) ? i + 1 : i;
    j = (tempBlock.isMaterial(DefaultMaterial.AIR)) ? j + 1 : j;

    tempBlock = world.getMaterial(x, y, z - 1);

    i = (sourceBlocks.contains(tempBlock)) ? i + 1 : i;
    j = (tempBlock.isMaterial(DefaultMaterial.AIR)) ? j + 1 : j;

    tempBlock = world.getMaterial(x, y, z + 1);

    i = (sourceBlocks.contains(tempBlock)) ? i + 1 : i;
    j = (tempBlock.isMaterial(DefaultMaterial.AIR)) ? j + 1 : j;

    if ((i == 3) && (j == 1)) {
      world.setBlock(x, y, z, material);
    }
  }