diff options
| author | mat <git@matdoes.dev> | 2026-01-04 22:06:06 -0300 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2026-01-04 22:06:06 -0300 |
| commit | c50a8662afeadfce50f64600efa497b07e9bce86 (patch) | |
| tree | ccafaa122e11f5b94bbe2adb437b99eaa4028766 | |
| parent | f6e4ad941f44edc92bdde270f0d16e5fb3cb0f8d (diff) | |
| download | azalea-drasl-c50a8662afeadfce50f64600efa497b07e9bce86.tar.xz | |
better order for RelBlockPos and slightly cleanup calculate_cached_mining_costs_index
| -rw-r--r-- | azalea/src/pathfinder/rel_block_pos.rs | 6 | ||||
| -rw-r--r-- | azalea/src/pathfinder/world.rs | 38 |
2 files changed, 29 insertions, 15 deletions
diff --git a/azalea/src/pathfinder/rel_block_pos.rs b/azalea/src/pathfinder/rel_block_pos.rs index b8e96041..65b61ffa 100644 --- a/azalea/src/pathfinder/rel_block_pos.rs +++ b/azalea/src/pathfinder/rel_block_pos.rs @@ -14,10 +14,12 @@ use azalea_core::position::BlockPos; #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(C)] pub struct RelBlockPos { - pub x: i16, - pub z: i16, /// The actual non-relative Y coordinate of the block. pub y: i32, + /// The X coordinate of the block, relative to some origin. + pub x: i16, + /// The Y coordinate of the block, relative to some origin. + pub z: i16, } impl RelBlockPos { diff --git a/azalea/src/pathfinder/world.rs b/azalea/src/pathfinder/world.rs index 819e4254..a44af6b5 100644 --- a/azalea/src/pathfinder/world.rs +++ b/azalea/src/pathfinder/world.rs @@ -108,8 +108,11 @@ impl CachedWorld { cached_blocks: Default::default(), // this uses about 12mb of memory. it *really* helps though. cached_mining_costs: UnsafeCell::new( - vec![(RelBlockPos::new(i16::MAX, i32::MAX, i16::MAX), 0.); 2usize.pow(20)] - .into_boxed_slice(), + vec![ + (RelBlockPos::new(i16::MAX, i32::MAX, i16::MAX), 0.); + CACHED_MINING_COSTS_SIZE + ] + .into_boxed_slice(), ), } } @@ -314,7 +317,7 @@ impl CachedWorld { let cached_mining_costs = unsafe { &mut *self.cached_mining_costs.get() }; // 20 bits total: // 8 bits for x, 4 bits for y, 8 bits for z - let hash_index = Self::calculate_cached_mining_costs_index(pos); + let hash_index = calculate_cached_mining_costs_index(pos); let &(cached_pos, potential_cost) = unsafe { cached_mining_costs.get_unchecked(hash_index) }; if cached_pos == pos { @@ -329,16 +332,6 @@ impl CachedWorld { cost } - fn calculate_cached_mining_costs_index(pos: RelBlockPos) -> usize { - // 20 bits total: - // 8 bits for x, 8 bits for z, 4 bits for y - let hash_index = ((pos.x as usize & 0xff) << 12) - | ((pos.z as usize & 0xff) << 4) - | (pos.y as usize & 0xf); - debug_assert!(hash_index < 1048576); - hash_index - } - fn uncached_cost_for_breaking_block( &self, pos: RelBlockPos, @@ -526,6 +519,25 @@ impl CachedWorld { } } +const CACHED_MINING_COSTS_SIZE: usize = 2usize.pow(20); +fn calculate_cached_mining_costs_index(pos: RelBlockPos) -> usize { + // create a 20-bit index by taking the bottom bits from each axis + + const X_BITS: usize = 8; + const Y_BITS: usize = 3; + const Z_BITS: usize = 8; + + const X_MASK: usize = (1 << X_BITS) - 1; + const Y_MASK: usize = (1 << Y_BITS) - 1; + const Z_MASK: usize = (1 << Z_BITS) - 1; + + let hash_index = ((pos.x as usize & X_MASK) << (Y_BITS + Z_BITS)) + | ((pos.z as usize & Z_MASK) << Y_BITS) + | (pos.y as usize & Y_MASK); + debug_assert!(hash_index < CACHED_MINING_COSTS_SIZE); + hash_index +} + /// Whether our client could pass through this block. pub fn is_block_state_passable(block_state: BlockState) -> bool { // i already tried optimizing this by having it cache in an IntMap/FxHashMap but |
