From 0d004b72ac22641978c6ef93ca8641eb621e2f48 Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Tue, 15 Nov 2022 14:52:26 -0600 Subject: Rename "dimension" to "world" (#39) * rename "dimension" to "world" * Update mod.rs --- .../src/collision/dimension_collisions.rs | 139 --------------------- azalea-physics/src/collision/mod.rs | 22 ++-- azalea-physics/src/collision/world_collisions.rs | 139 +++++++++++++++++++++ azalea-physics/src/lib.rs | 70 ++++++----- 4 files changed, 187 insertions(+), 183 deletions(-) delete mode 100755 azalea-physics/src/collision/dimension_collisions.rs create mode 100644 azalea-physics/src/collision/world_collisions.rs (limited to 'azalea-physics/src') diff --git a/azalea-physics/src/collision/dimension_collisions.rs b/azalea-physics/src/collision/dimension_collisions.rs deleted file mode 100755 index fd4e5141..00000000 --- a/azalea-physics/src/collision/dimension_collisions.rs +++ /dev/null @@ -1,139 +0,0 @@ -use crate::collision::{BlockWithShape, VoxelShape, AABB}; -use azalea_block::BlockState; -use azalea_core::{ChunkPos, ChunkSectionPos, Cursor3d, CursorIterationType, EPSILON}; -use azalea_world::entity::EntityData; -use azalea_world::{Chunk, Dimension}; -use parking_lot::Mutex; -use std::sync::Arc; - -use super::Shapes; - -pub trait CollisionGetter { - fn get_block_collisions<'a>( - &'a self, - entity: Option<&EntityData>, - aabb: AABB, - ) -> BlockCollisions<'a>; -} - -impl CollisionGetter for Dimension { - fn get_block_collisions<'a>( - &'a self, - entity: Option<&EntityData>, - aabb: AABB, - ) -> BlockCollisions<'a> { - BlockCollisions::new(self, entity, aabb) - } -} - -pub struct BlockCollisions<'a> { - pub dimension: &'a Dimension, - // context: CollisionContext, - pub aabb: AABB, - pub entity_shape: VoxelShape, - pub cursor: Cursor3d, - pub only_suffocating_blocks: bool, -} - -impl<'a> BlockCollisions<'a> { - // TODO: the entity is stored in the context - pub fn new(dimension: &'a Dimension, _entity: Option<&EntityData>, aabb: AABB) -> Self { - let origin_x = (aabb.min_x - EPSILON) as i32 - 1; - let origin_y = (aabb.min_y - EPSILON) as i32 - 1; - let origin_z = (aabb.min_z - EPSILON) as i32 - 1; - - let end_x = (aabb.max_x + EPSILON) as i32 + 1; - let end_y = (aabb.max_y + 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, - entity_shape: VoxelShape::from(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; - // } - - self.dimension[&chunk_pos].as_ref() - } -} - -impl<'a> Iterator for BlockCollisions<'a> { - type Item = VoxelShape; - - fn next(&mut self) -> Option { - 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 pos = item.pos; - let block_state: BlockState = chunk - .lock() - .get(&(&pos).into(), self.dimension.min_y()) - .unwrap_or(BlockState::Air); - - // TODO: continue if self.only_suffocating_blocks and the block is not suffocating - - let block_shape = block_state.shape(); - - // if it's a full block do a faster collision check - if block_shape == &crate::collision::block_shape() { - 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 Some(block_shape.move_relative( - item.pos.x as f64, - item.pos.y as f64, - item.pos.z as f64, - )); - } - - let block_shape = - block_shape.move_relative(item.pos.x as f64, item.pos.y as f64, item.pos.z as f64); - // if the entity shape and block shape don't collide, continue - if !Shapes::matches_anywhere(&block_shape, &self.entity_shape, |a, b| a && b) { - continue; - } - - return Some(block_shape); - } - - None - } -} diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index d5502f3d..aa585aa8 100755 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -1,18 +1,18 @@ mod blocks; -mod dimension_collisions; mod discrete_voxel_shape; mod mergers; mod shape; +mod world_collisions; use std::ops::DerefMut; use azalea_core::{Axis, Vec3, AABB, EPSILON}; use azalea_world::entity::{Entity, EntityData}; -use azalea_world::{Dimension, MoveEntityError}; +use azalea_world::{MoveEntityError, World}; pub use blocks::BlockWithShape; -use dimension_collisions::CollisionGetter; pub use discrete_voxel_shape::*; pub use shape::*; +use world_collisions::CollisionGetter; pub enum MoverType { Own, @@ -34,7 +34,7 @@ pub trait MovableEntity { ) -> Result<(), MoveEntityError>; } -impl HasCollision for Dimension { +impl HasCollision for World { // private Vec3 collide(Vec3 var1) { // AABB var2 = this.getBoundingBox(); // List var3 = this.level.getEntityCollisions(this, var2.expandTowards(var1)); @@ -63,7 +63,7 @@ impl HasCollision for Dimension { fn collide(&self, movement: &Vec3, entity: &EntityData) -> Vec3 { let entity_bounding_box = entity.bounding_box; // TODO: get_entity_collisions - // let entity_collisions = dimension.get_entity_collisions(self, entity_bounding_box.expand_towards(movement)); + // let entity_collisions = world.get_entity_collisions(self, entity_bounding_box.expand_towards(movement)); let entity_collisions = Vec::new(); if movement.length_sqr() == 0.0 { *movement @@ -83,7 +83,7 @@ impl HasCollision for Dimension { } } -impl> MovableEntity for Entity<'_, D> { +impl> MovableEntity for Entity<'_, D> { /// Move an entity by a given delta, checking for collisions. fn move_colliding( &mut self, @@ -111,7 +111,7 @@ impl> MovableEntity for Entity<'_, D> { // movement = this.maybeBackOffFromEdge(movement, moverType); - let collide_result = { self.dimension.collide(movement, self) }; + let collide_result = { self.world.collide(movement, self) }; let move_distance = collide_result.length_sqr(); @@ -127,7 +127,7 @@ impl> MovableEntity for Entity<'_, D> { } }; - self.dimension.set_entity_pos(self.id, new_pos)?; + self.world.set_entity_pos(self.id, new_pos)?; } let x_collision = movement.x != collide_result.x; @@ -141,7 +141,7 @@ impl> MovableEntity for Entity<'_, D> { let _block_pos_below = self.on_pos_legacy(); // let _block_state_below = self - // .dimension + // .world // .get_block_state(&block_pos_below) // .expect("Couldn't get block state below"); @@ -198,7 +198,7 @@ fn collide_bounding_box( entity: Option<&EntityData>, movement: &Vec3, entity_bounding_box: &AABB, - dimension: &Dimension, + world: &World, entity_collisions: Vec, ) -> Vec3 { let mut collision_boxes: Vec = Vec::with_capacity(entity_collisions.len() + 1); @@ -210,7 +210,7 @@ fn collide_bounding_box( // TODO: world border let block_collisions = - dimension.get_block_collisions(entity, entity_bounding_box.expand_towards(movement)); + world.get_block_collisions(entity, entity_bounding_box.expand_towards(movement)); let block_collisions = block_collisions.collect::>(); collision_boxes.extend(block_collisions); collide_with_shapes(movement, *entity_bounding_box, &collision_boxes) diff --git a/azalea-physics/src/collision/world_collisions.rs b/azalea-physics/src/collision/world_collisions.rs new file mode 100644 index 00000000..65f7f5bb --- /dev/null +++ b/azalea-physics/src/collision/world_collisions.rs @@ -0,0 +1,139 @@ +use crate::collision::{BlockWithShape, VoxelShape, AABB}; +use azalea_block::BlockState; +use azalea_core::{ChunkPos, ChunkSectionPos, Cursor3d, CursorIterationType, EPSILON}; +use azalea_world::entity::EntityData; +use azalea_world::{Chunk, World}; +use parking_lot::Mutex; +use std::sync::Arc; + +use super::Shapes; + +pub trait CollisionGetter { + fn get_block_collisions<'a>( + &'a self, + entity: Option<&EntityData>, + aabb: AABB, + ) -> BlockCollisions<'a>; +} + +impl CollisionGetter for World { + fn get_block_collisions<'a>( + &'a self, + entity: Option<&EntityData>, + aabb: AABB, + ) -> BlockCollisions<'a> { + BlockCollisions::new(self, entity, aabb) + } +} + +pub struct BlockCollisions<'a> { + pub world: &'a World, + // context: CollisionContext, + pub aabb: AABB, + pub entity_shape: VoxelShape, + pub cursor: Cursor3d, + pub only_suffocating_blocks: bool, +} + +impl<'a> BlockCollisions<'a> { + // TODO: the entity is stored in the context + pub fn new(world: &'a World, _entity: Option<&EntityData>, aabb: AABB) -> Self { + let origin_x = (aabb.min_x - EPSILON) as i32 - 1; + let origin_y = (aabb.min_y - EPSILON) as i32 - 1; + let origin_z = (aabb.min_z - EPSILON) as i32 - 1; + + let end_x = (aabb.max_x + EPSILON) as i32 + 1; + let end_y = (aabb.max_y + 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 { + world, + aabb, + entity_shape: VoxelShape::from(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; + // } + + self.world[&chunk_pos].as_ref() + } +} + +impl<'a> Iterator for BlockCollisions<'a> { + type Item = VoxelShape; + + fn next(&mut self) -> Option { + 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 pos = item.pos; + let block_state: BlockState = chunk + .lock() + .get(&(&pos).into(), self.world.min_y()) + .unwrap_or(BlockState::Air); + + // TODO: continue if self.only_suffocating_blocks and the block is not suffocating + + let block_shape = block_state.shape(); + + // if it's a full block do a faster collision check + if block_shape == &crate::collision::block_shape() { + 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 Some(block_shape.move_relative( + item.pos.x as f64, + item.pos.y as f64, + item.pos.z as f64, + )); + } + + let block_shape = + block_shape.move_relative(item.pos.x as f64, item.pos.y as f64, item.pos.z as f64); + // if the entity shape and block shape don't collide, continue + if !Shapes::matches_anywhere(&block_shape, &self.entity_shape, |a, b| a && b) { + continue; + } + + return Some(block_shape); + } + + None + } +} diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 852874b8..2295e6f2 100755 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -8,7 +8,7 @@ use azalea_block::{Block, BlockState}; use azalea_core::{BlockPos, Vec3}; use azalea_world::{ entity::{Entity, EntityData}, - Dimension, + World, }; use collision::{MovableEntity, MoverType}; @@ -19,7 +19,7 @@ pub trait HasPhysics { fn jump_from_ground(&mut self); } -impl> HasPhysics for Entity<'_, D> { +impl> HasPhysics for Entity<'_, D> { /// Move the entity with the given acceleration while handling friction, /// gravity, collisions, and some other stuff. fn travel(&mut self, acceleration: &Vec3) { @@ -40,7 +40,7 @@ impl> HasPhysics for Entity<'_, D> { let block_pos_below = get_block_pos_below_that_affects_movement(self); let block_state_below = self - .dimension + .world .get_block_state(&block_pos_below) .unwrap_or(BlockState::Air); let block_below: Box = block_state_below.into(); @@ -142,7 +142,7 @@ fn get_block_pos_below_that_affects_movement(entity: &EntityData) -> BlockPos { ) } -fn handle_relative_friction_and_calculate_movement>( +fn handle_relative_friction_and_calculate_movement>( entity: &mut Entity, acceleration: &Vec3, block_friction: f32, @@ -181,10 +181,10 @@ fn get_friction_influenced_speed(entity: &EntityData, friction: f32) -> f32 { /// Returns the what the entity's jump should be multiplied by based on the /// block they're standing on. -fn block_jump_factor>(entity: &Entity) -> f32 { - let block_at_pos = entity.dimension.get_block_state(&entity.pos().into()); +fn block_jump_factor>(entity: &Entity) -> f32 { + let block_at_pos = entity.world.get_block_state(&entity.pos().into()); let block_below = entity - .dimension + .world .get_block_state(&get_block_pos_below_that_affects_movement(entity)); let block_at_pos_jump_factor = if let Some(block) = block_at_pos { @@ -209,11 +209,11 @@ fn block_jump_factor>(entity: &Entity) -> f32 // public double getJumpBoostPower() { // return this.hasEffect(MobEffects.JUMP) ? (double)(0.1F * (float)(this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D; // } -fn jump_power>(entity: &Entity) -> f32 { +fn jump_power>(entity: &Entity) -> f32 { 0.42 * block_jump_factor(entity) } -fn jump_boost_power>(_entity: &Entity) -> f64 { +fn jump_boost_power>(_entity: &Entity) -> f64 { // TODO: potion effects // if let Some(effects) = entity.effects() { // if let Some(jump_effect) = effects.get(&Effect::Jump) { @@ -231,14 +231,14 @@ fn jump_boost_power>(_entity: &Entity) -> f64 mod tests { use super::*; use azalea_core::ChunkPos; - use azalea_world::{Chunk, Dimension}; + use azalea_world::{Chunk, World}; use uuid::Uuid; #[test] fn test_gravity() { - let mut dim = Dimension::default(); + let mut world = World::default(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -249,7 +249,7 @@ mod tests { }, ), ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // y should start at 70 assert_eq!(entity.pos().y, 70.); entity.ai_step(); @@ -266,10 +266,11 @@ mod tests { } #[test] fn test_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -280,12 +281,12 @@ mod tests { }, ), ); - let block_state = dim.set_block_state(&BlockPos { x: 0, y: 69, z: 0 }, BlockState::Stone); + let block_state = world.set_block_state(&BlockPos { x: 0, y: 69, z: 0 }, BlockState::Stone); assert!( block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); entity.ai_step(); // delta will change, but it won't move until next tick assert_eq!(entity.pos().y, 70.); @@ -297,10 +298,11 @@ mod tests { #[test] fn test_slab_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -311,7 +313,7 @@ mod tests { }, ), ); - let block_state = dim.set_block_state( + let block_state = world.set_block_state( &BlockPos { x: 0, y: 69, z: 0 }, BlockState::StoneSlab_BottomFalse, ); @@ -319,7 +321,7 @@ mod tests { block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // do a few steps so we fall on the slab for _ in 0..20 { entity.ai_step(); @@ -329,10 +331,11 @@ mod tests { #[test] fn test_top_slab_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -343,7 +346,7 @@ mod tests { }, ), ); - let block_state = dim.set_block_state( + let block_state = world.set_block_state( &BlockPos { x: 0, y: 69, z: 0 }, BlockState::StoneSlab_TopFalse, ); @@ -351,7 +354,7 @@ mod tests { block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // do a few steps so we fall on the slab for _ in 0..20 { entity.ai_step(); @@ -361,10 +364,11 @@ mod tests { #[test] fn test_weird_wall_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -375,7 +379,7 @@ mod tests { }, ), ); - let block_state = dim.set_block_state( + let block_state = world.set_block_state( &BlockPos { x: 0, y: 69, z: 0 }, BlockState::CobblestoneWall_LowLowLowFalseFalseLow, ); @@ -383,7 +387,7 @@ mod tests { block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // do a few steps so we fall on the slab for _ in 0..20 { entity.ai_step(); -- cgit v1.2.3