diff --git a/world/src/canvas.rs b/world/src/canvas.rs index ff7779d522..b342501874 100644 --- a/world/src/canvas.rs +++ b/world/src/canvas.rs @@ -1,18 +1,18 @@ use crate::{ block::{block_from_structure, ZCache}, - column::ColumnSample, + column::{ColumnGen, ColumnSample}, index::IndexRef, land::Land, layer::spot::Spot, sim::{SimChunk, WorldSim}, - util::Grid, + util::{Grid, Sampler}, }; use common::{ generation::EntityInfo, terrain::{Block, Structure, TerrainChunk, TerrainChunkSize}, vol::{ReadVol, RectVolSize, WriteVol}, }; -use std::ops::Deref; +use std::{borrow::Cow, ops::Deref}; use vek::*; #[derive(Copy, Clone)] @@ -37,14 +37,26 @@ impl<'a> CanvasInfo<'a> { .into() } - pub fn col(&self, pos: Vec2) -> Option<&'a ColumnSample> { + pub fn col(&self, wpos: Vec2) -> Option<&'a ColumnSample> { self.column_grid - .get(self.column_grid_border + pos - self.wpos()) + .get(self.column_grid_border + wpos - self.wpos()) .map(Option::as_ref) .flatten() .map(|zc| &zc.sample) } + /// Attempt to get the data for the given column, generating it if we don't + /// have it. + /// + /// This function does not (currently) cache generated columns. + pub fn col_or_gen(&self, wpos: Vec2) -> Option> { + self.col(wpos).map(Cow::Borrowed).or_else(|| { + Some(Cow::Owned( + ColumnGen::new(self.chunks()).get((wpos, self.index()))?, + )) + }) + } + pub fn nearby_spots(&self) -> impl Iterator, Spot, u32)> + '_ { (-1..2) .map(|x| (-1..2).map(move |y| Vec2::new(x, y))) diff --git a/world/src/layer/spot.rs b/world/src/layer/spot.rs index 0bd20d7e92..0b99e6e626 100644 --- a/world/src/layer/spot.rs +++ b/world/src/layer/spot.rs @@ -24,14 +24,14 @@ impl Spot { Spot::Camp, world, 10.0, - |g, c| g < 0.25 && !c.near_cliffs() && !c.river.near_water(), + |g, c| g < 0.25 && !c.near_cliffs() && !c.river.near_water() && !c.path.0.is_way(), false, ); Self::generate_spots( Spot::BanditCamp, world, 10.0, - |g, c| g < 0.25 && !c.near_cliffs() && !c.river.near_water(), + |g, c| g < 0.25 && !c.near_cliffs() && !c.river.near_water() && !c.path.0.is_way(), false, ); } @@ -90,7 +90,12 @@ pub fn apply_spots_to(canvas: &mut Canvas, dynamic_rng: &mut impl Rng) { Spot::BanditCamp => { let structures = Structure::load_group("dungeon_entrances").read(); let structure = structures.choose(&mut rng).unwrap(); - let origin = spot_wpos.with_z(canvas.land().get_alt_approx(spot_wpos) as i32); + let origin = spot_wpos.with_z( + canvas + .col_or_gen(spot_wpos) + .map(|c| c.alt as i32) + .unwrap_or(0), + ); canvas.blit_structure(origin, &structure, seed); let spawn_radius = 12;