diff --git a/client/src/lib.rs b/client/src/lib.rs
index 00f64c5025..bb1bbf2873 100644
--- a/client/src/lib.rs
+++ b/client/src/lib.rs
@@ -172,7 +172,8 @@ impl Client {
     pub fn set_view_distance(&mut self, view_distance: u32) {
         self.view_distance = Some(view_distance.max(1).min(25));
         self.postbox
-            .send_message(ClientMsg::SetViewDistance(self.view_distance.unwrap())); // Can't fail
+            .send_message(ClientMsg::SetViewDistance(self.view_distance.unwrap()));
+        // Can't fail
     }
 
     pub fn swap_inventory_slots(&mut self, a: usize, b: usize) {
diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index 5305b8f223..cbd5b2b99f 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -10,6 +10,8 @@ use common::{
     msg::ServerMsg,
     npc::{get_npc_name, NpcKind},
     state::TimeOfDay,
+    terrain::TerrainChunkSize,
+    vol::VolSize,
 };
 use rand::Rng;
 use specs::{Builder, Entity as EcsEntity, Join};
@@ -198,7 +200,14 @@ lazy_static! {
             "/adminify <playername> : Temporarily gives a player admin permissions or removes them",
             true,
             handle_adminify,
-        )
+        ),
+        ChatCommand::new(
+             "debug_column",
+             "{} {}",
+             "/debug_column <x> <y> : Prints some debug information about a column",
+             false,
+             handle_debug_column,
+         ),
     ];
 }
 
@@ -828,3 +837,50 @@ fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
             .notify(entity, ServerMsg::private(String::from(action.help_string)));
     }
 }
