chunkgen 0.2.0

Minecraft world generation library
Documentation
use crate::world::chunk::heightmap::HeightmapType;
use crate::world::worldgen::region::WorldGenRegion;
use crate::world::worldgen::structure::structure_piece::PieceBase;
use shulkr::util::BlockPosition;
use shulkr::util::BoundingBox;
use shulkr::util::Direction;

#[derive(Debug)]
pub struct ScatteredFeature {
    pub width: i32,
    pub height: i32,
    pub depth: i32,
    pub height_position: i32,
}

impl ScatteredFeature {
    pub const fn new(width: i32, height: i32, depth: i32) -> Self {
        Self {
            width,
            height,
            depth,
            height_position: -1,
        }
    }

    pub const fn make_base(
        west: i32,
        floor: i32,
        north: i32,
        width: i32,
        height: i32,
        depth: i32,
        direction: Direction,
    ) -> PieceBase {
        let mut base = PieceBase::new(
            0,
            PieceBase::make_bounding_box(west, floor, north, direction, width, height, depth),
        );
        base.set_orientation(Some(direction));
        base
    }

    pub fn update_average_ground_height(
        &mut self,
        base: &mut PieceBase,
        region: &WorldGenRegion<'_>,
        chunk_bb: BoundingBox,
        offset: i32,
    ) -> bool {
        if self.height_position >= 0 {
            return true;
        }

        let mut total = 0;
        let mut count = 0;
        let box_ = base.bounding_box;
        for z in box_.min_z()..=box_.max_z() {
            for x in box_.min_x()..=box_.max_x() {
                if chunk_bb.is_inside(BlockPosition::new(x, 64, z)) {
                    total += region.get_height(HeightmapType::MotionBlockingNoLeaves, x, z);
                    count += 1;
                }
            }
        }

        if count == 0 {
            return false;
        }

        self.height_position = total / count;
        base.move_by(0, self.height_position - box_.min_y() + offset, 0);
        true
    }

    pub fn update_height_position_to_lowest_ground_height(
        &mut self,
        base: &mut PieceBase,
        region: &WorldGenRegion<'_>,
        offset: i32,
    ) -> bool {
        if self.height_position >= 0 {
            return true;
        }

        let mut lowest_ground_height = region.max_y() + 1;
        let mut found = false;
        let box_ = base.bounding_box;
        for z in box_.min_z()..=box_.max_z() {
            for x in box_.min_x()..=box_.max_x() {
                lowest_ground_height = lowest_ground_height.min(region.get_height(
                    HeightmapType::MotionBlockingNoLeaves,
                    x,
                    z,
                ));
                found = true;
            }
        }

        if !found {
            return false;
        }

        self.height_position = lowest_ground_height;
        base.move_by(0, self.height_position - box_.min_y() + offset, 0);
        true
    }
}