aboutsummaryrefslogtreecommitdiff
path: root/azalea-core/src/position.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-06-25 05:09:26 +0000
committerGitHub <noreply@github.com>2022-06-25 05:09:26 +0000
commit7d3e57763e32ac9cf94180b1c714704cfbc3034d (patch)
tree2dcfe72bf09a42f6614f9dc988dc0254162ea0bf /azalea-core/src/position.rs
parent69c47eda4c496b13dadd80976bffd2fab7ea5894 (diff)
parentca7067e173129f3044ebc8c77634f06da29a086e (diff)
downloadazalea-drasl-7d3e57763e32ac9cf94180b1c714704cfbc3034d.tar.xz
Merge pull request #10 from mat-1/azalea-entity
azalea-entity
Diffstat (limited to 'azalea-core/src/position.rs')
-rw-r--r--azalea-core/src/position.rs258
1 files changed, 199 insertions, 59 deletions
diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs
index 24be5f6a..de8e2516 100644
--- a/azalea-core/src/position.rs
+++ b/azalea-core/src/position.rs
@@ -1,8 +1,17 @@
-use std::ops::Rem;
+use crate::ResourceLocation;
+use azalea_buf::{McBufReadable, McBufWritable};
+use std::{
+ io::{Read, Write},
+ ops::Rem,
+};
-use crate::resource_location::ResourceLocation;
+pub trait PositionXYZ<T> {
+ fn add_x(&self, n: T) -> Self;
+ fn add_y(&self, n: T) -> Self;
+ fn add_z(&self, n: T) -> Self;
+}
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct BlockPos {
pub x: i32,
pub y: i32,
@@ -27,7 +36,31 @@ impl Rem<i32> for BlockPos {
}
}
-#[derive(Clone, Copy, Debug, Default, PartialEq)]
+impl PositionXYZ<i32> for BlockPos {
+ fn add_x(&self, n: i32) -> Self {
+ BlockPos {
+ x: self.x + n,
+ y: self.y,
+ z: self.z,
+ }
+ }
+ fn add_y(&self, n: i32) -> Self {
+ BlockPos {
+ x: self.x,
+ y: self.y + n,
+ z: self.z,
+ }
+ }
+ fn add_z(&self, n: i32) -> Self {
+ BlockPos {
+ x: self.x,
+ y: self.y,
+ z: self.z + n,
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct ChunkPos {
pub x: i32,
pub z: i32,
@@ -39,15 +72,6 @@ impl ChunkPos {
}
}
-impl From<&BlockPos> for ChunkPos {
- fn from(pos: &BlockPos) -> Self {
- ChunkPos {
- x: pos.x.div_floor(16),
- z: pos.z.div_floor(16),
- }
- }
-}
-
/// The coordinates of a chunk section in the world.
#[derive(Clone, Copy, Debug, Default)]
pub struct ChunkSectionPos {
@@ -61,23 +85,6 @@ impl ChunkSectionPos {
ChunkSectionPos { x, y, z }
}
}
-
-impl From<BlockPos> for ChunkSectionPos {
- fn from(pos: BlockPos) -> Self {
- ChunkSectionPos {
- x: pos.x.div_floor(16),
- y: pos.y.div_floor(16),
- z: pos.z.div_floor(16),
- }
- }
-}
-
-impl From<ChunkSectionPos> for ChunkPos {
- fn from(pos: ChunkSectionPos) -> Self {
- ChunkPos { x: pos.x, z: pos.z }
- }
-}
-
/// The coordinates of a block inside a chunk.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct ChunkBlockPos {
@@ -91,17 +98,6 @@ impl ChunkBlockPos {
ChunkBlockPos { x, y, z }
}
}
-
-impl From<&BlockPos> for ChunkBlockPos {
- fn from(pos: &BlockPos) -> Self {
- ChunkBlockPos {
- x: pos.x.rem_euclid(16).abs() as u8,
- y: pos.y,
- z: pos.z.rem_euclid(16).abs() as u8,
- }
- }
-}
-
/// The coordinates of a block inside a chunk section.
#[derive(Clone, Copy, Debug, Default)]
pub struct ChunkSectionBlockPos {
@@ -119,6 +115,80 @@ impl ChunkSectionBlockPos {
}
}
+/// A block pos with an attached dimension
+#[derive(Debug, Clone)]
+pub struct GlobalPos {
+ pub pos: BlockPos,
+ // this is actually a ResourceKey in Minecraft, but i don't think it matters?
+ pub dimension: ResourceLocation,
+}
+
+#[derive(Debug, Clone, Copy, Default)]
+pub struct EntityPos {
+ pub x: f64,
+ pub y: f64,
+ pub z: f64,
+}
+
+impl PositionXYZ<f64> for EntityPos {
+ fn add_x(&self, n: f64) -> Self {
+ EntityPos {
+ x: self.x + n,
+ y: self.y,
+ z: self.z,
+ }
+ }
+ fn add_y(&self, n: f64) -> Self {
+ EntityPos {
+ x: self.x,
+ y: self.y + n,
+ z: self.z,
+ }
+ }
+ fn add_z(&self, n: f64) -> Self {
+ EntityPos {
+ x: self.x,
+ y: self.y,
+ z: self.z + n,
+ }
+ }
+}
+
+impl From<&BlockPos> for ChunkPos {
+ fn from(pos: &BlockPos) -> Self {
+ ChunkPos {
+ x: pos.x.div_floor(16),
+ z: pos.z.div_floor(16),
+ }
+ }
+}
+
+impl From<BlockPos> for ChunkSectionPos {
+ fn from(pos: BlockPos) -> Self {
+ ChunkSectionPos {
+ x: pos.x.div_floor(16),
+ y: pos.y.div_floor(16),
+ z: pos.z.div_floor(16),
+ }
+ }
+}
+
+impl From<ChunkSectionPos> for ChunkPos {
+ fn from(pos: ChunkSectionPos) -> Self {
+ ChunkPos { x: pos.x, z: pos.z }
+ }
+}
+
+impl From<&BlockPos> for ChunkBlockPos {
+ fn from(pos: &BlockPos) -> Self {
+ ChunkBlockPos {
+ x: pos.x.rem_euclid(16).abs() as u8,
+ y: pos.y,
+ z: pos.z.rem_euclid(16).abs() as u8,
+ }
+ }
+}
+
impl From<&BlockPos> for ChunkSectionBlockPos {
fn from(pos: &BlockPos) -> Self {
ChunkSectionBlockPos {
@@ -138,29 +208,77 @@ impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
}
}
}
+impl From<&EntityPos> for BlockPos {
+ fn from(pos: &EntityPos) -> Self {
+ BlockPos {
+ x: pos.x.floor() as i32,
+ y: pos.y.floor() as i32,
+ z: pos.z.floor() as i32,
+ }
+ }
+}
-/// A block pos with an attached dimension
-#[derive(Debug, Clone)]
-pub struct GlobalPos {
- pub pos: BlockPos,
- // this is actually a ResourceKey in Minecraft, but i don't think it matters?
- pub dimension: ResourceLocation,
+impl From<&EntityPos> for ChunkPos {
+ fn from(pos: &EntityPos) -> Self {
+ ChunkPos::from(&BlockPos::from(pos))
+ }
}
-#[derive(Debug, Clone, Default)]
-pub struct EntityPos {
- pub x: f64,
- pub y: f64,
- pub z: f64,
+impl McBufReadable for BlockPos {
+ fn read_into(buf: &mut impl Read) -> Result<Self, String> {
+ let val = u64::read_into(buf)?;
+ let x = (val >> 38) as i32;
+ let y = (val & 0xFFF) as i32;
+ let z = ((val >> 12) & 0x3FFFFFF) as i32;
+ Ok(BlockPos { x, y, z })
+ }
}
-impl From<&EntityPos> for BlockPos {
- fn from(pos: &EntityPos) -> Self {
- BlockPos {
- x: pos.x as i32,
- y: pos.y as i32,
- z: pos.z as i32,
- }
+impl McBufReadable for GlobalPos {
+ fn read_into(buf: &mut impl Read) -> Result<Self, String> {
+ Ok(GlobalPos {
+ dimension: ResourceLocation::read_into(buf)?,
+ pos: BlockPos::read_into(buf)?,
+ })
+ }
+}
+
+impl McBufReadable for ChunkSectionPos {
+ fn read_into(buf: &mut impl Read) -> Result<Self, String> {
+ let long = i64::read_into(buf)?;
+ Ok(ChunkSectionPos {
+ x: (long >> 42) as i32,
+ y: (long << 44 >> 44) as i32,
+ z: (long << 22 >> 42) as i32,
+ })
+ }
+}
+
+impl McBufWritable for BlockPos {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ let data = (((self.x & 0x3FFFFFF) as i64) << 38)
+ | (((self.z & 0x3FFFFFF) as i64) << 12)
+ | ((self.y & 0xFFF) as i64);
+ data.write_into(buf)
+ }
+}
+
+impl McBufWritable for GlobalPos {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ ResourceLocation::write_into(&self.dimension, buf)?;
+ BlockPos::write_into(&self.pos, buf)?;
+
+ Ok(())
+ }
+}
+
+impl McBufWritable for ChunkSectionPos {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ let long = (((self.x & 0x3FFFFF) as i64) << 42)
+ | (self.y & 0xFFFFF) as i64
+ | (((self.z & 0x3FFFFF) as i64) << 20);
+ long.write_into(buf)?;
+ Ok(())
}
}
@@ -181,4 +299,26 @@ mod tests {
let chunk_block_pos = ChunkBlockPos::from(&block_pos);
assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
}
+
+ #[test]
+ fn test_from_entity_pos_to_block_pos() {
+ let entity_pos = EntityPos {
+ x: 31.5,
+ y: 80.0,
+ z: -16.1,
+ };
+ let block_pos = BlockPos::from(&entity_pos);
+ assert_eq!(block_pos, BlockPos::new(31, 80, -17));
+ }
+
+ #[test]
+ fn test_from_entity_pos_to_chunk_pos() {
+ let entity_pos = EntityPos {
+ x: 31.5,
+ y: 80.0,
+ z: -16.1,
+ };
+ let chunk_pos = ChunkPos::from(&entity_pos);
+ assert_eq!(chunk_pos, ChunkPos::new(1, -2));
+ }
}