package net.glowstone.generator;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.util.noise.OctaveGenerator;
import org.bukkit.util.noise.SimplexOctaveGenerator;
import java.util.Map;
import java.util.Random;
/**
* A generator for subterranean worlds, in particular the Nether.
*/
public class UndergroundGenerator extends GlowChunkGenerator {
public UndergroundGenerator() {
// todo: populators
super();
}
@Override
public byte[] generate(World world, Random random, int chunkX, int chunkZ) {
Map<String, OctaveGenerator> octaves = getWorldOctaves(world);
OctaveGenerator noiseFloor = octaves.get("floor");
OctaveGenerator noiseCeiling = octaves.get("ceiling");
OctaveGenerator noiseJitter1 = octaves.get("jitter1");
OctaveGenerator noiseJitter2 = octaves.get("jitter2");
OctaveGenerator noiseStalactite = octaves.get("stalactite");
OctaveGenerator noiseStalagmite = octaves.get("stalagmite");
OctaveGenerator noisePlatform1 = octaves.get("platform1");
OctaveGenerator noisePlatform2 = octaves.get("platform2");
chunkX <<= 4;
chunkZ <<= 4;
Material stone = world.getEnvironment() == Environment.NETHER ? Material.NETHERRACK : Material.STONE;
int height = WORLD_DEPTH;
byte[] buf = start(stone);
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
int min = (int) (Math.abs(noiseFloor.noise(x + chunkX, z + chunkZ, 0.5, 0.5) * 3)
+ 5 + noiseJitter1.noise(x + chunkX, z + chunkZ, 0.5, 0.5) * 2
+ convertPointyThings(noiseStalagmite, x + chunkX, z + chunkZ, height));
int max = (int) (height - Math.abs(noiseCeiling.noise(x + chunkX, z + chunkZ, 0.5, 0.5) * 3)
- 5 + noiseJitter2.noise(x + chunkX, z + chunkZ, 0.5, 0.5) * 2 - random.nextInt(5)
- convertPointyThings(noiseStalactite, x + chunkX, z + chunkZ, height));
if (min > 20) {
min -= random.nextInt(5);
}
if (min >= max) {
set(buf, x, 0, z, Material.BEDROCK);
set(buf, x, height - 1, z, Material.BEDROCK);
continue;
}
for (int y = min; y <= max; y++) {
set(buf, x, y, z, Material.AIR);
}
int platform = (int) (noisePlatform1.noise(x + chunkX, z + chunkZ, 0.5, 0.5, true) * 20 - 4);
if (platform > 5) {
platform -= random.nextInt(3);
}
while (platform-- > 0) {
set(buf, x, height / 2 - platform - 1, z, stone);
}
platform = (int) (noisePlatform2.noise(x + chunkX, z + chunkZ, 0.5, 0.5, true) * 30 - 6);
if (platform > 5) {
platform -= random.nextInt(3);
}
while (platform-- > 0) {
set(buf, x, height / 4 - platform - 1, z, stone);
}
for (int i = 4; i > 0; i--) {
if (get(buf, x, i, z) == Material.AIR) {
set(buf, x, i, z, Material.LAVA);
}
}
set(buf, x, 0, z, Material.BEDROCK);
set(buf, x, height - 1, z, Material.BEDROCK);
}
}
return buf;
}
private double convertPointyThings(OctaveGenerator noise, int x, int z, int height) {
return Math.max(noise.noise(x, z, 0.5, 0.5, true) * height * 3 / 2 - height / 2, 0);
}
@Override
public Location getFixedSpawnLocation(World world, Random random) {
while (true) {
int x = random.nextInt(WORLD_DEPTH) - 64;
int y = WORLD_DEPTH * 3 / 4;
int z = random.nextInt(WORLD_DEPTH) - 64;
if (world.getBlockAt(x, y, z).isEmpty()) {
while (world.getBlockAt(x, y - 1, z).isEmpty() && y > 0) {
y--;
}
return new Location(world, x, y, z);
}
}
}
@Override
protected void createWorldOctaves(World world, Map<String, OctaveGenerator> octaves) {
Random seed = new Random(world.getSeed());
OctaveGenerator gen = new SimplexOctaveGenerator(seed, 10);
gen.setScale(1 / 64.0);
octaves.put("floor", gen);
gen = new SimplexOctaveGenerator(seed, 10);
gen.setScale(1 / 64.0);
octaves.put("ceiling", gen);
gen = new SimplexOctaveGenerator(seed, 5);
gen.setScale(1 / 32.0);
octaves.put("jitter1", gen);
gen = new SimplexOctaveGenerator(seed, 5);
gen.setScale(1 / 32.0);
octaves.put("jitter2", gen);
gen = new SimplexOctaveGenerator(seed, 10);
gen.setScale(1 / 32.0);
octaves.put("stalactite", gen);
gen = new SimplexOctaveGenerator(seed, 10);
gen.setScale(1 / 48.0);
octaves.put("stalagmite", gen);
gen = new SimplexOctaveGenerator(seed, 7);
gen.setScale(1 / 32.0);
octaves.put("platform1", gen);
gen = new SimplexOctaveGenerator(seed, 8);
gen.setScale(1 / 96.0);
octaves.put("platform2", gen);
}
}