aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/pathfinder/positions.rs
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2026-01-17 11:58:37 -1030
committermat <git@matdoes.dev>2026-01-17 11:58:37 -1030
commit74ef7d19b2bc4453f5368cc39c838582f2f3bafd (patch)
treecd133a77934f461b52db614eb10a99eb620f53e6 /azalea/src/pathfinder/positions.rs
parenta49c8d0b53fed223bab127704c604291ee77f921 (diff)
downloadazalea-drasl-74ef7d19b2bc4453f5368cc39c838582f2f3bafd.tar.xz
use more compact chunk section positions in pathfinder
Diffstat (limited to 'azalea/src/pathfinder/positions.rs')
-rw-r--r--azalea/src/pathfinder/positions.rs170
1 files changed, 170 insertions, 0 deletions
diff --git a/azalea/src/pathfinder/positions.rs b/azalea/src/pathfinder/positions.rs
new file mode 100644
index 00000000..ca2768b2
--- /dev/null
+++ b/azalea/src/pathfinder/positions.rs
@@ -0,0 +1,170 @@
+use std::{
+ cmp,
+ hash::{Hash, Hasher},
+ mem::{self, transmute},
+ ops::{Add, Mul},
+};
+
+use azalea_core::position::BlockPos;
+
+/// An offset from a block position.
+///
+/// This fits in 64 bits, so it's more efficient than a BlockPos in some cases.
+///
+/// The X and Z are limited to ±32k.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[repr(C)]
+pub struct RelBlockPos {
+ /// The actual non-relative Y coordinate of the block.
+ pub y: i32,
+ /// The X coordinate of the block, relative to some origin.
+ pub x: i16,
+ /// The Y coordinate of the block, relative to some origin.
+ 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)
+ }
+
+ /// Create a new [`RelBlockPos`] from a given origin and new position.
+ #[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 {
+ // SAFETY: RelBlockPos can be represented as a 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);
+ }
+}
+
+/// Similar to [`ChunkSectionPos`] but fits in 64 bits.
+///
+/// [`ChunkSectionPos`]: azalea_core::position::ChunkSectionPos
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[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> {
+ self.as_u64().partial_cmp(&other.as_u64())
+ }
+}
+impl Ord for SmallChunkSectionPos {
+ fn cmp(&self, other: &Self) -> cmp::Ordering {
+ self.as_u64().cmp(&other.as_u64())
+ }
+}