use std::{
cmp,
hash::{Hash, Hasher},
mem::{self, transmute},
ops::{Add, Mul},
};
use azalea_core::position::BlockPos;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct RelBlockPos {
pub y: i32,
pub x: i16,
pub z: i16,
}
impl RelBlockPos {
pub fn get_origin(origin: BlockPos) -> Self {
Self::new(0, origin.y, 0)
}
#[inline]
pub const fn new(x: i16, y: i32, z: i16) -> Self {
Self { x, y, z }
}
#[inline]
pub fn apply(self, origin: BlockPos) -> BlockPos {
BlockPos::new(origin.x + self.x as i32, self.y, origin.z + self.z as i32)
}
#[inline]
pub fn from_origin(origin: BlockPos, new: BlockPos) -> Self {
Self {
x: (new.x - origin.x) as i16,
y: new.y,
z: (new.z - origin.z) as i16,
}
}
#[inline]
pub fn up(&self, y: i32) -> Self {
Self {
x: self.x,
y: self.y + y,
z: self.z,
}
}
#[inline]
pub fn down(&self, y: i32) -> Self {
Self {
x: self.x,
y: self.y - y,
z: self.z,
}
}
#[inline]
pub fn north(&self, z: i16) -> Self {
Self {
x: self.x,
y: self.y,
z: self.z - z,
}
}
#[inline]
pub fn south(&self, z: i16) -> Self {
Self {
x: self.x,
y: self.y,
z: self.z + z,
}
}
#[inline]
pub fn east(&self, x: i16) -> Self {
Self {
x: self.x + x,
y: self.y,
z: self.z,
}
}
#[inline]
pub fn west(&self, x: i16) -> Self {
Self {
x: self.x - x,
y: self.y,
z: self.z,
}
}
#[inline]
pub fn as_u64(self) -> u64 {
unsafe { transmute::<Self, u64>(self) }
}
}
impl Add<RelBlockPos> for RelBlockPos {
type Output = RelBlockPos;
fn add(self, rhs: RelBlockPos) -> Self::Output {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl Mul<i16> for RelBlockPos {
type Output = RelBlockPos;
fn mul(self, rhs: i16) -> Self::Output {
Self {
x: self.x * rhs,
y: self.y * rhs as i32,
z: self.z * rhs,
}
}
}
impl Hash for RelBlockPos {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_u64().hash(state);
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(C)]
pub struct SmallChunkSectionPos {
pub y: i32,
pub x: i16,
pub z: i16,
}
impl SmallChunkSectionPos {
pub fn as_u64(self) -> u64 {
unsafe { mem::transmute::<_, u64>(self) }
}
}
impl From<BlockPos> for SmallChunkSectionPos {
#[inline]
fn from(pos: BlockPos) -> Self {
Self {
x: (pos.x >> 4) as i16,
y: pos.y >> 4,
z: (pos.z >> 4) as i16,
}
}
}
impl PartialOrd for SmallChunkSectionPos {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for SmallChunkSectionPos {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_u64().cmp(&other.as_u64())
}
}