diff --git a/src/entities/livestock/rabbit.rs b/src/entities/livestock/rabbit.rs index e22b05d..d94e3ce 100644 --- a/src/entities/livestock/rabbit.rs +++ b/src/entities/livestock/rabbit.rs @@ -126,6 +126,11 @@ pub fn rabbit_dig_system( let entity_pos = transform.translation.as_ivec3(); let below_pos = IVec3::new(entity_pos.x, entity_pos.y, entity_pos.z - ITILE_SIZE); + // Don't dig below world floor — would panic in remove_floor bounds check. + if below_pos.z < -(crate::world::chunks::Z_BELOW as i32 - 1) * ITILE_SIZE { + continue; + } + if tilemap.remove_floor(&below_pos).is_some() { tile_changed.write(TileChangedEvent { pos: below_pos }); diff --git a/src/entities/shared_systems/pathfinding.rs b/src/entities/shared_systems/pathfinding.rs index 1c4b94c..77ec7b6 100644 --- a/src/entities/shared_systems/pathfinding.rs +++ b/src/entities/shared_systems/pathfinding.rs @@ -68,7 +68,7 @@ use crate::world::tiles::tile_changed::{PathfindingDirtyChunks, TileChangedEvent use crate::world::tiles::TileMap; use crate::world::{ chunks::CHUNK_SIZE, - chunks::{world_to_chunk, ChunkMap}, + chunks::{world_to_chunk, ChunkMap, Z_ABOVE, Z_BELOW}, }; use crate::{constants::*, entities::shared_components::Ambulatory}; use bevy::math::ivec3; @@ -609,10 +609,12 @@ pub fn movement( .for_each(|(mut ambulatory, mut transform)| { let current_pos = transform.translation; if !is_standable_tile(&tilemap, current_pos.as_ivec3()) { - // Don't fall below world minimum z — rabbits digging can leave no floor - // to stand on, but they should stop at the world floor rather than - // falling into oblivion and panicking pos_to_index overflow. - if transform.translation.z > -(crate::world::chunks::Z_BELOW as f32) * TILE_SIZE { + // Entities can spawn above the loaded world range (z > Z_ABOVE*TILE_SIZE). + // Snap them to the top instead of falling through unloaded z-space one + // tile per tick. + if transform.translation.z > Z_ABOVE as f32 * TILE_SIZE { + transform.translation.z = Z_ABOVE as f32 * TILE_SIZE; + } else if transform.translation.z > -(Z_BELOW as f32) * TILE_SIZE { transform.translation.z -= TILE_SIZE; } ambulatory.current_path = None;