From d6491ac08b089ab45384d20c1101f069d6f35514 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 26 Jun 2022 23:15:31 -0500 Subject: [PATCH] more physics stuff --- Cargo.lock | 1 + azalea-block/src/lib.rs | 2 +- azalea-core/src/cursor3d.rs | 15 ++-- azalea-core/src/position.rs | 3 + azalea-entity/src/lib.rs | 1 - azalea-physics/Cargo.toml | 1 + azalea-physics/README.md | 3 + azalea-physics/src/aabb.rs | 6 +- azalea-physics/src/dimension_collisions.rs | 100 +++++++++++++++++++-- azalea-physics/src/lib.rs | 18 +++- 10 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 azalea-physics/README.md diff --git a/Cargo.lock b/Cargo.lock index 5f817777..68a5889d 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,6 +183,7 @@ dependencies = [ name = "azalea-physics" version = "0.1.0" dependencies = [ + "azalea-block", "azalea-core", "azalea-entity", "azalea-world", diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index f07b1bce..3eb86a90 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -8,7 +8,7 @@ use std::mem; impl BlockState { /// Transmutes a u32 to a block state. - /// + /// /// # Safety /// The `state_id` should be a valid block state. #[inline] diff --git a/azalea-core/src/cursor3d.rs b/azalea-core/src/cursor3d.rs index 9083e7a7..180301e3 100644 --- a/azalea-core/src/cursor3d.rs +++ b/azalea-core/src/cursor3d.rs @@ -1,3 +1,5 @@ +use crate::BlockPos; + pub struct Cursor3d { index: usize, @@ -37,15 +39,18 @@ impl Iterator for Cursor3d { } Some(CursorIteration { - x: self.origin_x + x as i32, - y: self.origin_y + y as i32, - z: self.origin_z + z as i32, + pos: BlockPos { + x: self.origin_x + x as i32, + y: self.origin_y + y as i32, + z: self.origin_z + z as i32, + }, iteration_type: iteration_type.into(), }) } } #[repr(u8)] +#[derive(Eq, PartialEq, Debug)] pub enum CursorIterationType { Inside = 0, Face = 1, @@ -54,9 +59,7 @@ pub enum CursorIterationType { } pub struct CursorIteration { - pub x: i32, - pub y: i32, - pub z: i32, + pub pos: BlockPos, pub iteration_type: CursorIterationType, } diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 879955a2..b222e509 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -134,6 +134,9 @@ impl ChunkSectionPos { pub fn new(x: i32, y: i32, z: i32) -> Self { ChunkSectionPos { x, y, z } } + pub fn block_to_section_coord(block: i32) -> i32 { + block >> 4 + } } /// The coordinates of a block inside a chunk. #[derive(Clone, Copy, Debug, Default, PartialEq)] diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 62860752..1fab90bf 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -1,5 +1,4 @@ mod data; -mod physics; use azalea_core::{PositionDelta, Vec3}; pub use data::*; diff --git a/azalea-physics/Cargo.toml b/azalea-physics/Cargo.toml index 910167d4..493e7336 100644 --- a/azalea-physics/Cargo.toml +++ b/azalea-physics/Cargo.toml @@ -6,6 +6,7 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +azalea-block = {path = "../azalea-block"} azalea-core = {path = "../azalea-core"} azalea-entity = {path = "../azalea-entity"} azalea-world = {path = "../azalea-world"} diff --git a/azalea-physics/README.md b/azalea-physics/README.md new file mode 100644 index 00000000..21ee18ba --- /dev/null +++ b/azalea-physics/README.md @@ -0,0 +1,3 @@ +# Azalea Physics + +Physics for Minecraft entities. diff --git a/azalea-physics/src/aabb.rs b/azalea-physics/src/aabb.rs index 741daa05..020221dc 100644 --- a/azalea-physics/src/aabb.rs +++ b/azalea-physics/src/aabb.rs @@ -15,7 +15,7 @@ pub struct AABB { } impl AABB { - pub fn contract(&mut self, x: f64, y: f64, z: f64) -> AABB { + pub fn contract(&self, x: f64, y: f64, z: f64) -> AABB { let mut min_x = self.min_x; let mut min_y = self.min_y; let mut min_z = self.min_z; @@ -53,7 +53,7 @@ impl AABB { } } - pub fn expand_towards(&mut self, other: &Vec3) -> AABB { + pub fn expand_towards(&self, other: &Vec3) -> AABB { let mut min_x = self.min_x; let mut min_y = self.min_y; let mut min_z = self.min_z; @@ -91,7 +91,7 @@ impl AABB { } } - pub fn inflate(&mut self, x: f64, y: f64, z: f64) -> AABB { + pub fn inflate(&self, x: f64, y: f64, z: f64) -> AABB { let min_x = self.min_x - x; let min_y = self.min_y - y; let min_z = self.min_z - z; diff --git a/azalea-physics/src/dimension_collisions.rs b/azalea-physics/src/dimension_collisions.rs index bbac09de..3ed4e924 100644 --- a/azalea-physics/src/dimension_collisions.rs +++ b/azalea-physics/src/dimension_collisions.rs @@ -1,9 +1,11 @@ +use crate::{aabb::EPSILON, AABB}; +use azalea_block::{Block, BlockState}; +use azalea_core::{ChunkPos, ChunkSectionPos, Cursor3d, CursorIterationType}; use azalea_entity::Entity; -use azalea_world::Dimension; +use azalea_world::{Chunk, Dimension}; +use std::sync::{Arc, Mutex}; -use crate::AABB; - -trait CollisionGetter { +pub trait CollisionGetter { fn get_block_collisions<'a>( &'a self, entity: Option<&Entity>, @@ -25,23 +27,103 @@ pub struct BlockCollisions<'a> { dimension: &'a Dimension, // context: CollisionContext, aabb: AABB, + + cursor: Cursor3d, + only_suffocating_blocks: bool, } impl<'a> BlockCollisions<'a> { pub fn new(dimension: &'a Dimension, entity: Option<&Entity>, aabb: AABB) -> Self { - Self { dimension, aabb } + let origin_x = (aabb.min_x - EPSILON) as i32 - 1; + let origin_y = (aabb.max_x + EPSILON) as i32 + 1; + let origin_z = (aabb.min_y - EPSILON) as i32 - 1; + + let end_x = (aabb.max_y + EPSILON) as i32 + 1; + let end_y = (aabb.min_z - EPSILON) as i32 - 1; + let end_z = (aabb.max_z + EPSILON) as i32 + 1; + + let cursor = Cursor3d::new(origin_x, origin_y, origin_z, end_x, end_y, end_z); + + Self { + dimension, + aabb, + cursor, + only_suffocating_blocks: false, + } + } + + fn get_chunk(&self, block_x: i32, block_z: i32) -> Option<&Arc>> { + let chunk_x = ChunkSectionPos::block_to_section_coord(block_x); + let chunk_z = ChunkSectionPos::block_to_section_coord(block_z); + let chunk_pos = ChunkPos::new(chunk_x, chunk_z); + + // TODO: minecraft caches chunk here + // int chunkX = SectionPos.blockToSectionCoord(blockX); + // int chunkZ = SectionPos.blockToSectionCoord(blockZ); + // long chunkPosLong = ChunkPos.asLong(chunkX, chunkZ); + // if (this.cachedBlockGetter != null && this.cachedBlockGetterPos == var5) { + // return this.cachedBlockGetter; + // } else { + // BlockGetter var7 = this.collisionGetter.getChunkForCollisions(chunkX, chunkZ); + // this.cachedBlockGetter = var7; + // this.cachedBlockGetterPos = chunkPosLong; + // return var7; + // } + + let chunk = self.dimension[&chunk_pos].as_ref(); + return chunk; } } -impl Iterator for BlockCollisions<'a> { +impl<'a> Iterator for BlockCollisions<'a> { type Item = VoxelShape; fn next(&mut self) -> Option { - loop { - if !self.cursor.advance() { - return None; + while let Some(item) = self.cursor.next() { + if item.iteration_type == CursorIterationType::Corner { + continue; } + + let chunk = self.get_chunk(item.pos.x, item.pos.z); + let chunk = match chunk { + Some(chunk) => chunk, + None => continue, + }; + let chunk_lock = chunk.lock().unwrap(); + + let pos = item.pos; + let block_state: BlockState = chunk_lock.get(&(&pos).into(), self.dimension.min_y()); + let block: &dyn Block = &block_state.into(); + + // TODO: continue if self.only_suffocating_blocks and the block is not suffocating + + let block_shape = VoxelShape {}; + // let block_shape = block.get_collision_shape(); + // if block_shape == Shapes::block() { + if true { + if !self.aabb.intersects_aabb(&AABB { + min_x: item.pos.x as f64, + min_y: item.pos.y as f64, + min_z: item.pos.z as f64, + max_x: (item.pos.x + 1) as f64, + max_y: (item.pos.y + 1) as f64, + max_z: (item.pos.z + 1) as f64, + }) { + continue; + } + + return block_shape.move_relative(item.pos.x, item.pos.y, item.pos.z); + } + + // let block_shape = block_shape.move_relative(item.pos.x, item.pos.y, item.pos.z); + // if (!Shapes.joinIsNotEmpty(block_shape, this.entityShape, BooleanOp.AND)) { + // continue; + // } + + // return block_shape; } + + None } } diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 1f50473c..678db7d6 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -7,6 +7,7 @@ use azalea_core::{PositionDelta, PositionXYZ, Vec3}; use azalea_entity::Entity; use azalea_world::Dimension; pub use block_hit_result::BlockHitResult; +use dimension_collisions::CollisionGetter; pub enum MoverType { Own, @@ -25,6 +26,11 @@ trait HasPhysics { dimension: &Dimension, // entity_collisions: Vec ) -> Vec3; + fn collide_with_shapes( + movement: &Vec3, + entity_box: &AABB, + // collision_boxes: Vec, + ) -> Vec3; } impl HasPhysics for Entity { @@ -80,6 +86,16 @@ impl HasPhysics for Entity { let block_collisions = dimension.get_block_collisions(entity, entity_bounding_box.expand_towards(movement)); collision_boxes.extend(block_collisions); - Self::collide_with_shapes(movement, &entity_bounding_box, &collision_boxes) + // Self::collide_with_shapes(movement, &entity_bounding_box, &collision_boxes) + Self::collide_with_shapes(movement, &entity_bounding_box) + } + + fn collide_with_shapes( + movement: &Vec3, + entity_box: &AABB, + // collision_boxes: Vec, + ) -> Vec3 { + // TODO + *movement } }