rezcraft 0.2.0

Minecraft like game written in rust using wgpu, supporting both native and wasm
Documentation
use std::{iter, num::NonZeroI32};

use block_mesh::ndshape::ConstShape;
use cgmath::Vector3;
use noise::{Cache, NoiseFn, Perlin};
use rand::prelude::*;

use crate::{
    game::world::{Block, BlockBuffer, BlockManager, ChunkShape, CHUNK_SIZE},
    misc::pos::Pos,
};

const BASE_GROUND_LEVEL: f64 = -10.0;
const SEA_LEVEL: i32 = 0;
const HILLINESS: f64 = 20.0;
const LEVELS_OF_DIRT: u32 = 5;

#[derive(Clone, Debug)]
pub struct TerrainGenerator {
    #[allow(dead_code)]
    seed: u32,
    noise: Cache<Perlin>,
    block_manager: BlockManager,
}

impl TerrainGenerator {
    pub fn new(seed: u32, block_manager: BlockManager) -> Self {
        Self {
            seed,
            block_manager,
            noise: Cache::new(Perlin::new(seed)),
        }
    }

    pub fn generate_blocks(&mut self, chunk_pos: &Vector3<NonZeroI32>) -> BlockBuffer {
        let mut blocks = Vec::from_iter(iter::repeat(Block::default()).take((CHUNK_SIZE as usize).pow(3)));

        for x in 0..CHUNK_SIZE as usize {
            for y in 0..CHUNK_SIZE as usize {
                for z in 0..CHUNK_SIZE as usize {
                    let block_pos = Pos::new(*chunk_pos, Vector3::new(x as f32, y as f32, z as f32));

                    let index = block_pos.in_chunk_pos_i32();
                    blocks[ChunkShape::linearize([index.x as u32, index.y as u32, index.z as u32]) as usize] = self
                        .generate_block(&{
                            let abs_pos = block_pos.abs_pos();
                            Vector3::new(abs_pos.x as i32, abs_pos.y as i32, abs_pos.z as i32)
                        });
                }
            }
        }

        BlockBuffer::new(blocks)
    }

    fn generate_block(&mut self, abs_pos: &Vector3<i32>) -> Block {
        let xy = [abs_pos.x as f64 / 100.0, abs_pos.z as f64 / 100.0];
        let ground_y = (BASE_GROUND_LEVEL - ((self.noise.get(xy) - 0.5) * HILLINESS)) as i32;

        let block_name = if abs_pos.y > ground_y {
            if abs_pos.y <= SEA_LEVEL {
                "Water"
            } else {
                "Air"
            }
        } else {
            if abs_pos.y == ground_y {
                if ground_y < SEA_LEVEL {
                    "Sand"
                } else {
                    "Grass"
                }
            } else if abs_pos.y > ground_y - LEVELS_OF_DIRT as i32 {
                if ground_y < SEA_LEVEL {
                    "Sand"
                } else {
                    "Dirt"
                }
            } else {
                "Stone"
            }
        };

        Block::new_with_default(block_name, &self.block_manager)
    }

    pub fn generate_seed() -> u32 {
        let mut rng = rand::thread_rng();
        rng.gen()
    }
}