diff --git a/assets/world/structure/dungeon/ruins.vox b/assets/world/structure/dungeon/ruins.vox new file mode 100644 index 0000000000..c06fd4d539 --- /dev/null +++ b/assets/world/structure/dungeon/ruins.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df1e59df3b17fcb861dedf6bbd9363db72e55e695508e8b0997f9a05d3b42c63 +size 845603 diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 4d386c9743..0ebe337f62 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -15,6 +15,7 @@ pub enum StructureBlock { Acacia, PalmLeaves, Fruit, + Hollow, Block(Block), } @@ -94,6 +95,7 @@ impl Asset for Structure { 2 => StructureBlock::PalmLeaves, 4 => StructureBlock::Acacia, 7 => StructureBlock::Fruit, + 15 => StructureBlock::Hollow, index => { let color = palette .get(index as usize) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 0c3c0d5871..42c4b010c3 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -289,40 +289,14 @@ impl<'a> BlockGen<'a> { } }); - let block = if definitely_underground { - block.unwrap_or(Block::empty()) - } else { - block - .or_else(|| { - structures.iter().find_map(|st| { - let (st, st_sample) = st.as_ref()?; - - st.get(wpos, st_sample) - - /* - let rpos = wpos - st.pos; - let block_pos = Vec3::unit_z() * rpos.z - + Vec3::from(st.units.0) * rpos.x - + Vec3::from(st.units.1) * rpos.y; - - st.volume - .get((block_pos * 128) / 128) // Scaling - .map(|b| { - block_from_structure( - *b, - block_pos, - st.pos.into(), - st.seed, - st_sample, - ) - }) - .ok() - .filter(|block| !block.is_empty()) - */ - }) - }) - .unwrap_or(Block::empty()) - }; + let block = structures + .iter() + .find_map(|st| { + let (st, st_sample) = st.as_ref()?; + st.get(wpos, st_sample) + }) + .or(block) + .unwrap_or(Block::empty()); Some(block) } @@ -346,9 +320,11 @@ impl<'a> ZCache<'a> { let cliff = if self.sample.near_cliffs { 48.0 } else { 0.0 }; let warp = self.sample.chaos * 48.0; - let structure = self.structures.iter().filter_map(|st| st.as_ref()).fold( - 0, - |a, (st_info, st_sample)| { + let (structure_min, structure_max) = self + .structures + .iter() + .filter_map(|st| st.as_ref()) + .fold((0.0f32, 0.0f32), |(min, max), (st_info, st_sample)| { let bounds = st_info.get_bounds(); let st_area = Aabr { min: Vec2::from(bounds.min), @@ -356,14 +332,14 @@ impl<'a> ZCache<'a> { }; if st_area.contains_point(self.wpos - st_info.pos) { - a.max(bounds.max.z) + (min.min(bounds.min.z as f32), max.max(bounds.max.z as f32)) } else { - a + (min, max) } - }, - ) as f32; + }); - let max = (self.sample.alt + cliff + structure + warp + 8.0) + let min = min + structure_min; + let max = (self.sample.alt + cliff + structure_max + warp + 8.0) .max(self.sample.water_level) .max(CONFIG.sea_level + 2.0); @@ -444,11 +420,10 @@ impl StructureInfo { volume .get((block_pos * 128) / 128) // Scaling - .map(|b| { + .ok() + .and_then(|b| { block_from_structure(*b, block_pos, self.pos.into(), self.seed, sample) }) - .ok() - .filter(|block| !block.is_empty()) } } } @@ -460,7 +435,7 @@ fn block_from_structure( structure_pos: Vec2, structure_seed: u32, _sample: &ColumnSample, -) -> Block { +) -> Option { let field = RandomField::new(structure_seed + 0); let lerp = 0.5 @@ -468,17 +443,17 @@ fn block_from_structure( + ((field.get(Vec3::from(pos)) % 256) as f32 / 256.0 - 0.5) * 0.15; match sblock { - StructureBlock::TemperateLeaves => Block::new( + StructureBlock::TemperateLeaves => Some(Block::new( 1, Lerp::lerp(Rgb::new(0.0, 70.0, 35.0), Rgb::new(100.0, 140.0, 0.0), lerp) .map(|e| e as u8), - ), - StructureBlock::PineLeaves => Block::new( + )), + StructureBlock::PineLeaves => Some(Block::new( 1, Lerp::lerp(Rgb::new(0.0, 60.0, 50.0), Rgb::new(30.0, 100.0, 10.0), lerp) .map(|e| e as u8), - ), - StructureBlock::PalmLeaves => Block::new( + )), + StructureBlock::PalmLeaves => Some(Block::new( 1, Lerp::lerp( Rgb::new(15.0, 100.0, 30.0), @@ -486,8 +461,8 @@ fn block_from_structure( lerp, ) .map(|e| e as u8), - ), - StructureBlock::Acacia => Block::new( + )), + StructureBlock::Acacia => Some(Block::new( 1, Lerp::lerp( Rgb::new(35.0, 100.0, 10.0), @@ -495,12 +470,13 @@ fn block_from_structure( lerp, ) .map(|e| e as u8), - ), - StructureBlock::Fruit => Block::new( + )), + StructureBlock::Fruit => Some(Block::new( 1, Lerp::lerp(Rgb::new(255.0, 0.0, 0.0), Rgb::new(200.0, 255.0, 6.0), lerp) .map(|e| e as u8), - ), - StructureBlock::Block(block) => block, + )), + StructureBlock::Hollow => Some(Block::empty()), + StructureBlock::Block(block) => Some(block).filter(|block| !block.is_empty()), } } diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 4e3e7a28f3..02114eddde 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -5,11 +5,17 @@ use crate::{ util::Sampler, World, CONFIG, }; -use common::{terrain::TerrainChunkSize, vol::VolSize}; +use common::{ + assets, + terrain::{Structure, TerrainChunkSize}, + vol::VolSize, +}; +use lazy_static::lazy_static; use noise::NoiseFn; use std::{ f32, ops::{Add, Div, Mul, Neg, Sub}, + sync::Arc, }; use vek::*; @@ -17,6 +23,15 @@ pub struct ColumnGen<'a> { world: &'a World, } +lazy_static! { + pub static ref DUNGEONS: Vec> = vec![ + // green oaks + assets::load_map("world/structure/dungeon/ruins.vox", |s: Structure| s + .with_center(Vec3::new(57, 58, 62))) + .unwrap(), + ]; +} + impl<'a> ColumnGen<'a> { pub fn new(world: &'a World) -> Self { Self { world } @@ -45,6 +60,15 @@ impl<'a> ColumnGen<'a> { seed, meta: Some(StructureMeta::Pyramid { height: 140 }), }) + } else if seed % 17 == 2 && chunk.chaos < 0.2 { + Some(StructureData { + pos, + seed, + meta: Some(StructureMeta::Volume { + units: (Vec2::unit_x(), Vec2::unit_y()), + volume: &DUNGEONS[0], + }), + }) } else { None }