diff options
| author | mat <git@matdoes.dev> | 2026-05-07 01:42:52 -0330 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2026-05-07 08:05:58 -1200 |
| commit | ee7358ebc2d3a033b48b3a97af4255e1efba9ef9 (patch) | |
| tree | 7a69c0676225bab4e37b44fb398829d554708623 /azalea-physics/src/collision/shape_offset.rs | |
| parent | a6fbdea961c2f8a788b362cbde1eab356d298e84 (diff) | |
| download | azalea-drasl-ee7358ebc2d3a033b48b3a97af4255e1efba9ef9.tar.xz | |
correct shapes for blocks with random offsets
Diffstat (limited to 'azalea-physics/src/collision/shape_offset.rs')
| -rw-r--r-- | azalea-physics/src/collision/shape_offset.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/azalea-physics/src/collision/shape_offset.rs b/azalea-physics/src/collision/shape_offset.rs new file mode 100644 index 00000000..2832d680 --- /dev/null +++ b/azalea-physics/src/collision/shape_offset.rs @@ -0,0 +1,79 @@ +use std::borrow::Cow; + +use azalea_block::BlockState; +use azalea_core::{ + math::get_seed, + position::{BlockPos, Vec3}, +}; +use azalea_registry::builtin::BlockKind; + +use crate::collision::{VoxelShape, blocks::RANDOM_SHAPE_OFFSETS_MAP}; + +/// Adds the random offset for the shape, given the block state and position. +/// +/// For most blocks, this won't have any effect. It's only used for a few blocks +/// like flowers and bamboo. +pub fn apply_shape_offset( + block: BlockState, + pos: BlockPos, + shape: &'static VoxelShape, +) -> Cow<'static, VoxelShape> { + // don't waste time checking the block if it's already known to be empty. also, + // it's faster to compare addresses than to call `.is_empty`. + if std::ptr::eq(shape, &*super::EMPTY_SHAPE) { + return Cow::Borrowed(shape); + } + + let offset_kind = RANDOM_SHAPE_OFFSETS_MAP[block.id() as usize]; + if offset_kind == 0 { + return Cow::Borrowed(shape); + } + + let kind = block.as_block_kind(); + + let mut max_horizontal_offset = 0.25; + // search `getMaxHorizontalOffset` in the vanilla code + // TODO: sulfur spike gets added here in 26.2 + if kind == BlockKind::PointedDripstone { + max_horizontal_offset = 2. / 16.; + } + + // these ids are required to be the same as the ones in shapes.py + let delta = match offset_kind { + // see offsetType in BlockBehaviour.java + 1 => { + // xz + xyz_offset_for_pos(pos.with_y(0), max_horizontal_offset, 0.) + } + 2 => { + // xyz + + let mut max_vertical_offset = 0.2; + if kind == BlockKind::SmallDripleaf { + // search `getMaxVerticalOffset` in the vanilla code + max_vertical_offset = 0.1; + } + + xyz_offset_for_pos(pos, max_horizontal_offset, max_vertical_offset) + } + _ => unreachable!(), + }; + + Cow::Owned(shape.move_relative(delta)) +} + +fn xyz_offset_for_pos(pos: BlockPos, max_horizontal_offset: f64, max_vertical_offset: f64) -> Vec3 { + let seed = get_seed(pos); + let y = if max_vertical_offset == 0. { + 0. + } else { + ((((seed >> 4) & 15) as f32 / 15.) as f64 - 1.) * max_vertical_offset + }; + + let x = (((seed & 15) as f32 / 15.) as f64 - 0.5) * 0.5; + let x = x.clamp(-max_horizontal_offset, max_horizontal_offset); + let z = ((((seed >> 8) & 15) as f32 / 15.) as f64 - 0.5) * 0.5; + let z = z.clamp(-max_horizontal_offset, max_horizontal_offset); + + Vec3 { x, y, z } +} |
