use super::error::{GeneratorError, TryFromRangeError};
#[repr(i32)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Scale {
Block = 1,
Quad = 4,
Chunk = 16,
QuadChunk = 64,
HalfRegion = 256,
}
impl Scale {
#[must_use]
pub const fn scale_coord(&self, num: i32) -> i32 {
num / *self as i32
}
#[must_use]
pub const fn unscale_coord(&self, num: i32) -> i32 {
num * *self as i32
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
pub struct Range {
pub scale: Scale,
pub x: i32,
pub z: i32,
pub size_x: u32,
pub size_z: u32,
pub y: i32,
pub size_y: u32,
}
impl TryFrom<Range> for cubiomes_sys::Range {
type Error = GeneratorError;
fn try_from(value: Range) -> Result<Self, Self::Error> {
Ok(Self {
scale: value.scale as i32,
x: value.x,
z: value.z,
sx: value
.size_x
.try_into()
.map_err(|_| TryFromRangeError::XSizeOutOfBounds)
.and_then(|sx| err_if_zero(sx, TryFromRangeError::XSizeOutOfBounds))?,
sz: value
.size_z
.try_into()
.map_err(|_| TryFromRangeError::ZSizeOutOfBounds)
.and_then(|sz| err_if_zero(sz, TryFromRangeError::YSizeOutOfBouns))?,
y: value.y,
sy: value
.size_y
.try_into()
.map_err(|_| TryFromRangeError::YSizeOutOfBouns)?,
})
}
}
impl Range {
#[must_use]
pub fn is_inside(&self, x: i32, z: i32) -> bool {
((self.x <= self.scale.scale_coord(x))
&& (self.scale.scale_coord(x) < (self.x + self.size_x as i32)))
&& ((self.z <= self.scale.scale_coord(z))
&& (self.scale.scale_coord(z) < (self.z + self.size_z as i32)))
}
#[must_use]
pub fn global_to_local_coord(&self, x: i32, z: i32) -> Option<(u32, u32)> {
if self.is_inside(x, z) {
Some((
(self.scale.scale_coord(x) - self.x)
.try_into()
.unwrap_or_else(|_| unreachable!()),
(self.scale.scale_coord(z) - self.z)
.try_into()
.unwrap_or_else(|_| unreachable!()),
))
} else {
None
}
}
}
fn err_if_zero(num: i32, err: TryFromRangeError) -> Result<i32, TryFromRangeError> {
if num == 0 {
return Err(err);
}
Ok(num)
}