for (ChunkPosition region: regions) {
world.regionDiscovered(region);
world.getRegion(region).parse();
}
Heightmap biomeIdMap = new Heightmap();
task = "Loading chunks";
int done = 1;
int target = chunksToLoad.size();
for (ChunkPosition cp : chunksToLoad) {
progressListener.setProgress(task, done, 0, target);
done += 1;
if (loadedChunks.contains(cp))
continue;
loadedChunks.add(cp);
world.getChunk(cp).getBlockData(blocks, data, biomes);
nchunks += 1;
for (int cz = 0; cz < 16; ++cz) {
int wz = cz + cp.z*16;
for (int cx = 0; cx < 16; ++cx) {
int wx = cx + cp.x*16;
int biomeId = 0xFF & biomes[Chunk.chunkXZIndex(cx, cz)];
biomeIdMap.set(biomeId, wx, wz);
}
}
for (int cy = 0; cy < 256; ++cy) {
for (int cz = 0; cz < 16; ++cz) {
int z = cz + cp.z*16 - origin.z;
for (int cx = 0; cx < 16; ++cx) {
int x = cx + cp.x*16 - origin.x;
int index = Chunk.chunkIndex(cx, cy, cz);
Block block = Block.get(blocks[index]);
if (cx > 0 && cx < 15 && cz > 0 && cz < 15 && cy > 0 && cy < 255 &&
block != Block.STONE && block.isOpaque) {
// set obscured blocks to stone
if (Block.get(blocks[index-1]).isOpaque &&
Block.get(blocks[index+1]).isOpaque &&
Block.get(blocks[index-Chunk.X_MAX]).isOpaque &&
Block.get(blocks[index+Chunk.X_MAX]).isOpaque &&
Block.get(blocks[index-Chunk.X_MAX*Chunk.Z_MAX]).isOpaque &&
Block.get(blocks[index+Chunk.X_MAX*Chunk.Z_MAX]).isOpaque) {
octree.set(Block.STONE.id, x, cy - origin.y, z);
continue;
}
}
int metadata = 0xFF & data[index/2];
metadata >>= (cx % 2) * 4;
metadata &= 0xF;
if (block == Block.STATIONARYWATER)
block = Block.WATER;
else if (block == Block.STATIONARYLAVA)
block = Block.LAVA;
int type = block.id;
// store metadata
switch (block.id) {
case Block.VINES_ID:
if (cy < 255) {
// is this the top vine block?
index = Chunk.chunkIndex(cx, cy+1, cz);
Block above = Block.get(blocks[index]);
if (above.isSolid) {
type = type | (1<<BlockData.VINE_TOP);
}
}
break;
case Block.WATER_ID:
if (cy < 255) {
// is there water above?
index = Chunk.chunkIndex(cx, cy+1, cz);
Block above = Block.get(blocks[index]);
if (above.isWater()) {
type |= (1<<WaterModel.FULL_BLOCK);
} else if (above == Block.LILY_PAD) {
type |= (1<<BlockData.LILY_PAD);
long wx = cp.x * 16L + cx;
long wy = cy + 1;
long wz = cp.z * 16L + cz;
long pr = (wx * 3129871L) ^ (wz * 116129781L) ^ (wy);
pr = pr * pr * 42317861L + pr * 11L;
int dir = 3 & (int)(pr >> 16);
type |= (dir<<BlockData.LILY_PAD_ROTATION);
}
}
break;
case Block.LAVA_ID:
if (cy < 255) {
// is there lava above?
index = Chunk.chunkIndex(cx, cy+1, cz);
Block above = Block.get(blocks[index]);
if (above.isLava()) {
type = type | (1<<WaterModel.FULL_BLOCK);
}
}
break;
case Block.GRASS_ID:
if (cy < 255) {
// is it snow covered?
index = Chunk.chunkIndex(cx, cy+1, cz);
int blockAbove = 0xFF & blocks[index];
if (blockAbove == Block.SNOW.id) {
type = type | (1 << 8);// 9th bit is the snow bit
}
}
// fallthrough!
case Block.WOODENDOOR_ID:
case Block.IRONDOOR_ID:
{
int top = 0;
int bottom = 0;
if ((metadata & 8) != 0) {
// this is the top part of the door
top = metadata;
if (cy > 0) {
bottom = 0xFF & data[Chunk.chunkIndex(cx, cy-1, cz)/2];
bottom >>= (cx % 2) * 4;// extract metadata
bottom &= 0xF;
}
} else {
// this is the bottom part of the door
bottom = metadata;
if (cy < 255) {
top = 0xFF & data[Chunk.chunkIndex(cx, cy+1, cz)/2];
top >>= (cx % 2) * 4;// extract metadata
top &= 0xF;
}
}
type |= (top << BlockData.DOOR_TOP);
type |= (bottom << BlockData.DOOR_BOTTOM);
break;
}
default:
break;
}
type |= metadata << 8;
if (block.isEmitter)
emitters += 1;
if (block.isInvisible)
type = 0;
octree.set(type, cx + cp.x*16 - origin.x,
cy - origin.y, cz + cp.z*16 - origin.z);
}
}
}
}
grassTexture = new WorldTexture();
foliageTexture = new WorldTexture();
Set<ChunkPosition> chunkSet = new HashSet<ChunkPosition>(chunksToLoad);
task = "Finalizing octree";
done = 0;
for (ChunkPosition cp : chunksToLoad) {
// finalize grass and foliage textures
// box blur 3x3
for (int x = 0; x < 16; ++x) {
for (int z = 0; z < 16; ++z) {
int nsum = 0;
float[] grassMix = { 0, 0, 0 };
float[] foliageMix = { 0, 0, 0 };
for (int sx = x-1; sx <= x+1; ++sx) {
int wx = cp.x*16 + sx;
for (int sz = z-1; sz <= z+1; ++sz) {
int wz = cp.z*16 + sz;
ChunkPosition ccp = ChunkPosition.get(wx >> 4, wz >> 4);
if (chunkSet.contains(ccp)) {
nsum += 1;
int biomeId = biomeIdMap.get(wx, wz);
float[] grassColor = Biomes.getGrassColorLinear(biomeId);
grassMix[0] += grassColor[0];
grassMix[1] += grassColor[1];
grassMix[2] += grassColor[2];
float[] foliageColor = Biomes.getFoliageColorLinear(biomeId);