chunkgen 0.2.0

Minecraft world generation library
Documentation
use shulkr::util::Axis;
use shulkr::util::Direction;
use shulkr::world::block::{Mirror, Rotation};

pub trait MirrorExt {
    fn mirror_index(self, rotation: i32, steps: i32) -> i32;

    fn get_rotation(self, direction: Direction) -> Rotation;

    fn mirror(self, direction: Direction) -> Direction;
}

impl MirrorExt for Mirror {
    fn mirror_index(self, rotation: i32, steps: i32) -> i32 {
        let half_steps = steps / 2;
        let corrected = if rotation > half_steps {
            rotation - steps
        } else {
            rotation
        };
        match self {
            Self::LeftRight => (half_steps - corrected + steps) % steps,
            Self::FrontBack => (steps - corrected) % steps,
            Self::None => rotation,
        }
    }

    fn get_rotation(self, direction: Direction) -> Rotation {
        let axis = direction.get_axis();
        match self {
            Self::LeftRight if matches!(axis, Axis::Z) => Rotation::Clockwise180,
            Self::FrontBack if matches!(axis, Axis::X) => Rotation::Clockwise180,
            _ => Rotation::None,
        }
    }

    fn mirror(self, direction: Direction) -> Direction {
        match self {
            Self::FrontBack if matches!(direction.get_axis(), Axis::X) => direction.opposite(),
            Self::LeftRight if matches!(direction.get_axis(), Axis::Z) => direction.opposite(),
            _ => direction,
        }
    }
}

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

    #[test]
    fn mirror_flips_only_the_matching_axis() {
        assert_eq!(Mirror::FrontBack.mirror(Direction::East), Direction::West);
        assert_eq!(Mirror::FrontBack.mirror(Direction::North), Direction::North);
        assert_eq!(Mirror::LeftRight.mirror(Direction::North), Direction::South);
        assert_eq!(Mirror::LeftRight.mirror(Direction::East), Direction::East);
        assert_eq!(Mirror::None.mirror(Direction::East), Direction::East);
    }

    #[test]
    fn get_rotation_matches_vanilla() {
        assert_eq!(
            Mirror::LeftRight.get_rotation(Direction::North),
            Rotation::Clockwise180
        );
        assert_eq!(
            Mirror::LeftRight.get_rotation(Direction::East),
            Rotation::None
        );
        assert_eq!(
            Mirror::FrontBack.get_rotation(Direction::West),
            Rotation::Clockwise180
        );
    }

    #[test]
    fn mirror_index_matches_vanilla_for_16_steps() {
        assert_eq!(Mirror::None.mirror_index(3, 16), 3);
        assert_eq!(Mirror::LeftRight.mirror_index(0, 16), 8);
        assert_eq!(Mirror::LeftRight.mirror_index(12, 16), 12);
        assert_eq!(Mirror::FrontBack.mirror_index(4, 16), 12);
        assert_eq!(Mirror::FrontBack.mirror_index(0, 16), 0);
    }
}