use super::*;
use crate::{
util::{RandomField, Sampler},
Land,
};
use common::terrain::{Block, BlockKind};
use rand::prelude::*;
use std::sync::Arc;
use vek::*;
pub struct DesertCityTemple {
pub door_tile: Vec2<i32>,
bounds: Aabr<i32>,
pub(crate) alt: i32,
}
impl DesertCityTemple {
pub fn generate(
land: &Land,
_rng: &mut impl Rng,
site: &Site,
door_tile: Vec2<i32>,
door_dir: Vec2<i32>,
tile_aabr: Aabr<i32>,
) -> Self {
let door_tile_pos = site.tile_center_wpos(door_tile);
let bounds = Aabr {
min: site.tile_wpos(tile_aabr.min),
max: site.tile_wpos(tile_aabr.max),
};
Self {
bounds,
door_tile: door_tile_pos,
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32,
}
}
}
impl Structure for DesertCityTemple {
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_desertcitytemple\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_desertcitytemple")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let sandstone = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 37 {
0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
_ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
})
}));
let sandstone_broken = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 42 {
0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
_ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
})
}));
let base = self.alt + 1;
let center = self.bounds.center();
let diameter =
10 + (self.bounds.max.x - self.bounds.min.x).min(self.bounds.max.y - self.bounds.min.y);
painter
.aabb(Aabb {
min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
})
.union(painter.aabb(Aabb {
min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
}))
.union(painter.aabb(Aabb {
min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
}))
.union(painter.aabb(Aabb {
min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
}))
.fill(sandstone_broken);
painter
.aabb(Aabb {
min: Vec2::new(self.bounds.min.x + 1, center.y - 8).with_z(base),
max: Vec2::new(self.bounds.max.x, center.y + 8).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 7, self.bounds.min.y + 1).with_z(base),
max: Vec2::new(center.x + 9, self.bounds.max.y).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: (self.bounds.min + 1).with_z(base - 20),
max: (self.bounds.max).with_z(base),
})
.fill(sandstone.clone());
let temple_color = match (RandomField::new(0).get((center - 3).with_z(base))) % 2 {
0 => Fill::Brick(BlockKind::Rock, Rgb::new(100, 101, 250), 3),
_ => Fill::Brick(BlockKind::Rock, Rgb::new(63, 49, 63), 24),
};
let temple_size = diameter / 3;
let floaty_block = Fill::Brick(BlockKind::GlowingWeakRock, Rgb::new(253, 240, 149), 2);
let temple = Aabb {
min: (center - temple_size).with_z(base),
max: (center + temple_size - 1).with_z(base + temple_size + 1),
};
painter.aabb(temple).fill(sandstone.clone());
painter
.aabb(Aabb {
min: (center - temple_size - 1).with_z(base + temple_size + 1),
max: (center + temple_size).with_z(base + temple_size + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: (center - temple_size).with_z(base + temple_size + 2),
max: (center + temple_size - 1).with_z(base + temple_size + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size - 1, center.y - (temple_size / 4) - 2)
.with_z(base + temple_size + 3),
max: Vec2::new(center.x + temple_size, center.y + (temple_size / 4) + 1)
.with_z(base + temple_size + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - (temple_size / 4) - 2, center.y - temple_size - 1)
.with_z(base + temple_size + 3),
max: Vec2::new(center.x + (temple_size / 4) + 1, center.y + temple_size)
.with_z(base + temple_size + 4),
})
.clear();
painter
.aabb(Aabb {
min: (center - temple_size + 1).with_z(base + temple_size),
max: (center + temple_size - 2).with_z(base + temple_size + 3),
})
.clear();
for dir in SQUARE_4 {
let corner_pos = center - temple_size;
let pillar_center = corner_pos + (dir * ((2 * temple_size) - 1));
painter
.aabb(Aabb {
min: (pillar_center - 4).with_z(base),
max: (pillar_center + 4).with_z(base + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: (pillar_center - 3).with_z(base + 4),
max: (pillar_center + 3).with_z(base + temple_size + 3),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: (pillar_center - 4).with_z(base + temple_size + 3),
max: (pillar_center + 4).with_z(base + temple_size + 6),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: (pillar_center - 3).with_z(base + temple_size + 4),
max: (pillar_center + 3).with_z(base + temple_size + 6),
})
.clear();
painter
.aabb(Aabb {
min: (center - temple_size).with_z(base + temple_size + 3),
max: (center + temple_size - 1).with_z(base + temple_size + 6),
})
.clear()
}
for s in 0..2 {
let spread_select = ((RandomField::new(0).get((center - 1).with_z(base))) % 2) as i32;
let spread = 3 * spread_select;
let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
match carve_style {
0 => {
for c in 0..(temple_size - 5) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size + 5 + (2 * c),
center.y - temple_size,
)
.with_z(base + 2),
max: Vec2::new(
center.x - temple_size + 6 + (2 * c),
center.y + temple_size - 1,
)
.with_z(base + temple_size - 1),
})
.clear();
}
for c in 0..(temple_size - 5) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size,
center.y - temple_size + 5 + (2 * c),
)
.with_z(base + 2),
max: Vec2::new(
center.x + temple_size - 1,
center.y - temple_size + 6 + (2 * c),
)
.with_z(base + temple_size - 1),
})
.clear();
}
},
1 => {
for c in 0..((temple_size / 2) - 2) {
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 5, center.y - temple_size)
.with_z(base + 2 + ((spread + 2) * c)),
max: Vec2::new(
center.x + temple_size - 6,
center.y + temple_size - 1,
)
.with_z(base + 3 + ((spread + 2) * c) + spread_select),
})
.clear();
}
for c in 0..((temple_size / 2) - 2) {
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - temple_size + 5)
.with_z(base + 2 + ((spread + 2) * c)),
max: Vec2::new(
center.x + temple_size - 1,
center.y + temple_size - 6,
)
.with_z(base + 3 + ((spread + 2) * c) + spread_select),
})
.clear();
}
},
_ => {},
}
}
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 3, center.y - temple_size + 3)
.with_z(base + temple_size - 1),
})
.fill(temple_color.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 2, center.y + temple_size - 4)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
.with_z(base + temple_size - 1),
})
.fill(temple_color.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
.with_z(base + 2),
max: Vec2::new(center.x - temple_size + 3, center.y + temple_size - 3)
.with_z(base + temple_size - 1),
})
.fill(temple_color.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x + temple_size - 4, center.y - temple_size + 2)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
.with_z(base + temple_size - 1),
})
.fill(temple_color.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 6, center.y - temple_size).with_z(base + 3),
max: Vec2::new(center.x + temple_size - 7, center.y - temple_size + 1)
.with_z(base + temple_size - 2),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 6, center.y + temple_size - 2)
.with_z(base + 3),
max: Vec2::new(center.x + temple_size - 7, center.y + temple_size - 1)
.with_z(base + temple_size - 2),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - temple_size + 6).with_z(base + 3),
max: Vec2::new(center.x - temple_size + 1, center.y + temple_size - 7)
.with_z(base + temple_size - 2),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x + temple_size - 2, center.y - temple_size + 6)
.with_z(base + 3),
max: Vec2::new(center.x + temple_size - 1, center.y + temple_size - 7)
.with_z(base + temple_size - 2),
})
.clear();
painter
.cylinder(Aabb {
min: (center - temple_size + 3).with_z(base + temple_size),
max: (center + temple_size - 4).with_z(base + temple_size + 1),
})
.fill(sandstone.clone());
let top = painter.sphere(Aabb {
min: (center - temple_size + 3).with_z(base),
max: (center + temple_size - 4).with_z(base + (2 * temple_size) - 7),
});
top.fill(sandstone.clone());
for s in 0..2 {
let spread_select =
((RandomField::new(0).get((center - 1 - s).with_z(base))) % 2) as i32;
let spread = 3 * spread_select;
let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
match carve_style {
0 => {
for c in 0..(temple_size - 2) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size + 2 + ((spread + 2) * c),
center.y - temple_size,
)
.with_z(base + temple_size),
max: Vec2::new(
center.x - temple_size + 3 + ((spread + 2) * c) + spread_select,
center.y + temple_size - 1,
)
.with_z(base + (2 * temple_size)),
})
.intersect(top)
.fill(temple_color.clone());
}
},
1 => {
for c in 0..(temple_size - 2) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size,
center.y - temple_size + 2 + ((spread + 2) * c),
)
.with_z(base + temple_size),
max: Vec2::new(
center.x + temple_size - 1,
center.y - temple_size + 3 + ((spread + 2) * c) + spread_select,
)
.with_z(base + (2 * temple_size)),
})
.intersect(top)
.fill(temple_color.clone());
}
},
_ => {},
}
}
painter
.cylinder(Aabb {
min: (center - temple_size + 3).with_z(base + temple_size),
max: (center + temple_size - 4).with_z(base + temple_size + 1),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - temple_size + 4).with_z(base + 1),
max: (center + temple_size - 5).with_z(base + (2 * temple_size) - 8),
})
.clear();
let entry_select = ((RandomField::new(0).get((center + 1).with_z(base))) % 2) as i32;
match entry_select {
0 => {
painter
.aabb(Aabb {
min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base + 4),
max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 7),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 4),
max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 7),
max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 7),
max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 9),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 9),
max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 10),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base + 4),
max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 7),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 4),
max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 7),
max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 7),
max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 9),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 9),
max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 10),
})
.fill(sandstone.clone());
},
_ => {
painter
.aabb(Aabb {
min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 8),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 6),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 8),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 6),
})
.clear();
},
}
painter
.aabb(Aabb {
min: (center - temple_size + 4).with_z(base),
max: (center + temple_size - 5).with_z(base + temple_size - 1),
})
.clear();
painter
.sphere(Aabb {
min: (center - 3).with_z(base),
max: (center + 2).with_z(base + 5),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 4),
max: (center + 2).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 8),
max: (center + 2).with_z(base + 13),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 4).with_z(base + 14),
max: (center + 3).with_z(base + 15),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 16),
max: (center + 2).with_z(base + 21),
})
.fill(floaty_block.clone());
for dir in SQUARE_4 {
let corner_pos = center - temple_size / 2;
let sclpt_center = corner_pos + (dir * (temple_size));
painter
.sphere(Aabb {
min: (sclpt_center - 2).with_z(base),
max: (sclpt_center + 1).with_z(base + 3),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 2).with_z(base + 2),
max: (sclpt_center + 1).with_z(base + 5),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 3).with_z(base + 5),
max: (sclpt_center + 2).with_z(base + 6),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 3).with_z(base + 7),
max: (sclpt_center + 2).with_z(base + 8),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 2).with_z(base + 9),
max: (sclpt_center + 1).with_z(base + 12),
})
.fill(floaty_block.clone());
}
}
}