diff --git a/pumpkin-world/src/coordinates.rs b/pumpkin-world/src/coordinates.rs index 0873d0e80..93056f531 100644 --- a/pumpkin-world/src/coordinates.rs +++ b/pumpkin-world/src/coordinates.rs @@ -1,31 +1,38 @@ use std::ops::Deref; +use num_traits::{PrimInt, Signed, Unsigned}; +use serde::{Deserialize, Serialize}; + use crate::{WORLD_LOWEST_Y, WORLD_MAX_Y}; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +#[serde(transparent)] pub struct Height { height: i16, } impl Height { - pub fn new(height: i16) -> Self { - assert!(height <= WORLD_MAX_Y); - assert!(height >= WORLD_LOWEST_Y); - - Self { height } - } - pub fn from_absolute(height: u16) -> Self { - Self::new(height as i16 - WORLD_LOWEST_Y.abs()) + (height as i16 - WORLD_LOWEST_Y.abs()).into() } /// Absolute height ranges from `0..WORLD_HEIGHT` /// instead of `WORLD_LOWEST_Y..WORLD_MAX_Y` - pub fn get_absolute(&self) -> u16 { + pub fn get_absolute(self) -> u16 { (self.height + WORLD_LOWEST_Y.abs()) as u16 } } +impl From for Height { + fn from(height: T) -> Self { + let height = height.to_i16().unwrap(); + + assert!(height <= WORLD_MAX_Y); + assert!(height >= WORLD_LOWEST_Y); + Self { height } + } +} + impl Deref for Height { type Target = i16; @@ -39,25 +46,14 @@ pub struct ChunkRelativeScalar { scalar: u8, } -macro_rules! derive_chunk_relative_scalar_from_int_impl { - ($integer:ty) => { - impl From<$integer> for ChunkRelativeScalar { - fn from(scalar: $integer) -> Self { - assert!(scalar < 16); - Self { - scalar: scalar as u8, - } - } - } - }; -} +impl From for ChunkRelativeScalar { + fn from(scalar: T) -> Self { + let scalar = scalar.to_u8().unwrap(); -derive_chunk_relative_scalar_from_int_impl! {u8} -derive_chunk_relative_scalar_from_int_impl! {u16} -derive_chunk_relative_scalar_from_int_impl! {u32} -derive_chunk_relative_scalar_from_int_impl! {u64} -derive_chunk_relative_scalar_from_int_impl! {u128} -derive_chunk_relative_scalar_from_int_impl! {usize} + assert!(scalar < 16); + Self { scalar } + } +} impl Deref for ChunkRelativeScalar { type Target = u8; @@ -81,6 +77,16 @@ pub struct XZBlockCoordinates { pub z: i32, } +impl XZBlockCoordinates { + pub fn with_y(self, height: Height) -> BlockCoordinates { + BlockCoordinates { + x: self.x, + y: height, + z: self.z, + } + } +} + /// Coordinates of a block relative to a chunk #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ChunkRelativeBlockCoordinates { @@ -90,7 +96,7 @@ pub struct ChunkRelativeBlockCoordinates { } impl ChunkRelativeBlockCoordinates { - pub fn with_chunk_coordinates(&self, chunk_coordinates: ChunkCoordinates) -> BlockCoordinates { + pub fn with_chunk_coordinates(self, chunk_coordinates: ChunkCoordinates) -> BlockCoordinates { BlockCoordinates { x: *self.x as i32 + chunk_coordinates.x * 16, y: self.y, @@ -115,6 +121,14 @@ impl ChunkRelativeXZBlockCoordinates { z: *self.z as i32 + chunk_coordinates.z * 16, } } + + pub fn with_y(self, height: Height) -> ChunkRelativeBlockCoordinates { + ChunkRelativeBlockCoordinates { + x: self.x, + y: height, + z: self.z, + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -122,12 +136,3 @@ pub struct ChunkCoordinates { pub x: i32, pub z: i32, } - -macro_rules! impl_get_absolute_height { - ($struct_name:ident) => { - impl $struct_name {} - }; -} - -impl_get_absolute_height! {BlockCoordinates} -impl_get_absolute_height! {ChunkRelativeBlockCoordinates}