+
+fn handle_debug_column(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
+    let sim = server.world.sim();
+    if let Ok((x, y)) = scan_fmt!(&args, action.arg_fmt, i32, i32) {
+        let wpos = Vec2::new(x, y);
+        /* let chunk_pos = wpos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| {
+            e / sz as i32
+        }); */
+
+        let foo = || {
+            // let sim_chunk = sim.get(chunk_pos)?;
+            let alt_base = sim.get_interpolated(wpos, |chunk| chunk.alt_base)?;
+            let alt = sim.get_interpolated(wpos, |chunk| chunk.alt)?;
+            let chaos = sim.get_interpolated(wpos, |chunk| chunk.chaos)?;
+            let temp = sim.get_interpolated(wpos, |chunk| chunk.temp)?;
+            let humidity = sim.get_interpolated(wpos, |chunk| chunk.humidity)?;
+            let rockiness = sim.get_interpolated(wpos, |chunk| chunk.rockiness)?;
+            let tree_density = sim.get_interpolated(wpos, |chunk| chunk.tree_density)?;
+            let spawn_rate = sim.get_interpolated(wpos, |chunk| chunk.spawn_rate)?;
+
+            Some(format!(
+                r#"wpos: {:?}
+alt_base {:?}
+alt {:?}
+chaos {:?}
+temp {:?}
+humidity {:?}
+rockiness {:?}
+tree_density {:?}
+spawn_rate {:?} "#,
+                wpos, alt_base, alt, chaos, temp, humidity, rockiness, tree_density, spawn_rate
+            ))
+        };
+        if let Some(s) = foo() {
+            server.clients.notify(entity, ServerMsg::private(s));
+        } else {
+            server.clients.notify(
+                entity,
+                ServerMsg::private(String::from("Not a pregenerated chunk.")),
+            );
+        }
+    } else {
+        server
+            .clients
+            .notify(entity, ServerMsg::private(String::from(action.help_string)));
+    }
+}
diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs
index 1d12a72cc5..79fde45685 100644
--- a/world/src/block/natural.rs
+++ b/world/src/block/natural.rs
@@ -8,6 +8,7 @@ use crate::{
 use common::{assets, terrain::Structure};
 use lazy_static::lazy_static;
 use std::sync::Arc;
+use std::u32;
 use vek::*;
 
 static VOLUME_RAND: RandomPerm = RandomPerm::new(0xDB21C052);
@@ -25,7 +26,8 @@ pub fn structure_gen<'a>(
     let st_sample = &structure_samples[idx].as_ref()?;
 
     // Assuming it's a tree... figure out when it SHOULDN'T spawn
-    if st_sample.tree_density < 0.5 + (st_seed as f32 / 1000.0).fract() * 0.5
+    let random_seed = (st_seed as f64) / (u32::MAX as f64);
+    if (st_sample.tree_density as f64) < random_seed
         || st_sample.alt < st_sample.water_level
         || st_sample.spawn_rate < 0.5
     {
diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs
index e8d58b7c47..c89575e1e4 100644
--- a/world/src/column/mod.rs
+++ b/world/src/column/mod.rs
@@ -78,8 +78,8 @@ impl<'a> ColumnGen<'a> {
 
         if seed % 5 == 2
             && chunk.temp > CONFIG.desert_temp
-            && chunk.humidity < CONFIG.desert_hum
             && chunk.alt > CONFIG.sea_level + 5.0
+            && chunk.chaos <= 0.35
         {
             Some(StructureData {
                 pos,
diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs
index a259a98309..5be3ae1e69 100644
--- a/world/src/sim/mod.rs
+++ b/world/src/sim/mod.rs
@@ -55,6 +55,7 @@ struct GenCdf {
     alt_base: InverseCdf,
     chaos: InverseCdf,
     alt: InverseCdf,
+    alt_no_seawater: InverseCdf,
 }
 
 pub(crate) struct GenCtx {
@@ -223,8 +224,8 @@ impl WorldSim {
         // are included).
         let pure_water = |posi| {
             let pos = uniform_idx_as_vec2(posi);
-            for x in (pos.x - 1..=pos.x + 1) {
-                for y in (pos.y - 1..=pos.y + 1) {
+            for x in pos.x - 1..=pos.x + 1 {
+                for y in pos.y - 1..=pos.y + 1 {
                     if x >= 0 && y >= 0 && x < WORLD_SIZE.x as i32 && y < WORLD_SIZE.y as i32 {
                         let posi = vec2_as_uniform_idx(Vec2::new(x, y));
                         if alt[posi].1.mul(CONFIG.mountain_scale) > 0.0 {
@@ -236,12 +237,21 @@ impl WorldSim {
             true
         };
 
+        // A version of alt that is uniform over *non-seawater* (or land-adjacent seawater) chunks.
+        let alt_no_seawater = uniform_noise(|posi, wposf| {
+            if pure_water(posi) {
+                None
+            } else {
+                Some(alt[posi].1)
+            }
+        });
+
         // -1 to 1.
         let temp_base = uniform_noise(|posi, wposf| {
             if pure_water(posi) {
                 None
             } else {
-                Some((gen_ctx.temp_nz.get((wposf.div(12000.0)).into_array()) as f32))
+                Some(gen_ctx.temp_nz.get((wposf.div(12000.0)).into_array()) as f32)
             }
         });
 
@@ -265,6 +275,7 @@ impl WorldSim {
             alt_base,
             chaos,
             alt,
+            alt_no_seawater,
         };
 
         let mut chunks = Vec::new();
@@ -530,7 +541,8 @@ impl SimChunk {
         let map_edge_factor = map_edge_factor(posi);
         let (_, chaos) = gen_cdf.chaos[posi];
         let (humid_uniform, _) = gen_cdf.humid_base[posi];
-        let (alt_uniform, alt_pre) = gen_cdf.alt[posi];
+        let (_, alt_pre) = gen_cdf.alt[posi];
+        let (alt_uniform, _) = gen_cdf.alt_no_seawater[posi];
         let (temp_uniform, _) = gen_cdf.temp_base[posi];
 
         // Take the weighted average of our randomly generated base humidity, the scaled