Theme

alex/beta-minecraft-rust

Minecraft Beta 1.7.3 Rewrite

BRANCH main
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
Download file

root / crates / server / src / populate / ores.rs

//! Ports of `WorldGenMinable` and `WorldGenClay`: blobs along a random segment.

use std::f32::consts::PI;

use common::JavaRandom;
use common::math::{self, floor_f64};
use common::world::{Block, Material};

use crate::level::Level;

/// `WorldGenMinable`: replaces stone.
pub fn vein(level: &mut Level, pos: [i32; 3], rand: &mut JavaRandom, ore: Block, size: i32) {
    blob(level, pos, rand, size, [Block::STONE, ore]);
}

/// `WorldGenClay`: replaces sand, starting only in water.
pub fn clay(level: &mut Level, [x, y, z]: [i32; 3], rand: &mut JavaRandom, size: i32) {
    if level.material(x, y, z) == Material::Water {
        blob(level, [x, y, z], rand, size, [Block::SAND, Block::CLAY]);
    }
}

/// `size + 1` spheres of varying radii along a segment centered around (x + 8, z + 8),
/// replacing `from` with `to`.
fn blob(
    level: &mut Level,
    [x, y, z]: [i32; 3],
    rand: &mut JavaRandom,
    size: i32,
    [from, to]: [Block; 2],
) {
    let angle = rand.next_float() * PI;
    let reach = |offset: f32| offset * size as f32 / 8.0;
    let (sin, cos) = (reach(math::sin(angle)), reach(math::cos(angle)));
    let (x, z) = ((x + 8) as f32, (z + 8) as f32);
    let start = [
        f64::from(x + sin),
        f64::from(y + rand.next_int(3) + 2),
        f64::from(z + cos),
    ];
    let end = [
        f64::from(x - sin),
        f64::from(y + rand.next_int(3) + 2),
        f64::from(z - cos),
    ];
    for step in 0..=size {
        let t = |axis: usize| {
            start[axis] + (end[axis] - start[axis]) * f64::from(step) / f64::from(size)
        };
        let (cx, cy, cz) = (t(0), t(1), t(2));
        let scale = rand.next_double() * f64::from(size) / 16.0;
        let bulge = math::sin(step as f32 * PI / size as f32) + 1.0;
        let radius = (f64::from(bulge) * scale + 1.0) / 2.0;
        for bx in floor_f64(cx - radius)..=floor_f64(cx + radius) {
            let dx = (f64::from(bx) + 0.5 - cx) / radius;
            if dx * dx >= 1.0 {
                continue;
            }
            for by in floor_f64(cy - radius)..=floor_f64(cy + radius) {
                let dy = (f64::from(by) + 0.5 - cy) / radius;
                if dx * dx + dy * dy >= 1.0 {
                    continue;
                }
                for bz in floor_f64(cz - radius)..=floor_f64(cz + radius) {
                    let dz = (f64::from(bz) + 0.5 - cz) / radius;
                    if dx * dx + dy * dy + dz * dz < 1.0 && level.block(bx, by, bz) == from {
                        level.set_block(bx, by, bz, to);
                    }
                }
            }
        }
    }
}