chunkgen 0.2.0

Minecraft world generation library
Documentation
use crate::world::chunk::heightmap::HeightmapType;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum ChunkStatus {
    Empty,
    StructureStarts,
    StructureReferences,
    Biomes,
    Terrain,
    Features,
    InitializeLight,
    Light,
    Spawn,
    Full,
}

impl ChunkStatus {
    pub const fn get_index(self) -> usize {
        self as usize
    }

    pub const fn next(self) -> Option<Self> {
        match self {
            Self::Empty => Some(Self::StructureStarts),
            Self::StructureStarts => Some(Self::StructureReferences),
            Self::StructureReferences => Some(Self::Biomes),
            Self::Biomes => Some(Self::Terrain),
            Self::Terrain => Some(Self::Features),
            Self::Features => Some(Self::InitializeLight),
            Self::InitializeLight => Some(Self::Light),
            Self::Light => Some(Self::Spawn),
            Self::Spawn => Some(Self::Full),
            Self::Full => None,
        }
    }

    pub const fn parent(self) -> Option<Self> {
        match self {
            Self::Empty => None,
            Self::StructureStarts => Some(Self::Empty),
            Self::StructureReferences => Some(Self::StructureStarts),
            Self::Biomes => Some(Self::StructureReferences),
            Self::Terrain => Some(Self::Biomes),
            Self::Features => Some(Self::Terrain),
            Self::InitializeLight => Some(Self::Features),
            Self::Light => Some(Self::InitializeLight),
            Self::Spawn => Some(Self::Light),
            Self::Full => Some(Self::Spawn),
        }
    }

    pub const fn heightmaps_after(self) -> &'static [HeightmapType] {
        match self {
            Self::Empty | Self::StructureStarts | Self::StructureReferences | Self::Biomes => {
                HeightmapType::worldgen_types()
            }
            Self::Terrain
            | Self::Features
            | Self::InitializeLight
            | Self::Light
            | Self::Spawn
            | Self::Full => HeightmapType::final_types(),
        }
    }

    pub const fn requirements(self) -> &'static [(ChunkStatus, usize)] {
        match self {
            Self::Empty | Self::StructureStarts | Self::InitializeLight | Self::Full => &[],
            Self::StructureReferences | Self::Biomes => &[(Self::StructureStarts, 8)],
            Self::Terrain => &[(Self::StructureStarts, 8), (Self::Biomes, 1)],
            Self::Features => &[(Self::StructureStarts, 8), (Self::Terrain, 1)],
            Self::Light => &[(Self::InitializeLight, 1)],
            Self::Spawn => &[(Self::Biomes, 1)],
        }
    }
}

impl TryFrom<usize> for ChunkStatus {
    type Error = ();

    fn try_from(value: usize) -> Result<Self, Self::Error> {
        Ok(match value {
            0 => Self::Empty,
            1 => Self::StructureStarts,
            2 => Self::StructureReferences,
            3 => Self::Biomes,
            4 => Self::Terrain,
            5 => Self::Features,
            6 => Self::InitializeLight,
            7 => Self::Light,
            8 => Self::Spawn,
            9 => Self::Full,
            _ => return Err(()),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn index_roundtrips() {
        for index in 0..=9 {
            let status = ChunkStatus::try_from(index).expect("valid index");
            assert_eq!(status.get_index(), index);
        }
        assert_eq!(ChunkStatus::try_from(10), Err(()));
    }

    #[test]
    fn next_and_parent_are_inverses() {
        let mut status = ChunkStatus::Empty;
        while let Some(next) = status.next() {
            assert_eq!(next.parent(), Some(status));
            status = next;
        }
        assert_eq!(status, ChunkStatus::Full);
    }

    #[test]
    fn requirements_match_vanilla_generation_pyramid() {
        assert_eq!(ChunkStatus::Empty.requirements(), &[]);
        assert_eq!(
            ChunkStatus::StructureReferences.requirements(),
            &[(ChunkStatus::StructureStarts, 8)]
        );
        assert_eq!(
            ChunkStatus::Terrain.requirements(),
            &[(ChunkStatus::StructureStarts, 8), (ChunkStatus::Biomes, 1)]
        );
        assert_eq!(
            ChunkStatus::Features.requirements(),
            &[(ChunkStatus::StructureStarts, 8), (ChunkStatus::Terrain, 1)]
        );
        assert_eq!(
            ChunkStatus::Light.requirements(),
            &[(ChunkStatus::InitializeLight, 1)]
        );
        assert_eq!(
            ChunkStatus::Spawn.requirements(),
            &[(ChunkStatus::Biomes, 1)]
        );
    }
}