diff --git a/azalea-core/src/direction.rs b/azalea-core/src/direction.rs index c7b89784..96d20a10 100644 --- a/azalea-core/src/direction.rs +++ b/azalea-core/src/direction.rs @@ -73,4 +73,11 @@ impl AxisCycle { Self::Backward => Axis::from_ordinal(floor_mod(axis as i32 - 1, 3)), } } + pub fn cycle_xyz(self, x: u32, y: u32, z: u32, axis: Axis) -> u32 { + match self { + Self::None => axis.choose(x, y, z), + Self::Forward => axis.choose(z, x, y), + Self::Backward => axis.choose(y, z, x), + } + } } diff --git a/azalea-physics/src/discrete_voxel_shape.rs b/azalea-physics/src/discrete_voxel_shape.rs index 0cf8ddf0..299eefe6 100644 --- a/azalea-physics/src/discrete_voxel_shape.rs +++ b/azalea-physics/src/discrete_voxel_shape.rs @@ -1,24 +1,8 @@ -use azalea_core::{Axis, BitSet}; +use azalea_core::{Axis, AxisCycle, BitSet}; // TODO: every impl of DiscreteVoxelShape could be turned into a single enum as an optimization pub trait DiscreteVoxelShape { - // public boolean isFullWide(int var1, int var2, int var3) { - // if (var1 >= 0 && var2 >= 0 && var3 >= 0) { - // return var1 < this.xSize && var2 < this.ySize && var3 < this.zSize ? this.isFull(var1, var2, var3) : false; - // } else { - // return false; - // } - // } - // pub fn is_full_wide(&self, x: i32, y: i32, z: i32) -> bool { - // // TODO: can this be u32 instead of i32? - // if x >= 0 && y >= 0 && z >= 0 { - // if x < self.x_size as i32 && y < self.y_size as i32 && z < self.z_size as i32 { - // return self.is_full(x, y, z); - // } - // } - // return false; - // } fn size(&self, axis: Axis) -> u32; fn first_full_x(&self) -> u32; @@ -42,6 +26,21 @@ pub trait DiscreteVoxelShape { false } + fn is_full_wide(&self, x: u32, y: u32, z: u32) -> bool { + (x >= 0 && y >= 0 && z >= 0) + && (x < self.size(Axis::X) && y < self.size(Axis::Y) && z < self.size(Axis::Z)) + && (self.is_full(x, y, z)) + } + fn is_full_wide_axis_cycle(&self, axis_cycle: AxisCycle, x: u32, y: u32, z: u32) -> bool { + self.is_full_wide( + axis_cycle.cycle_xyz(x, y, z, Axis::X), + axis_cycle.cycle_xyz(x, y, z, Axis::Y), + axis_cycle.cycle_xyz(x, y, z, Axis::Z), + ) + } + + fn is_full(&self, x: u32, y: u32, z: u32) -> bool; + // i don't know how to do this properly fn clone(&self) -> Box; } @@ -151,4 +150,8 @@ impl DiscreteVoxelShape for BitSetDiscreteVoxelShape { fn clone(&self) -> Box { Box::new(Clone::clone(self)) } + + fn is_full(&self, x: u32, y: u32, z: u32) -> bool { + self.storage.index(self.get_index(x, y, z)) + } } diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 5de85fea..9a117faa 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -5,7 +5,7 @@ mod discrete_voxel_shape; mod shape; pub use aabb::*; -use azalea_core::{PositionDelta, PositionXYZ, Vec3}; +use azalea_core::{Axis, PositionDelta, PositionXYZ, Vec3}; use azalea_entity::Entity; use azalea_world::Dimension; pub use block_hit_result::*; @@ -32,7 +32,7 @@ trait HasPhysics { ) -> Vec3; fn collide_with_shapes( movement: &Vec3, - entity_box: &AABB, + entity_box: AABB, collision_boxes: &Vec>, ) -> Vec3; } @@ -92,12 +92,12 @@ 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) } fn collide_with_shapes( movement: &Vec3, - entity_box: &AABB, + mut entity_box: AABB, collision_boxes: &Vec>, ) -> Vec3 { if collision_boxes.is_empty() { @@ -108,9 +108,9 @@ impl HasPhysics for Entity { let mut y_movement = movement.y; let mut z_movement = movement.z; if y_movement != 0. { - y_movement = Shapes::collide_y(entity_box, collision_boxes, y_movement); + y_movement = Shapes::collide(&Axis::Y, &entity_box, collision_boxes, y_movement); if y_movement != 0. { - *entity_box = entity_box.move_relative(0., y_movement, 0.); + entity_box = entity_box.move_relative(0., y_movement, 0.); } } @@ -119,21 +119,21 @@ impl HasPhysics for Entity { let more_z_movement = x_movement.abs() < z_movement.abs(); if more_z_movement && z_movement != 0. { - z_movement = Shapes::collide_z(entity_box, collision_boxes, z_movement); + z_movement = Shapes::collide(&Axis::Z, &entity_box, collision_boxes, z_movement); if z_movement != 0. { - *entity_box = entity_box.move_relative(0., 0., z_movement); + entity_box = entity_box.move_relative(0., 0., z_movement); } } if x_movement != 0. { - x_movement = Shapes::collide_x(entity_box, collision_boxes, x_movement); + x_movement = Shapes::collide(&Axis::X, &entity_box, collision_boxes, x_movement); if x_movement != 0. { - *entity_box = entity_box.move_relative(x_movement, 0., 0.); + entity_box = entity_box.move_relative(x_movement, 0., 0.); } } if !more_z_movement && z_movement != 0. { - z_movement = Shapes::collide_z(entity_box, collision_boxes, z_movement); + z_movement = Shapes::collide(&Axis::Z, &entity_box, collision_boxes, z_movement); } Vec3 { diff --git a/azalea-physics/src/shape.rs b/azalea-physics/src/shape.rs index ff74111c..893e376a 100644 --- a/azalea-physics/src/shape.rs +++ b/azalea-physics/src/shape.rs @@ -24,9 +24,8 @@ impl Shapes { axis: &Axis, entity_box: &AABB, collision_boxes: &Vec>, - movement: f64, + mut movement: f64, ) -> f64 { - let mut shape: Box; for shape in collision_boxes { if movement.abs() < EPSILON { return 0.; @@ -69,7 +68,7 @@ pub trait VoxelShape { fn collide(&self, axis: &Axis, entity_box: &AABB, movement: f64) -> f64 { self.collide_x(AxisCycle::between(*axis, Axis::X), entity_box, movement) } - fn collide_x(&self, axis_cycle: AxisCycle, entity_box: &AABB, movement: f64) -> f64 { + fn collide_x(&self, axis_cycle: AxisCycle, entity_box: &AABB, mut movement: f64) -> f64 { if self.shape().is_empty() { return movement; } @@ -115,13 +114,15 @@ pub trait VoxelShape { for var20 in var14 + 1..var19 { for var21 in var15..var16 { for var22 in var17..var18 { - if self - .shape() - .is_full_wide(inverse_axis_cycle, var20, var21, var22) - { + if self.shape().is_full_wide_axis_cycle( + inverse_axis_cycle, + var20, + var21, + var22, + ) { let var23 = self.get(x_axis, var20 as usize) - var9; if var23 >= -EPSILON { - movement = cmp::min(movement, var23); + movement = f64::min(movement, var23); } return movement; } @@ -132,13 +133,15 @@ pub trait VoxelShape { for var20 in (var13 - 1)..=0 { for var21 in var15..var16 { for var22 in var17..var18 { - if self - .shape() - .is_full_wide(inverse_axis_cycle, var20, var21, var22) - { - let var23 = self.get(x_axis, var20 + 1) - var11; + if self.shape().is_full_wide_axis_cycle( + inverse_axis_cycle, + var20, + var21, + var22, + ) { + let var23 = self.get(x_axis, (var20 + 1) as usize) - var11; if var23 <= EPSILON { - movement = cmp::max(movement, var23); + movement = f64::max(movement, var23); } return movement; }