alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates server src populate lakes.rs
//! Port of `WorldGenLakes`.
use std::ops::Range;
use common::JavaRandom;
use common::world::{Block, Material};
use crate::level::{Level, LightKind};
const fn slot(x: usize, z: usize, y: usize) -> usize {
(x * 16 + z) * 8 + y
}
/// The cells of the lake's box in the original loop order: x, then z, then y.
fn cells(xz: Range<usize>, y: Range<usize>) -> impl Iterator<Item = (usize, usize, usize)> {
let z = xz.clone();
xz.flat_map(move |i| {
let y = y.clone();
z.clone()
.flat_map(move |j| y.clone().map(move |k| (i, j, k)))
})
}
/// A 16x8x16 blob of overlapping ellipsoids: liquid in the lower half, air above.
pub fn generate(level: &mut Level, [x, y, z]: [i32; 3], rand: &mut JavaRandom, liquid: Block) {
let (x, z) = (x - 8, z - 8);
let mut y = y;
while y > 0 && level.is_air(x, y, z) {
y -= 1;
}
y -= 4;
let mut shape = [false; 2048];
for _ in 0..rand.next_int(4) + 4 {
let size_x = rand.next_double() * 6.0 + 3.0;
let size_y = rand.next_double() * 4.0 + 2.0;
let size_z = rand.next_double() * 6.0 + 3.0;
let center_x = rand.next_double() * (16.0 - size_x - 2.0) + 1.0 + size_x / 2.0;
let center_y = rand.next_double() * (8.0 - size_y - 4.0) + 2.0 + size_y / 2.0;
let center_z = rand.next_double() * (16.0 - size_z - 2.0) + 1.0 + size_z / 2.0;
for (i, j, k) in cells(1..15, 1..7) {
let dx = (i as f64 - center_x) / (size_x / 2.0);
let dy = (k as f64 - center_y) / (size_y / 2.0);
let dz = (j as f64 - center_z) / (size_z / 2.0);
if dx * dx + dy * dy + dz * dz < 1.0 {
shape[slot(i, j, k)] = true;
}
}
}
let border = |i: usize, j: usize, k: usize| {
!shape[slot(i, j, k)]
&& (i < 15 && shape[slot(i + 1, j, k)]
|| i > 0 && shape[slot(i - 1, j, k)]
|| j < 15 && shape[slot(i, j + 1, k)]
|| j > 0 && shape[slot(i, j - 1, k)]
|| k < 7 && shape[slot(i, j, k + 1)]
|| k > 0 && shape[slot(i, j, k - 1)])
};
let at = |i: usize, j: usize, k: usize| (x + i as i32, y + k as i32, z + j as i32);
for (i, j, k) in cells(0..16, 0..8).filter(|&(i, j, k)| border(i, j, k)) {
let (bx, by, bz) = at(i, j, k);
let material = level.material(bx, by, bz);
if k >= 4 && material.is_liquid() {
return;
}
if k < 4 && !material.is_solid() && level.block(bx, by, bz) != liquid {
return;
}
}
for (i, j, k) in cells(0..16, 0..8).filter(|&(i, j, k)| shape[slot(i, j, k)]) {
let (bx, by, bz) = at(i, j, k);
level.set_block(bx, by, bz, if k >= 4 { Block::AIR } else { liquid });
}
for (i, j, k) in cells(0..16, 4..8).filter(|&(i, j, k)| shape[slot(i, j, k)]) {
let (bx, by, bz) = at(i, j, k);
if level.block(bx, by - 1, bz) == Block::DIRT
&& level.saved_light(LightKind::Sky, bx, by, bz) > 0
{
level.set_block(bx, by - 1, bz, Block::GRASS);
}
}
if liquid.material() == Material::Lava {
for (i, j, k) in cells(0..16, 0..8).filter(|&(i, j, k)| border(i, j, k)) {
let (bx, by, bz) = at(i, j, k);
if (k < 4 || rand.next_int(2) != 0) && level.material(bx, by, bz).is_solid() {
level.set_block(bx, by, bz, Block::STONE);
}
}
}
}