chunkgen 0.2.0

Minecraft world generation library
Documentation
use shulkr::world::block::BlockState;

use crate::world::worldgen::region::WorldGenRegion;
use shulkr::util::BlockPosition;

#[derive(Debug, Clone, Copy)]
pub struct Column {
    floor: Option<i32>,
    ceiling: Option<i32>,
}

impl Column {
    pub const fn create(floor: Option<i32>, ceiling: Option<i32>) -> Self {
        Self { floor, ceiling }
    }

    pub const fn floor(self) -> Option<i32> {
        self.floor
    }

    pub const fn ceiling(self) -> Option<i32> {
        self.ceiling
    }

    pub const fn height(self) -> Option<i32> {
        match (self.floor, self.ceiling) {
            (Some(floor), Some(ceiling)) => Some(ceiling - floor - 1),
            _ => None,
        }
    }

    pub const fn with_floor(self, floor: Option<i32>) -> Self {
        Self::create(floor, self.ceiling)
    }

    pub fn scan(
        region: &WorldGenRegion<'_>,
        pos: BlockPosition,
        search_range: i32,
        inside_column: impl Fn(BlockState) -> bool,
        valid_edge: impl Fn(BlockState) -> bool,
    ) -> Option<Self> {
        if !inside_column(region.get_block(pos)) {
            return None;
        }

        let ceiling = scan_direction(region, search_range, &inside_column, &valid_edge, pos, true);
        let floor = scan_direction(
            region,
            search_range,
            &inside_column,
            &valid_edge,
            pos,
            false,
        );
        Some(Self::create(floor, ceiling))
    }
}

fn scan_direction(
    region: &WorldGenRegion<'_>,
    search_range: i32,
    inside_column: &impl Fn(BlockState) -> bool,
    valid_edge: &impl Fn(BlockState) -> bool,
    start: BlockPosition,
    up: bool,
) -> Option<i32> {
    let mut pos = start;
    let mut i = 1;
    while i < search_range && inside_column(region.get_block(pos)) {
        pos = if up { pos.above() } else { pos.below() };
        i += 1;
    }

    if valid_edge(region.get_block(pos)) {
        Some(pos.y())
    } else {
        None
    }
}