chunkgen 0.2.0

Minecraft world generation library
Documentation
use crate::util::rng::RandomSource;
use crate::world::worldgen::structure::pieces::pieces_container::PiecesContainer;
use crate::world::worldgen::structure::structure_piece::{StructurePiece, create_bounding_box};
use shulkr::util::BoundingBox;

#[derive(Debug, Default)]
pub struct StructurePiecesBuilder {
    pieces: Vec<StructurePiece>,
}

impl StructurePiecesBuilder {
    pub const fn new() -> Self {
        Self { pieces: Vec::new() }
    }

    pub fn add_piece(&mut self, piece: StructurePiece) {
        self.pieces.push(piece);
    }

    pub fn add_piece_indexed(&mut self, piece: StructurePiece) -> usize {
        self.pieces.push(piece);
        self.pieces.len() - 1
    }

    pub fn piece_at(&self, index: usize) -> &StructurePiece {
        &self.pieces[index]
    }

    pub fn piece_at_mut(&mut self, index: usize) -> &mut StructurePiece {
        &mut self.pieces[index]
    }

    pub fn move_below_sea_level(
        &mut self,
        sea_level: i32,
        min_y: i32,
        random: &mut RandomSource,
        offset: i32,
    ) -> i32 {
        let max_y = sea_level - offset;
        let bounding_box = self.get_bounding_box();
        let mut y1_pos = bounding_box.y_span() + min_y + 1;
        if y1_pos < max_y {
            y1_pos += random.next_i32_bounded(max_y - y1_pos);
        }
        let dy = y1_pos - bounding_box.max_y();
        self.offset_pieces_vertically(dy);
        dy
    }

    pub fn find_collision_piece(&self, box_: BoundingBox) -> Option<&StructurePiece> {
        self.pieces
            .iter()
            .find(|piece| piece.bounding_box().intersects(box_))
    }

    pub fn offset_pieces_vertically(&mut self, dy: i32) {
        for piece in &mut self.pieces {
            piece.move_by(0, dy, 0);
        }
    }

    pub fn take_pieces(self) -> Vec<StructurePiece> {
        self.pieces
    }

    pub fn move_inside_heights(
        &mut self,
        random: &mut RandomSource,
        lowest_allowed: i32,
        highest_allowed: i32,
    ) {
        let bounding_box = self.get_bounding_box();
        let height_span = highest_allowed - lowest_allowed + 1 - bounding_box.y_span();
        let y0_pos = if height_span > 1 {
            lowest_allowed + random.next_i32_bounded(height_span)
        } else {
            lowest_allowed
        };
        let dy = y0_pos - bounding_box.min_y();
        self.offset_pieces_vertically(dy);
    }

    pub fn build(self) -> PiecesContainer {
        PiecesContainer::new(self.pieces)
    }

    pub fn clear(&mut self) {
        self.pieces.clear();
    }

    pub const fn is_empty(&self) -> bool {
        self.pieces.is_empty()
    }

    pub fn get_bounding_box(&self) -> BoundingBox {
        create_bounding_box(&self.pieces).expect("Unable to calculate boundingbox without pieces")
    }
}