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 / springs.rs

//! Ports of `WorldGenLiquids` and `WorldGenHellLava`.

use common::world::Block;

use crate::blocks;
use crate::level::Level;

/// `WorldGenLiquids`: a fluid source in a stone wall with exactly one open side.
///
/// The original passes the population random to the first update, but a fresh source
/// (or the obsidian lava hardens into) never draws from it.
pub fn generate(level: &mut Level, [x, y, z]: [i32; 3], fluid: Block) {
    if level.block(x, y + 1, z) == Block::STONE && level.block(x, y - 1, z) == Block::STONE {
        place(
            level,
            [x, y, z],
            fluid,
            Block::STONE,
            &[(-1, 0, 0), (1, 0, 0), (0, 0, -1), (0, 0, 1)],
        );
    }
}

/// `WorldGenHellLava`: a lava source in a netherrack pocket open on one side.
pub fn hell_lava(level: &mut Level, [x, y, z]: [i32; 3]) {
    if level.block(x, y + 1, z) == Block::NETHERRACK {
        let sides = [(-1, 0, 0), (1, 0, 0), (0, 0, -1), (0, 0, 1), (0, -1, 0)];
        place(
            level,
            [x, y, z],
            Block::FLOWING_LAVA,
            Block::NETHERRACK,
            &sides,
        );
    }
}

/// Places `fluid` in air or `rock` if exactly one of `sides` is open and the rest are `rock`.
/// Its first update runs with scheduled updates made immediate, so the flow settles at once.
fn place(
    level: &mut Level,
    [x, y, z]: [i32; 3],
    fluid: Block,
    rock: Block,
    sides: &[(i32, i32, i32)],
) {
    let current = level.block(x, y, z);
    if current != Block::AIR && current != rock {
        return;
    }
    let mut count = |block| {
        sides
            .iter()
            .filter(|&&(dx, dy, dz)| level.block(x + dx, y + dy, z + dz) == block)
            .count()
    };
    if (count(rock), count(Block::AIR)) == (sides.len() - 1, 1) {
        level.set_block_notify(x, y, z, fluid);
        level.immediate_ticks = true;
        blocks::update_tick(level, fluid, x, y, z);
        level.immediate_ticks = false;
    }
}