From 1c6a6cd6cf003cc1cb90c2fb7217938cb47d2dd5 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 26 Feb 2020 21:43:31 +0000 Subject: [PATCH] Moved settlement code to site directory, removed old town generation code --- world/src/block/mod.rs | 34 +- world/src/block/natural.rs | 1 - world/src/column/mod.rs | 18 - world/src/generator/town/mod.rs | 710 ------------------ world/src/generator/town/util.rs | 36 - world/src/generator/town/vol.rs | 215 ------ world/src/lib.rs | 2 +- world/src/sim/mod.rs | 2 +- world/src/{generator => site}/mod.rs | 39 +- .../src/{generator => site}/settlement/mod.rs | 0 10 files changed, 6 insertions(+), 1051 deletions(-) delete mode 100644 world/src/generator/town/mod.rs delete mode 100644 world/src/generator/town/util.rs delete mode 100644 world/src/generator/town/vol.rs rename world/src/{generator => site}/mod.rs (54%) rename world/src/{generator => site}/settlement/mod.rs (100%) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 57e72eed5c..3a6cfd571a 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -2,7 +2,6 @@ mod natural; use crate::{ column::{ColumnGen, ColumnSample}, - generator::{Generator, TownGen}, util::{RandomField, Sampler, SmallCache}, CONFIG, }; @@ -51,11 +50,7 @@ impl<'a> BlockGen<'a> { cache, Vec2::from(*cliff_pos), ) { - Some(cliff_sample) - if cliff_sample.is_cliffs - && cliff_sample.spawn_rate > 0.5 - && cliff_sample.spawn_rules.cliffs => - { + Some(cliff_sample) if cliff_sample.is_cliffs && cliff_sample.spawn_rate > 0.5 => { let cliff_pos3d = Vec3::from(*cliff_pos); // Conservative range of height: [15.70, 49.33] @@ -80,7 +75,7 @@ impl<'a> BlockGen<'a> { 0.0 }, ) - } + }, _ => max_height, }, ) @@ -397,16 +392,6 @@ impl<'a> BlockGen<'a> { (None, sample.alt) }; - // Structures (like towns) - /* - let block = chunk - .structures - .town - .as_ref() - .and_then(|town| TownGen.get((town, wpos, sample, height))) - .or(block); - */ - let block = structures .iter() .find_map(|st| { @@ -473,21 +458,6 @@ impl<'a> ZCache<'a> { let min = min + structure_min; let max = (ground_max + structure_max).max(self.sample.water_level + 2.0); - // Structures - /* - let (min, max) = self - .sample - .chunk - .structures - .town - .as_ref() - .map(|town| { - let (town_min, town_max) = TownGen.get_z_limits(town, self.wpos, &self.sample); - (town_min.min(min), town_max.max(max)) - }) - .unwrap_or((min, max)); - */ - let structures_only_min_z = ground_max.max(self.sample.water_level + 2.0); (min, structures_only_min_z, max) diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs index 0c2814dada..0f285fef28 100644 --- a/world/src/block/natural.rs +++ b/world/src/block/natural.rs @@ -28,7 +28,6 @@ pub fn structure_gen<'a>( if (st_sample.tree_density as f64) < random_seed || st_sample.alt < st_sample.water_level || st_sample.spawn_rate < 0.5 - || !st_sample.spawn_rules.trees { return None; } diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 2a7f02976b..d822099bd2 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -1,7 +1,6 @@ use crate::{ all::ForestKind, block::StructureMeta, - generator::{Generator, SpawnRules, TownGen}, sim::{ local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, LocationInfo, RiverKind, SimChunk, WorldSim, @@ -1102,22 +1101,6 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { stone_col, chunk: sim_chunk, - /* - spawn_rules: sim_chunk - .structures - .town - .as_ref() - .map(|town| TownGen.spawn_rules(town, wpos)) - .unwrap_or(SpawnRules::default()) - .and(SpawnRules { - cliffs: !in_water, - trees: true, - }), - */ - spawn_rules: SpawnRules { - cliffs: !in_water, - trees: true, - }, }) } } @@ -1150,7 +1133,6 @@ pub struct ColumnSample<'a> { pub stone_col: Rgb, pub chunk: &'a SimChunk, - pub spawn_rules: SpawnRules, } #[derive(Copy, Clone)] diff --git a/world/src/generator/town/mod.rs b/world/src/generator/town/mod.rs deleted file mode 100644 index b04798dba5..0000000000 --- a/world/src/generator/town/mod.rs +++ /dev/null @@ -1,710 +0,0 @@ -mod util; -mod vol; - -use super::{Generator, SpawnRules}; -use crate::{ - block::{block_from_structure, BlockGen}, - column::ColumnSample, - util::Sampler, - CONFIG, -}; -use common::{ - assets, - terrain::{Block, BlockKind, Structure}, - vol::{ReadVol, Vox, WriteVol}, -}; -use hashbrown::HashSet; -use lazy_static::lazy_static; -use rand::prelude::*; -use std::{ops::Add, sync::Arc}; -use vek::*; - -use self::vol::{CellKind, ColumnKind, Module, TownCell, TownColumn, TownVol}; - -const CELL_SIZE: i32 = 9; -const CELL_HEIGHT: i32 = 9; - -pub struct TownGen; - -impl<'a> Sampler<'a> for TownGen { - type Index = (&'a TownState, Vec3, &'a ColumnSample<'a>, f32); - type Sample = Option; - - fn get(&self, (town, wpos, sample, height): Self::Index) -> Self::Sample { - let cell_pos = (wpos - town.center) - .map2(Vec3::new(CELL_SIZE, CELL_SIZE, CELL_HEIGHT), |e, sz| { - e.div_euclid(sz) - }) - .add(Vec3::from(town.vol.size() / 2)); - let inner_pos = (wpos - town.center) - .map2(Vec3::new(CELL_SIZE, CELL_SIZE, CELL_HEIGHT), |e, sz| { - e.rem_euclid(sz) - }); - - let cell = town.vol.get(cell_pos).ok()?; - - match (modules_from_kind(&cell.kind), &cell.module) { - (Some(module_list), Some(module)) => { - let transform = [ - (Vec2::new(0, 0), Vec2::unit_x(), Vec2::unit_y()), - (Vec2::new(0, 1), -Vec2::unit_y(), Vec2::unit_x()), - (Vec2::new(1, 1), -Vec2::unit_x(), -Vec2::unit_y()), - (Vec2::new(1, 0), Vec2::unit_y(), -Vec2::unit_x()), - ]; - - module_list[module.vol_idx] - .0 - .get( - Vec3::from( - transform[module.dir].0 * (CELL_SIZE - 1) - + transform[module.dir].1 * inner_pos.x - + transform[module.dir].2 * inner_pos.y, - ) + Vec3::unit_z() * inner_pos.z, - ) - .ok() - .and_then(|sb| { - block_from_structure(*sb, BlockKind::Normal, wpos, wpos.into(), 0, sample) - }) - }, - _ => match cell.kind { - CellKind::Empty => None, - CellKind::Park => None, - CellKind::Rock => Some(Block::new(BlockKind::Normal, Rgb::broadcast(100))), - CellKind::Wall => Some(Block::new(BlockKind::Normal, Rgb::broadcast(175))), - CellKind::Well => Some(Block::new(BlockKind::Normal, Rgb::broadcast(0))), - CellKind::Road => { - if (wpos.z as f32) < height - 1.0 { - Some(Block::new( - BlockKind::Normal, - Lerp::lerp( - Rgb::new(150.0, 140.0, 50.0), - Rgb::new(100.0, 95.0, 30.0), - sample.marble_small, - ) - .map(|e| e as u8), - )) - } else { - Some(Block::empty()) - } - }, - CellKind::House(idx) => Some(Block::new(BlockKind::Normal, town.houses[idx].color)), - }, - } - } -} - -impl<'a> Generator<'a, TownState> for TownGen { - fn get_z_limits( - &self, - _town: &'a TownState, - _wpos: Vec2, - sample: &ColumnSample, - ) -> (f32, f32) { - (sample.alt - 32.0, sample.alt + 75.0) - } - - fn spawn_rules(&self, town: &'a TownState, wpos: Vec2) -> SpawnRules { - SpawnRules { - trees: wpos.distance_squared(town.center.into()) > (town.radius + 32).pow(2), - cliffs: false, - } - } -} - -struct House { - color: Rgb, -} - -pub struct TownState { - center: Vec3, - radius: i32, - vol: TownVol, - houses: Vec, -} - -impl TownState { - pub fn generate(center: Vec2, gen: &mut BlockGen, rng: &mut impl Rng) -> Option { - let radius = rng.gen_range(18, 20) * 9; - let size = Vec2::broadcast(radius * 2 / 9 - 2); - - let center_col = BlockGen::sample_column(&gen.column_gen, &mut gen.column_cache, center); - - if center_col.map(|sample| sample.chaos).unwrap_or(0.0) > 0.35 - || center_col.map(|sample| sample.alt).unwrap_or(0.0) < CONFIG.sea_level + 10.0 - { - return None; - } - - let alt = center_col.map(|sample| sample.alt).unwrap_or(0.0) as i32; - - let mut vol = TownVol::generate_from( - size, - |pos| { - let wpos = center + (pos - size / 2) * CELL_SIZE + CELL_SIZE / 2; - let rel_alt = BlockGen::sample_column(&gen.column_gen, &mut gen.column_cache, wpos) - .map(|sample| sample.alt) - .unwrap_or(0.0) as i32 - + CELL_HEIGHT / 2 - - alt; - - let col = TownColumn { - ground: rel_alt.div_euclid(CELL_HEIGHT), - kind: None, - }; - - (col.ground, col) - }, - |(col, pos)| { - if pos.z >= col.ground { - TownCell::empty() - } else { - TownCell::from(CellKind::Rock) - } - }, - ); - - // Generation passes - vol.setup(rng); - vol.gen_roads(rng, 30); - vol.gen_parks(rng, 3); - vol.emplace_columns(); - let houses = vol.gen_houses(rng, 50); - vol.gen_wells(rng, 5); - vol.gen_walls(rng); - vol.resolve_modules(rng); - vol.cull_unused(); - - Some(Self { - center: Vec3::new(center.x, center.y, alt), - radius, - vol, - houses, - }) - } - - pub fn center(&self) -> Vec3 { self.center } - - pub fn radius(&self) -> i32 { self.radius } -} - -impl TownVol { - fn floodfill( - &self, - limit: Option, - mut opens: HashSet>, - mut f: impl FnMut(Vec2, &TownColumn) -> bool, - ) -> HashSet> { - let mut closed = HashSet::new(); - - while opens.len() > 0 { - let mut new_opens = HashSet::new(); - - 'search: for open in opens.iter() { - for i in -1..2 { - for j in -1..2 { - let pos = *open + Vec2::new(i, j); - - if let Some(col) = self.col(pos) { - if !closed.contains(&pos) && !opens.contains(&pos) && f(pos, col) { - match limit { - Some(limit) - if limit - <= new_opens.len() + closed.len() + opens.len() => - { - break 'search; - } - _ => { - new_opens.insert(pos); - }, - } - } - } - } - } - } - - closed = closed.union(&opens).copied().collect(); - opens = new_opens; - } - - closed - } - - fn setup(&mut self, rng: &mut impl Rng) { - // Place a single road tile at first - let root_road = self - .size() - .map(|sz| (sz / 8) * 2 + rng.gen_range(0, sz / 4) * 2); - self.set_col_kind(root_road, Some(ColumnKind::Road)); - } - - fn gen_roads(&mut self, rng: &mut impl Rng, n: usize) { - const ATTEMPTS: usize = 5; - - let mut junctions = HashSet::new(); - junctions.insert(self.choose_column(rng, |_, col| col.is_road()).unwrap()); - - for _road in 0..n { - for _ in 0..ATTEMPTS { - let start = *junctions.iter().choose(rng).unwrap(); - //let start = self.choose_column(rng, |pos, col| pos.map(|e| e % 2 == - // 0).reduce_and() && col.is_road()).unwrap(); - let dir = util::gen_dir(rng); - - // If the direction we want to paint a path in is obstructed, abandon this - // attempt - if self - .col(start + dir) - .map(|col| !col.is_empty()) - .unwrap_or(true) - { - continue; - } - - // How long should this road be? - let len = rng.gen_range(1, 10) * 2 + 1; - - // Paint the road until we hit an obstacle - let success = (1..len) - .map(|i| start + dir * i) - .try_for_each(|pos| { - if self.col(pos).map(|col| col.is_empty()).unwrap_or(false) { - self.set_col_kind(pos, Some(ColumnKind::Road)); - Ok(()) - } else { - junctions.insert(pos); - Err(()) - } - }) - .is_ok(); - - if success { - junctions.insert(start + dir * (len - 1)); - } - - break; - } - } - } - - fn gen_parks(&mut self, rng: &mut impl Rng, n: usize) { - const ATTEMPTS: usize = 5; - - for _ in 0..n { - for _ in 0..ATTEMPTS { - let start = self - .choose_column(rng, |pos, col| { - col.is_empty() - && (0..4).any(|i| { - self.col(pos + util::dir(i)) - .map(|col| col.is_road()) - .unwrap_or(false) - }) - }) - .unwrap(); - - let park = self.floodfill(Some(16), [start].iter().copied().collect(), |_, col| { - col.is_empty() - }); - - if park.len() < 4 { - continue; - } - - for cell in park { - self.set_col_kind(cell, Some(ColumnKind::Internal)); - let col = self.col(cell).unwrap(); - let ground = col.ground; - let _ = self.set(Vec3::new(cell.x, cell.y, ground), CellKind::Park.into()); - } - - break; - } - } - } - - fn gen_walls(&mut self, _rng: &mut impl Rng) { - let mut outer = HashSet::new(); - for i in 0..self.size().x { - outer.insert(Vec2::new(i, 0)); - outer.insert(Vec2::new(i, self.size().y - 1)); - } - for j in 0..self.size().y { - outer.insert(Vec2::new(0, j)); - outer.insert(Vec2::new(self.size().x - 1, j)); - } - - let outer = self.floodfill(None, outer, |_, col| col.is_empty()); - - let mut walls = HashSet::new(); - let _inner = self.floodfill( - None, - [self.size() / 2].iter().copied().collect(), - |pos, _| { - if outer.contains(&pos) { - walls.insert(pos); - false - } else { - true - } - }, - ); - - while let Some(wall) = walls - .iter() - .filter(|pos| { - let lateral_count = (0..4) - .filter(|i| walls.contains(&(**pos + util::dir(*i)))) - .count(); - let max_quadrant_count = (0..4) - .map(|i| { - let units = util::unit(i); - (0..2) - .map(|i| (0..2).map(move |j| (i, j))) - .flatten() - .filter(|(i, j)| walls.contains(&(**pos + units.0 * *i + units.1 * *j))) - .count() - }) - .max() - .unwrap(); - - lateral_count < 2 || (lateral_count == 2 && max_quadrant_count == 4) - }) - .next() - { - let wall = *wall; - walls.remove(&wall); - } - - for wall in walls.iter() { - let col = self.col(*wall).unwrap(); - let ground = col.ground; - for z in -1..3 { - let _ = self.set(Vec3::new(wall.x, wall.y, ground + z), CellKind::Wall.into()); - } - } - } - - fn emplace_columns(&mut self) { - for i in 0..self.size().x { - for j in 0..self.size().y { - let col = self.col(Vec2::new(i, j)).unwrap(); - let ground = col.ground; - - match col.kind { - None => {}, - Some(ColumnKind::Internal) => {}, - //Some(ColumnKind::External) => {} - Some(ColumnKind::Road) => { - for z in -1..2 { - let _ = self.set(Vec3::new(i, j, ground + z), CellKind::Road.into()); - } - }, - } - } - } - } - - fn gen_wells(&mut self, rng: &mut impl Rng, n: usize) { - for _ in 0..n { - if let Some(cell) = self.choose_cell(rng, |_, cell| { - if let CellKind::Park = cell.kind { - true - } else { - false - } - }) { - let _ = self.set(cell, CellKind::Well.into()); - } - } - } - - fn gen_houses(&mut self, rng: &mut impl Rng, n: usize) -> Vec { - const ATTEMPTS: usize = 10; - - let mut houses = Vec::new(); - for _ in 0..n { - for _ in 0..ATTEMPTS { - let entrance = { - let start_col = self.choose_column(rng, |_, col| col.is_road()).unwrap(); - let start = Vec3::new( - start_col.x, - start_col.y, - self.col(start_col).unwrap().ground, - ); - let dir = Vec3::from(util::gen_dir(rng)); - - if self - .get(start + dir) - .map(|col| !col.is_empty()) - .unwrap_or(true) - || self - .get(start + dir - Vec3::unit_z()) - .map(|col| !col.is_foundation()) - .unwrap_or(true) - { - continue; - } else { - start + dir - } - }; - - let mut cells = HashSet::new(); - - let mut energy = 2300; - while energy > 0 { - energy -= 1; - - let parent = *cells.iter().choose(rng).unwrap_or(&entrance); - let dir = util::UNITS_3D - .choose_weighted(rng, |pos| 1 + pos.z.max(0)) - .unwrap(); - - if self - .get(parent + dir) - .map(|cell| cell.is_empty()) - .unwrap_or(false) - && self - .get(parent + dir - Vec3::unit_z()) - .map(|cell| { - cell.is_foundation() - || cells.contains(&(parent + dir - Vec3::unit_z())) - }) - .unwrap_or(false) - && parent.z + dir.z <= entrance.z + 2 - // Maximum house height - { - cells.insert(parent + dir); - energy -= 10; - } - } - - // Remove cells that are too isolated - loop { - let cells_copy = cells.clone(); - - let mut any_removed = false; - cells.retain(|pos| { - let neighbour_count = (0..6) - .filter(|i| { - let neighbour = pos + util::dir_3d(*i); - cells_copy.contains(&neighbour) - }) - .count(); - - if neighbour_count < 3 { - any_removed = true; - false - } else { - true - } - }); - - if !any_removed { - break; - } - } - - // Get rid of houses that are too small - if cells.len() < 6 { - continue; - } - - for cell in cells { - let _ = self.set(cell, CellKind::House(houses.len()).into()); - self.set_col_kind(Vec2::from(cell), Some(ColumnKind::Internal)); - } - - houses.push(House { - color: Rgb::new(rng.gen(), rng.gen(), rng.gen()), - }); - } - } - - houses - } - - fn cull_unused(&mut self) { - for x in 0..self.size().x { - for y in 0..self.size().y { - for z in self.col_range(Vec2::new(x, y)).unwrap().rev() { - let pos = Vec3::new(x, y, z); - - // Remove foundations that don't have anything on top of them - if self.get(pos).unwrap().is_foundation() - && self - .get(pos + Vec3::unit_z()) - .map(TownCell::is_space) - .unwrap_or(true) - { - let _ = self.set(pos, TownCell::empty()); - } - } - } - } - } - - fn resolve_modules(&mut self, rng: &mut impl Rng) { - fn classify(cell: &TownCell, this_cell: &TownCell) -> ModuleKind { - match (&cell.kind, &this_cell.kind) { - (CellKind::House(a), CellKind::House(b)) if a == b => ModuleKind::This, - (CellKind::Wall, CellKind::Wall) => ModuleKind::This, - _ => ModuleKind::That, - } - } - - for x in 0..self.size().x { - for y in 0..self.size().y { - for z in self.col_range(Vec2::new(x, y)).unwrap() { - let pos = Vec3::new(x, y, z); - let this_cell = if let Ok(this_cell) = self.get(pos) { - this_cell - } else { - continue; - }; - - let mut signature = [ModuleKind::That; 6]; - for i in 0..6 { - signature[i] = self - .get(pos + util::dir_3d(i)) - .map(|cell| classify(cell, this_cell)) - .unwrap_or(ModuleKind::That); - } - - let module_list = if let Some(modules) = modules_from_kind(&this_cell.kind) { - modules - } else { - continue; - }; - - let module = module_list - .iter() - .enumerate() - .filter_map(|(i, module)| { - let perms = [[0, 1, 2, 3], [3, 0, 1, 2], [2, 3, 0, 1], [1, 2, 3, 0]]; - - let mut rotated_signature = [ModuleKind::That; 6]; - for (dir, perm) in perms.iter().enumerate() { - rotated_signature[perm[0]] = signature[0]; - rotated_signature[perm[1]] = signature[1]; - rotated_signature[perm[2]] = signature[2]; - rotated_signature[perm[3]] = signature[3]; - rotated_signature[4] = signature[4]; - rotated_signature[5] = signature[5]; - - if &module.1[0..6] == &rotated_signature[0..6] { - return Some(Module { vol_idx: i, dir }); - } - } - - None - }) - .choose(rng); - - if let Some(module) = module { - let kind = this_cell.kind.clone(); - let _ = self.set(pos, TownCell { - kind, - module: Some(module), - }); - } - } - } - } - } -} - -#[derive(Copy, Clone, PartialEq)] -pub enum ModuleKind { - This, - That, -} - -fn module(name: &str, sig: [ModuleKind; 6]) -> (Arc, [ModuleKind; 6]) { - ( - assets::load(&format!("world.module.{}", name)).unwrap(), - sig, - ) -} - -fn modules_from_kind(kind: &CellKind) -> Option<&'static [(Arc, [ModuleKind; 6])]> { - match kind { - CellKind::House(_) => Some(&HOUSE_MODULES), - CellKind::Wall => Some(&WALL_MODULES), - CellKind::Well => Some(&WELL_MODULES), - _ => None, - } -} - -lazy_static! { - pub static ref HOUSE_MODULES: Vec<(Arc, [ModuleKind; 6])> = { - use ModuleKind::*; - vec![ - module("human.floor_ground", [This, This, This, This, This, That]), - module("human.stair_ground", [This, This, This, This, This, That]), - module("human.corner_ground", [This, This, That, That, This, That]), - module("human.window_corner_ground", [ - This, This, That, That, This, That, - ]), - module("human.wall_ground", [This, This, This, That, This, That]), - module("human.door_ground", [This, This, This, That, This, That]), - module("human.window_ground", [This, This, This, That, This, That]), - module("human.floor_roof", [This, This, This, This, That, This]), - module("human.corner_roof", [This, This, That, That, That, This]), - module("human.chimney_roof", [This, This, That, That, That, This]), - module("human.wall_roof", [This, This, This, That, That, This]), - module("human.floor_upstairs", [This, This, This, This, This, This]), - module("human.balcony_upstairs", [ - This, This, This, This, This, This, - ]), - module("human.corner_upstairs", [ - This, This, That, That, This, This, - ]), - module("human.window_corner_upstairs", [ - This, This, That, That, This, This, - ]), - module("human.wall_upstairs", [This, This, This, That, This, This]), - module("human.window_upstairs", [ - This, This, This, That, This, This, - ]), - ] - }; - pub static ref WALL_MODULES: Vec<(Arc, [ModuleKind; 6])> = { - use ModuleKind::*; - vec![ - module("wall.edge_ground", [This, That, This, That, This, That]), - module("wall.edge_mid", [This, That, This, That, This, This]), - module("wall.edge_top", [This, That, This, That, That, This]), - module("wall.corner_ground", [This, This, That, That, This, That]), - module("wall.corner_mid", [This, This, That, That, This, This]), - module("wall.corner_top", [This, This, That, That, That, This]), - module("wall.end_top", [That, This, That, That, That, This]), - module("wall.single_top", [That, That, That, That, That, This]), - ] - }; - pub static ref WELL_MODULES: Vec<(Arc, [ModuleKind; 6])> = { - use ModuleKind::*; - vec![module("misc.well", [That; 6])] - }; -} - -/* -// TODO -struct ModuleModel { - near: u64, - mask: u64, - vol: Arc, -} - -#[derive(Copy, Clone)] -pub enum NearKind { - This, - That, -} - -impl ModuleModel { - pub fn generate_list(_details: &[(&str, &[([i32; 3], NearKind)])]) -> Vec { - unimplemented!() - } -} -*/ diff --git a/world/src/generator/town/util.rs b/world/src/generator/town/util.rs deleted file mode 100644 index 46fde3926f..0000000000 --- a/world/src/generator/town/util.rs +++ /dev/null @@ -1,36 +0,0 @@ -use rand::prelude::*; -use vek::*; - -pub const UNITS: [Vec2; 4] = [ - Vec2 { x: 1, y: 0 }, - Vec2 { x: 0, y: 1 }, - Vec2 { x: -1, y: 0 }, - Vec2 { x: 0, y: -1 }, -]; - -pub fn dir(i: usize) -> Vec2 { UNITS[i % 4] } - -pub fn unit(i: usize) -> (Vec2, Vec2) { (UNITS[i % 4], UNITS[(i + 1) % 4]) } - -// unused -//pub fn gen_unit(rng: &mut impl Rng) -> (Vec2, Vec2) { -// unit(rng.gen_range(0, 4)) -//} - -pub fn gen_dir(rng: &mut impl Rng) -> Vec2 { UNITS[rng.gen_range(0, 4)] } - -pub const UNITS_3D: [Vec3; 6] = [ - Vec3 { x: 1, y: 0, z: 0 }, - Vec3 { x: 0, y: 1, z: 0 }, - Vec3 { x: -1, y: 0, z: 0 }, - Vec3 { x: 0, y: -1, z: 0 }, - Vec3 { x: 0, y: 0, z: 1 }, - Vec3 { x: 0, y: 0, z: -1 }, -]; - -pub fn dir_3d(i: usize) -> Vec3 { UNITS_3D[i % 6] } - -// unused -//pub fn gen_dir_3d(rng: &mut impl Rng) -> Vec3 { -// UNITS_3D[rng.gen_range(0, 6)] -//} diff --git a/world/src/generator/town/vol.rs b/world/src/generator/town/vol.rs deleted file mode 100644 index 1d6d041ec5..0000000000 --- a/world/src/generator/town/vol.rs +++ /dev/null @@ -1,215 +0,0 @@ -use crate::util::Grid; -use common::vol::{BaseVol, ReadVol, Vox, WriteVol}; -use rand::prelude::*; -use std::ops::Range; -use vek::*; - -#[derive(Clone)] -pub enum ColumnKind { - Road, - //Wall, - Internal, - //External, // Outside the boundary wall -} - -#[derive(Clone, Default)] -pub struct TownColumn { - pub ground: i32, - pub kind: Option, -} - -impl TownColumn { - pub fn is_empty(&self) -> bool { self.kind.is_none() } - - pub fn is_road(&self) -> bool { - self.kind - .as_ref() - .map(|kind| match kind { - ColumnKind::Road => true, - _ => false, - }) - .unwrap_or(false) - } -} - -#[derive(Clone, PartialEq)] -pub struct Module { - pub vol_idx: usize, - pub dir: usize, -} - -#[derive(Clone, PartialEq)] -pub enum CellKind { - Empty, - Park, - Rock, - Road, - Wall, - House(usize), - Well, -} - -#[derive(Clone, PartialEq)] -pub struct TownCell { - pub kind: CellKind, - pub module: Option, -} - -impl TownCell { - pub fn is_space(&self) -> bool { - match self.kind { - CellKind::Empty => true, - CellKind::Park => true, - CellKind::Road => true, - _ => false, - } - } - - pub fn is_foundation(&self) -> bool { - match self.kind { - CellKind::Rock => true, - _ => false, - } - } -} - -impl Vox for TownCell { - fn empty() -> Self { - Self { - kind: CellKind::Empty, - module: None, - } - } - - fn is_empty(&self) -> bool { - match self.kind { - CellKind::Empty => true, - _ => false, - } - } -} - -impl From for TownCell { - fn from(kind: CellKind) -> Self { Self { kind, module: None } } -} - -#[derive(Debug)] -pub enum TownError { - OutOfBounds, -} - -const HEIGHT: usize = 24; -const UNDERGROUND_DEPTH: i32 = 5; - -type GridItem = (i32, TownColumn, Vec); - -pub struct TownVol { - grid: Grid, -} - -impl TownVol { - pub fn generate_from( - size: Vec2, - mut f: impl FnMut(Vec2) -> (i32, TownColumn), - mut g: impl FnMut((&TownColumn, Vec3)) -> TownCell, - ) -> Self { - let mut this = Self { - grid: Grid::new( - (0, TownColumn::default(), vec![TownCell::empty(); HEIGHT]), - size, - ), - }; - - for (pos, (base, col, cells)) in this.grid.iter_mut() { - let column = f(pos); - *base = column.0; - *col = column.1; - for z in 0..HEIGHT { - cells[z] = g(( - col, - Vec3::new(pos.x, pos.y, *base - UNDERGROUND_DEPTH + z as i32), - )); - } - } - - this - } - - pub fn size(&self) -> Vec2 { self.grid.size() } - - pub fn set_col_kind(&mut self, pos: Vec2, kind: Option) { - self.grid.get_mut(pos).map(|col| col.1.kind = kind); - } - - pub fn col(&self, pos: Vec2) -> Option<&TownColumn> { - self.grid.get(pos).map(|col| &col.1) - } - - pub fn col_range(&self, pos: Vec2) -> Option> { - self.grid.get(pos).map(|col| { - let lower = col.0 - UNDERGROUND_DEPTH; - lower..lower + HEIGHT as i32 - }) - } - - pub fn choose_column( - &self, - rng: &mut impl Rng, - mut f: impl FnMut(Vec2, &TownColumn) -> bool, - ) -> Option> { - self.grid - .iter() - .filter(|(pos, col)| f(*pos, &col.1)) - .choose(rng) - .map(|(pos, _)| pos) - } - - pub fn choose_cell( - &self, - rng: &mut impl Rng, - mut f: impl FnMut(Vec3, &TownCell) -> bool, - ) -> Option> { - self.grid - .iter() - .map(|(pos, (base, _, cells))| { - cells.iter().enumerate().map(move |(i, cell)| { - ( - Vec3::new(pos.x, pos.y, *base - UNDERGROUND_DEPTH + i as i32), - cell, - ) - }) - }) - .flatten() - .filter(|(pos, cell)| f(*pos, *cell)) - .choose(rng) - .map(|(pos, _)| pos) - } -} - -impl BaseVol for TownVol { - type Error = TownError; - type Vox = TownCell; -} - -impl ReadVol for TownVol { - fn get(&self, pos: Vec3) -> Result<&Self::Vox, Self::Error> { - match self.grid.get(Vec2::from(pos)) { - Some((base, _, cells)) => cells - .get((pos.z + UNDERGROUND_DEPTH - *base) as usize) - .ok_or(TownError::OutOfBounds), - None => Err(TownError::OutOfBounds), - } - } -} - -impl WriteVol for TownVol { - fn set(&mut self, pos: Vec3, vox: Self::Vox) -> Result<(), Self::Error> { - match self.grid.get_mut(Vec2::from(pos)) { - Some((base, _, cells)) => cells - .get_mut((pos.z + UNDERGROUND_DEPTH - *base) as usize) - .map(|cell| *cell = vox) - .ok_or(TownError::OutOfBounds), - None => Err(TownError::OutOfBounds), - } - } -} diff --git a/world/src/lib.rs b/world/src/lib.rs index d69a3bce6f..00e627bd46 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -6,8 +6,8 @@ mod all; mod block; mod column; pub mod config; -pub mod generator; pub mod sim; +pub mod site; pub mod util; // Reexports diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index c4423b46ab..16552bd397 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -26,7 +26,7 @@ use crate::{ all::ForestKind, block::BlockGen, column::ColumnGen, - generator::{Settlement, Site}, + site::{Settlement, Site}, util::{seed_expan, FastNoise, RandomField, Sampler, StructureGen2d}, CONFIG, }; diff --git a/world/src/generator/mod.rs b/world/src/site/mod.rs similarity index 54% rename from world/src/generator/mod.rs rename to world/src/site/mod.rs index 66a6aea4fc..e42016b9ee 100644 --- a/world/src/generator/mod.rs +++ b/world/src/site/mod.rs @@ -1,11 +1,7 @@ -pub mod settlement; -mod town; +mod settlement; // Reexports -pub use self::{ - settlement::Settlement, - town::{TownGen, TownState}, -}; +pub use self::settlement::Settlement; use crate::{ block::ZCache, @@ -52,34 +48,3 @@ impl Site { impl From for Site { fn from(settlement: Settlement) -> Self { Site::Settlement(Arc::new(settlement)) } } - -#[derive(Copy, Clone, Debug)] -pub struct SpawnRules { - pub trees: bool, - pub cliffs: bool, -} - -impl Default for SpawnRules { - fn default() -> Self { - Self { - trees: true, - cliffs: true, - } - } -} - -impl SpawnRules { - pub fn and(self, other: Self) -> Self { - Self { - trees: self.trees && other.trees, - cliffs: self.cliffs && other.cliffs, - } - } -} - -pub trait Generator<'a, T: 'a>: - Sampler<'a, Index = (&'a T, Vec3, &'a ColumnSample<'a>, f32), Sample = Option> -{ - fn get_z_limits(&self, state: &'a T, wpos: Vec2, sample: &ColumnSample) -> (f32, f32); - fn spawn_rules(&self, town: &'a TownState, wpos: Vec2) -> SpawnRules; -} diff --git a/world/src/generator/settlement/mod.rs b/world/src/site/settlement/mod.rs similarity index 100% rename from world/src/generator/settlement/mod.rs rename to world/src/site/settlement/mod.rs