diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 5dbe404fad..ae91d523ec 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -426,7 +426,7 @@ fn write_column( wpos2d: Vec2, z_range: Range, tunnel: Tunnel, - mushroom_cache: &mut SmallCache>, + mushroom_cache: &mut SmallCache, Option>, rng: &mut R, ) { let info = canvas.info(); @@ -494,7 +494,7 @@ fn write_column( let mut get_mushroom = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { let mushroom = if let Some(mushroom) = mushroom_cache - .get(wpos2d, |_| { + .get(wpos2d.with_z(tunnel.a.depth), |_| { let mut rng = RandomPerm::new(seed); let (z_range, radius) = tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; diff --git a/world/src/util/small_cache.rs b/world/src/util/small_cache.rs index 2246d5b932..0205cac3a2 100644 --- a/world/src/util/small_cache.rs +++ b/world/src/util/small_cache.rs @@ -1,23 +1,23 @@ use arr_macro::arr; use vek::*; -fn calc_idx(v: Vec2) -> usize { - let mut x = v.x as u32; - let mut y = v.y as u32; - x = x.wrapping_mul(0x6eed0e9d); - y = y.wrapping_mul(0x2f72b421); - (x ^ y) as usize +fn calc_idx(v: impl Iterator) -> usize { + let mut r = 0; + for (e, h) in v.zip([0x6eed0e9d, 0x2f72b421, 0x18132f72, 0x891e2fba].into_iter()) { + r ^= (e as u32).wrapping_mul(h); + } + r as usize } // NOTE: Use 128 if TerrainChunkSize::RECT_SIZE.x = 128. const CACHE_LEN: usize = 32; -pub struct SmallCache { - index: [Option>; CACHE_LEN + 9], +pub struct SmallCache { + index: [Option; CACHE_LEN + 9], data: [V; CACHE_LEN + 9], random: u32, } -impl Default for SmallCache { +impl Default for SmallCache { fn default() -> Self { Self { index: [None; CACHE_LEN + 9], @@ -26,9 +26,9 @@ impl Default for SmallCache { } } } -impl SmallCache { - pub fn get) -> V>(&mut self, key: Vec2, f: F) -> &V { - let idx = calc_idx(key) % CACHE_LEN; +impl, V: Default> SmallCache { + pub fn get V>(&mut self, key: K, f: F) -> &V { + let idx = calc_idx(key.into_iter()) % CACHE_LEN; // Search if self.index[idx].as_ref().map(|k| k == &key).unwrap_or(false) {