diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 61a49ca553..3d0d3db1e9 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -482,49 +482,9 @@ fn handle_site( .map_or(false, |id| server.index.sites[id].name() == dest_name) }) { Some(site) => { - // The bulk of this code is to find the z coordinate to teleport to, searching - // for the lowest available one. Copied nearly verbatim from server's lib.rs - let dest_chunk = site.center; - // Unwrapping because generate_chunk only returns err when should_continue evals - // to true - let (tc, _cs) = server + let pos = server .world - .generate_chunk(server.index.as_index_ref(), dest_chunk, || false) - .unwrap(); - let min_z = tc.get_min_z(); - let max_z = tc.get_max_z(); - - let pos = TerrainChunkSize::center_wpos(dest_chunk); - let pos = Vec3::new(pos.x, pos.y, min_z); - let pos = { - use common::vol::ReadVol; - (0..(max_z - min_z)) - .map(|z_diff| pos + Vec3::unit_z() * z_diff) - .find(|test_pos| { - let chunk_relative_xy = - test_pos.xy().map2(TerrainChunkSize::RECT_SIZE, |e, sz| { - e.rem_euclid(sz as i32) - }); - tc.get( - Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z) - - Vec3::unit_z(), - ) - .map_or(false, |b| b.is_filled()) - && (0..3).all(|z| { - tc.get( - Vec3::new( - chunk_relative_xy.x, - chunk_relative_xy.y, - test_pos.z, - ) + Vec3::unit_z() * z, - ) - .map_or(true, |b| !b.is_solid()) - }) - }) - .unwrap_or(pos) - .map(|e| e as f32) - + 0.5 - }; + .find_lowest_accessible_pos(server.index.as_index_ref(), site.center); server.state.write_component(target, comp::Pos(pos)); server.state.write_component(target, comp::ForceUpdate); }, diff --git a/server/src/lib.rs b/server/src/lib.rs index c72ff68331..3869da74eb 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -66,7 +66,6 @@ use common::{ slowjob::SlowJobPool, terrain::TerrainChunkSize, uid::UidAllocator, - vol::{ReadVol, RectVolSize}, }; use common_ecs::run_now; use common_net::{ @@ -318,38 +317,7 @@ impl Server { }, }; - // Calculate the middle of the chunk in the world - let spawn_wpos = TerrainChunkSize::center_wpos(spawn_chunk); - - // Unwrapping because generate_chunk only returns err when should_continue evals - // to true - let (tc, _cs) = world.generate_chunk(index, spawn_chunk, || false).unwrap(); - let min_z = tc.get_min_z(); - let max_z = tc.get_max_z(); - - let pos = Vec3::new(spawn_wpos.x, spawn_wpos.y, min_z); - (0..(max_z - min_z)) - .map(|z_diff| pos + Vec3::unit_z() * z_diff) - .find(|test_pos| { - let chunk_relative_xy = test_pos - .xy() - .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e.rem_euclid(sz as i32)); - tc.get( - Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z) - - Vec3::unit_z(), - ) - .map_or(false, |b| b.is_filled()) - && (0..3).all(|z| { - tc.get( - Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z) - + Vec3::unit_z() * z, - ) - .map_or(true, |b| !b.is_solid()) - }) - }) - .unwrap_or(pos) - .map(|e| e as f32) - + 0.5 + world.find_lowest_accessible_pos(index, spawn_chunk) }; #[cfg(not(feature = "worldgen"))] let spawn_point = Vec3::new(0.0, 0.0, 256.0); diff --git a/world/src/lib.rs b/world/src/lib.rs index 749ae305c4..87eae3c622 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -165,6 +165,41 @@ impl World { pub fn sample_blocks(&self) -> BlockGen { BlockGen::new(ColumnGen::new(&self.sim)) } + pub fn find_lowest_accessible_pos(&self, index: IndexRef, chunk_pos: Vec2) -> Vec3 { + // Calculate the middle of the chunk in the world + let spawn_wpos = TerrainChunkSize::center_wpos(chunk_pos); + + // Unwrapping because generate_chunk only returns err when should_continue evals + // to true + let (tc, _cs) = self.generate_chunk(index, chunk_pos, || false).unwrap(); + let min_z = tc.get_min_z(); + let max_z = tc.get_max_z(); + + let pos = Vec3::new(spawn_wpos.x, spawn_wpos.y, min_z); + (0..(max_z - min_z)) + .map(|z_diff| pos + Vec3::unit_z() * z_diff) + .find(|test_pos| { + let chunk_relative_xy = test_pos + .xy() + .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e.rem_euclid(sz as i32)); + tc.get( + Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z) + - Vec3::unit_z(), + ) + .map_or(false, |b| b.is_filled()) + && (0..3).all(|z| { + tc.get( + Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z) + + Vec3::unit_z() * z, + ) + .map_or(true, |b| !b.is_solid()) + }) + }) + .unwrap_or(pos) + .map(|e| e as f32) + + 0.5 + } + #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 #[allow(clippy::eval_order_dependence)] #[allow(clippy::result_unit_err)]