mcrs 0.4.3

Interface with a local Minecraft server
Documentation
use std::{fmt, ops};

use crate::{Coordinate, Size2D};

/// 3D size in blocks.
///
/// Used by [`Chunk`].
///
/// [`Chunk`]: crate::Chunk
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub struct Size {
    pub x: u32,
    pub y: u32,
    pub z: u32,
}

impl Size {
    pub const fn new(x: u32, y: u32, z: u32) -> Self {
        Self { x, y, z }
    }

    /// Returns `true` if the **offset** [`Coordinate`] is within the size.
    pub fn contains(self, coordinate: impl Into<Coordinate>) -> bool {
        let coordinate = coordinate.into();
        (0..self.x as i32).contains(&coordinate.x)
            && (0..self.y as i32).contains(&coordinate.y)
            && (0..self.z as i32).contains(&coordinate.z)
    }

    /// Convert a [`Chunk`] index to an **offset** [`Coordinate`].
    ///
    /// [`Chunk`]: crate::Chunk
    pub const fn index_to_offset(self, index: usize) -> Coordinate {
        let z = (index % self.z as usize) as i32;
        let xy = index / self.z as usize;
        let x = (xy % self.x as usize) as i32;
        let y = (xy / self.x as usize) as i32;
        Coordinate { x, y, z }
    }

    /// Convert an **offset** [`Coordinate`] to a [`Chunk`] index.
    ///
    /// [`Chunk`]: crate::Chunk
    pub fn offset_to_index(self, coordinate: impl Into<Coordinate>) -> usize {
        let coordinate = coordinate.into();
        let [x, y, z] = [
            coordinate.x as usize,
            coordinate.y as usize,
            coordinate.z as usize,
        ];
        z + (x + y * self.x as usize) * self.z as usize
    }

    /// Returns the amount of blocks in the cuboid volume.
    pub fn volume(self) -> usize {
        self.x as usize * self.y as usize * self.z as usize
    }

    // TODO(doc)
    pub fn flat(self) -> Size2D {
        self.into()
    }
}

impl fmt::Display for Size {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}x{}x{}", self.x, self.y, self.z)
    }
}
impl fmt::Debug for Size {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Size({}, {}, {})", self.x, self.y, self.z)
    }
}

impl<T> ops::Add<T> for Size
where
    T: Into<Self>,
{
    type Output = Self;

    fn add(self, rhs: T) -> Self::Output {
        let rhs = rhs.into();
        Self {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
            z: self.z + rhs.z,
        }
    }
}
impl<T> ops::Sub<T> for Size
where
    T: Into<Self>,
{
    type Output = Self;

    fn sub(self, rhs: T) -> Self::Output {
        let rhs = rhs.into();
        Self {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
            z: self.z - rhs.z,
        }
    }
}

impl<T> ops::Mul<T> for Size
where
    T: Into<Self>,
{
    type Output = Self;

    fn mul(self, rhs: T) -> Self::Output {
        let rhs = rhs.into();
        Self {
            x: self.x * rhs.x,
            y: self.y * rhs.y,
            z: self.z * rhs.z,
        }
    }
}

impl ops::Mul<u32> for Size {
    type Output = Self;

    fn mul(self, rhs: u32) -> Self::Output {
        Self {
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs,
        }
    }
}
impl ops::Div<u32> for Size {
    type Output = Self;

    fn div(self, rhs: u32) -> Self::Output {
        Self {
            x: self.x / rhs,
            y: self.y / rhs,
            z: self.z / rhs,
        }
    }
}

impl ops::Add<Size2D> for Size {
    type Output = Self;

    fn add(self, rhs: Size2D) -> Self::Output {
        Self {
            x: self.x + rhs.x,
            y: self.y,
            z: self.z + rhs.z,
        }
    }
}

impl ops::Sub<Size2D> for Size {
    type Output = Self;

    fn sub(self, rhs: Size2D) -> Self::Output {
        Self {
            x: self.x - rhs.x,
            y: self.y,
            z: self.z - rhs.z,
        }
    }
}

impl From<[u32; 3]> for Size {
    fn from(value: [u32; 3]) -> Self {
        Self {
            x: value[0],
            y: value[1],
            z: value[2],
        }
    }
}
impl From<(u32, u32, u32)> for Size {
    fn from(value: (u32, u32, u32)) -> Self {
        Self {
            x: value.0,
            y: value.1,
            z: value.2,
        }
    }
}