diff --git a/world/src/site2/gen.rs b/world/src/site2/gen.rs
index c72c02d3f6..7fb17ee45e 100644
--- a/world/src/site2/gen.rs
+++ b/world/src/site2/gen.rs
@@ -1,3 +1,4 @@
+use super::*;
 use common::{
     terrain::Block,
     store::{Id, Store},
@@ -26,7 +27,8 @@ impl Fill {
     fn contains_at(&self, tree: &Store<Primitive>, prim: Id<Primitive>, pos: Vec3<i32>) -> bool {
         // Custom closure because vek's impl of `contains_point` is inclusive :(
         let aabb_contains = |aabb: Aabb<i32>, pos: Vec3<i32>| (aabb.min.x..aabb.max.x).contains(&pos.x)
-            && (aabb.min.y..aabb.max.y).contains(&pos.y);
+            && (aabb.min.y..aabb.max.y).contains(&pos.y)
+            && (aabb.min.z..aabb.max.z).contains(&pos.z);
 
         match &tree[prim] {
             Primitive::Empty => false,
@@ -40,8 +42,8 @@ impl Fill {
                     .reduce_max() as f32 / (inset as f32) < 1.0 - ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
             },
 
-            Primitive::And(a, b) => self.contains_at(tree, *a, pos) & self.contains_at(tree, *b, pos),
-            Primitive::Or(a, b) => self.contains_at(tree, *a, pos) | self.contains_at(tree, *b, pos),
+            Primitive::And(a, b) => self.contains_at(tree, *a, pos) && self.contains_at(tree, *b, pos),
+            Primitive::Or(a, b) => self.contains_at(tree, *a, pos) || self.contains_at(tree, *b, pos),
             Primitive::Xor(a, b) => self.contains_at(tree, *a, pos) ^ self.contains_at(tree, *b, pos),
         }
     }
@@ -68,15 +70,16 @@ impl Fill {
 pub trait Structure {
     fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Fill)>(
         &self,
+        site: &Site,
         prim: F,
         fill: G,
     ) {}
 
     // Generate a primitive tree and fills for this structure
-    fn render_collect(&self) -> (Store<Primitive>, Vec<Fill>) {
+    fn render_collect(&self, site: &Site) -> (Store<Primitive>, Vec<Fill>) {
         let mut tree = Store::default();
         let mut fills = Vec::new();
-        let root = self.render(|p| tree.insert(p), |f| fills.push(f));
+        let root = self.render(site, |p| tree.insert(p), |f| fills.push(f));
         (tree, fills)
     }
 }
diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs
index 3b11c32a3b..7211734589 100644
--- a/world/src/site2/mod.rs
+++ b/world/src/site2/mod.rs
@@ -437,7 +437,7 @@ impl Site {
 
         for plot in plots_to_render {
             let (prim_tree, fills) = match &self.plots[plot].kind {
-                PlotKind::House(house) => house.render_collect(),
+                PlotKind::House(house) => house.render_collect(self),
                 _ => continue,
             };
 
diff --git a/world/src/site2/plot/house.rs b/world/src/site2/plot/house.rs
index 6a503c87b0..677a3de3f1 100644
--- a/world/src/site2/plot/house.rs
+++ b/world/src/site2/plot/house.rs
@@ -1,11 +1,12 @@
 use super::*;
 use crate::{Land, util::SQUARE_4};
-use common::terrain::{Block, BlockKind};
+use common::terrain::{Block, BlockKind, SpriteKind};
 use vek::*;
 use rand::prelude::*;
 
 pub struct House {
     door_tile: Vec2<i32>,
+    tile_aabr: Aabr<i32>,
     bounds: Aabr<i32>,
     alt: i32,
     levels: u32,
@@ -15,11 +16,12 @@ impl House {
     pub fn generate(land: &Land, rng: &mut impl Rng, site: &Site, door_tile: Vec2<i32>, tile_aabr: Aabr<i32>) -> Self {
         Self {
             door_tile,
+            tile_aabr,
             bounds: Aabr {
                 min: site.tile_wpos(tile_aabr.min),
                 max: site.tile_wpos(tile_aabr.max),
             },
-            alt: land.get_alt_approx(site.tile_center_wpos(door_tile)) as i32,
+            alt: land.get_alt_approx(site.tile_center_wpos(door_tile)) as i32 + 2,
             levels: rng.gen_range(1..3),
         }
     }
@@ -28,15 +30,16 @@ impl House {
 impl Structure for House {
     fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Fill)>(
         &self,
+        site: &Site,
         mut prim: F,
         mut fill: G,
     ) {
-        let storey = 8;
+        let storey = 6;
         let roof = storey * self.levels as i32;
-        let foundations = 8;
+        let foundations = 12;
 
         // Walls
-        let wall = prim(Primitive::Aabb(Aabb {
+        let outer = prim(Primitive::Aabb(Aabb {
             min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt - foundations),
             max: Vec3::new(self.bounds.max.x, self.bounds.max.y, self.alt + roof),
         }));
@@ -44,14 +47,73 @@ impl Structure for House {
             min: Vec3::new(self.bounds.min.x + 1, self.bounds.min.y + 1, self.alt + 0),
             max: Vec3::new(self.bounds.max.x - 1, self.bounds.max.y - 1, self.alt + roof),
         }));
+        let walls = prim(Primitive::Xor(outer, inner));
         fill(Fill {
-            prim: prim(Primitive::Xor(wall, inner)),
+            prim: walls,
             block: Block::new(BlockKind::Rock, Rgb::new(181, 170, 148)),
         });
 
-        // Floor
+        // wall pillars
+        let mut pillars = prim(Primitive::Empty);
+        for x in self.tile_aabr.min.x + 1..self.tile_aabr.max.x {
+            let pillar = prim(Primitive::Aabb(Aabb {
+                min: Vec3::from(site.tile_wpos(Vec2::new(x, self.tile_aabr.min.y))) + Vec3::unit_z() * self.alt,
+                max: Vec3::from(site.tile_wpos(Vec2::new(x, self.tile_aabr.max.y)) + Vec2::unit_x()) + Vec3::unit_z() * (self.alt + roof),
+            }));
+            pillars = prim(Primitive::Or(pillars, pillar));
+        }
+        for y in self.tile_aabr.min.y + 1..self.tile_aabr.max.y {
+            let pillar = prim(Primitive::Aabb(Aabb {
+                min: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.min.x, y))) + Vec3::unit_z() * self.alt,
+                max: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y)) + Vec2::unit_y()) + Vec3::unit_z() * (self.alt + roof),
+            }));
+            pillars = prim(Primitive::Or(pillars, pillar));
+        }
+        fill(Fill {
+            prim: prim(Primitive::And(walls, pillars)),
+            block: Block::new(BlockKind::Wood, Rgb::new(89, 44, 14)),
+        });
+
+        // For each storey...
         for i in 0..self.levels + 1 {
             let height = storey * i as i32;
+
+            // Windows x axis
+            {
+                let mut windows = prim(Primitive::Empty);
+                for y in self.tile_aabr.min.y..self.tile_aabr.max.y {
+                    let window = prim(Primitive::Aabb(Aabb {
+                        min: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.min.x, y)) + Vec2::unit_y() * 2) + Vec3::unit_z() * (self.alt + height + 2),
+                        max: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y + 1)) - Vec2::unit_y() * 1) + Vec3::unit_z() * (self.alt + height + 5),
+                    }));
+                    windows = prim(Primitive::Or(windows, window));
+                }
+                fill(Fill {
+                    prim: prim(Primitive::And(walls, windows)),
+                    block: Block::air(SpriteKind::Window1)
+                        .with_ori(2)
+                        .unwrap(),
+                });
+            }
+            // Windows y axis
+            {
+                let mut windows = prim(Primitive::Empty);
+                for x in self.tile_aabr.min.x..self.tile_aabr.max.x {
+                    let window = prim(Primitive::Aabb(Aabb {
+                        min: Vec3::from(site.tile_wpos(Vec2::new(x, self.tile_aabr.min.y)) + Vec2::unit_x() * 2) + Vec3::unit_z() * (self.alt + height + 2),
+                        max: Vec3::from(site.tile_wpos(Vec2::new(x + 1, self.tile_aabr.max.y)) - Vec2::unit_x() * 1) + Vec3::unit_z() * (self.alt + height + 5),
+                    }));
+                    windows = prim(Primitive::Or(windows, window));
+                }
+                fill(Fill {
+                    prim: prim(Primitive::And(walls, windows)),
+                    block: Block::air(SpriteKind::Window1)
+                        .with_ori(0)
+                        .unwrap(),
+                });
+            }
+
+            // Floor
             fill(Fill {
                 prim: prim(Primitive::Aabb(Aabb {
                     min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt + height + 0),