Added dungeon entrances

This commit is contained in:
Joshua Barretto 2020-04-28 19:09:45 +01:00 committed by Pfauenauge90
parent 00f0a011de
commit d0b1c9eb6f
15 changed files with 169 additions and 64 deletions

View File

@ -0,0 +1,45 @@
(
[
(
specifier: "world.structure.dungeon.jungle_temple.entrance.1",
center: (50, 40, 10)
),
(
specifier: "world.structure.dungeon.pillar_entrance.round.1",
center: (21, 17, 28)
),
(
specifier: "world.structure.dungeon.pillar_entrance.round.2",
center: (20, 28, 15)
),
(
specifier: "world.structure.dungeon.pillar_entrance.1",
center: (18, 16, 17)
),
(
specifier: "world.structure.dungeon.pillar_entrance.2",
center: (18, 16, 17)
),
(
specifier: "world.structure.dungeon.pillar_entrance.3",
center: (18, 16, 17)
),
(
specifier: "world.structure.dungeon.pillar_entrance.4",
center: (18, 16, 17)
),
(
specifier: "world.structure.dungeon.pillar_entrance.5",
center: (18, 16, 17)
),
(
specifier: "world.structure.dungeon.pillar_entrance.6",
center: (18, 16, 17)
),
// Pfau's dungeon entrance
//(
// specifier: "world.structure.dungeon.entrance.1",
// center: (13, 11, 12)
//),
]
)

BIN
assets/world/structure/dungeon/jungle_temple/entrance/1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/3.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/4.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/5.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/6.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/round/1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/structure/dungeon/pillar_entrance/round/2.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -5,12 +5,13 @@ use crate::{
volumes::dyna::{Dyna, DynaError},
};
use dot_vox::DotVoxData;
use std::{fs::File, io::BufReader};
use std::{fs::File, io::BufReader, sync::Arc};
use vek::*;
#[derive(Copy, Clone, PartialEq)]
pub enum StructureBlock {
None,
Grass,
TemperateLeaves,
PineLeaves,
Acacia,
@ -50,6 +51,21 @@ pub struct Structure {
}
impl Structure {
pub fn load_group(specifier: &str) -> Vec<Arc<Structure>> {
let spec = assets::load::<StructuresSpec>(&["world.manifests.", specifier].concat());
return spec
.unwrap()
.0
.iter()
.map(|sp| {
assets::load_map(&sp.specifier[..], |s: Structure| {
s.with_center(Vec3::from(sp.center))
})
.unwrap()
})
.collect();
}
pub fn with_center(mut self, center: Vec3<i32>) -> Self {
self.center = center;
self
@ -113,6 +129,7 @@ impl Asset for Structure {
5 => StructureBlock::Mangrove,
6 => StructureBlock::GreenSludge,
7 => StructureBlock::Fruit,
8 => StructureBlock::Grass,
9 => StructureBlock::Liana,
10 => StructureBlock::Chest,
11 => StructureBlock::Coconut,
@ -150,3 +167,19 @@ impl Asset for Structure {
}
}
}
#[derive(Deserialize)]
struct StructureSpec {
specifier: String,
center: [i32; 3],
}
#[derive(Deserialize)]
struct StructuresSpec(Vec<StructureSpec>);
impl Asset for StructuresSpec {
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
}
}

View File

@ -538,7 +538,6 @@ impl StructureInfo {
.and_then(|b| {
block_from_structure(
*b,
volume.default_kind(),
block_pos,
self.pos.into(),
self.seed,
@ -552,11 +551,10 @@ impl StructureInfo {
pub fn block_from_structure(
sblock: StructureBlock,
default_kind: BlockKind,
pos: Vec3<i32>,
structure_pos: Vec2<i32>,
structure_seed: u32,
_sample: &ColumnSample,
sample: &ColumnSample,
) -> Option<Block> {
let field = RandomField::new(structure_seed + 0);
@ -565,6 +563,7 @@ pub fn block_from_structure(
match sblock {
StructureBlock::None => None,
StructureBlock::Grass => Some(Block::new(BlockKind::Normal, sample.surface_color.map(|e| (e * 255.0) as u8))),
StructureBlock::TemperateLeaves => Some(Block::new(
BlockKind::Leaves,
Lerp::lerp(
@ -639,7 +638,7 @@ pub fn block_from_structure(
)),
StructureBlock::Hollow => Some(Block::empty()),
StructureBlock::Normal(color) => {
Some(Block::new(default_kind, color)).filter(|block| !block.is_empty())
Some(Block::new(BlockKind::Normal, color)).filter(|block| !block.is_empty())
},
}
}

View File

@ -5,11 +5,9 @@ use crate::{
util::{RandomPerm, Sampler, SmallCache, UnitChooser},
CONFIG,
};
use common::{assets, assets::Asset, terrain::Structure};
use common::terrain::Structure;
use lazy_static::lazy_static;
use ron;
use serde::Deserialize;
use std::{fs::File, io::BufReader, sync::Arc, u32};
use std::{sync::Arc, u32};
use vek::*;
static VOLUME_RAND: RandomPerm = RandomPerm::new(0xDB21C052);
@ -76,47 +74,16 @@ pub fn structure_gen<'a>(
})
}
#[derive(Deserialize)]
struct StructureSpec {
specifier: String,
center: [i32; 3],
}
#[derive(Deserialize)]
struct StructuresSpec(Vec<StructureSpec>);
impl Asset for StructuresSpec {
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
}
}
fn load_structures(specifier: &str) -> Vec<Arc<Structure>> {
let spec = assets::load::<StructuresSpec>(&["world.manifests.", specifier].concat());
return spec
.unwrap()
.0
.iter()
.map(|sp| {
assets::load_map(&sp.specifier[..], |s: Structure| {
s.with_center(Vec3::from(sp.center))
})
.unwrap()
})
.collect();
}
lazy_static! {
pub static ref OAKS: Vec<Arc<Structure>> = load_structures("oaks");
pub static ref OAK_STUMPS: Vec<Arc<Structure>> = load_structures("oak_stumps");
pub static ref PINES: Vec<Arc<Structure>> = load_structures("pines");
pub static ref PALMS: Vec<Arc<Structure>> = load_structures("palms");
pub static ref SNOW_PINES: Vec<Arc<Structure>> = load_structures("snow_pines");
pub static ref ACACIAS: Vec<Arc<Structure>> = load_structures("acacias");
pub static ref FRUIT_TREES: Vec<Arc<Structure>> = load_structures("fruit_trees");
pub static ref BIRCHES: Vec<Arc<Structure>> = load_structures("birch");
pub static ref MANGROVE_TREES: Vec<Arc<Structure>> = load_structures("mangrove_trees");
pub static ref QUIRKY: Vec<Arc<Structure>> = load_structures("quirky");
pub static ref QUIRKY_DRY: Vec<Arc<Structure>> = load_structures("quirky_dry");
pub static ref OAKS: Vec<Arc<Structure>> = Structure::load_group("oaks");
pub static ref OAK_STUMPS: Vec<Arc<Structure>> = Structure::load_group("oak_stumps");
pub static ref PINES: Vec<Arc<Structure>> = Structure::load_group("pines");
pub static ref PALMS: Vec<Arc<Structure>> = Structure::load_group("palms");
pub static ref SNOW_PINES: Vec<Arc<Structure>> = Structure::load_group("snow_pines");
pub static ref ACACIAS: Vec<Arc<Structure>> = Structure::load_group("acacias");
pub static ref FRUIT_TREES: Vec<Arc<Structure>> = Structure::load_group("fruit_trees");
pub static ref BIRCHES: Vec<Arc<Structure>> = Structure::load_group("birch");
pub static ref MANGROVE_TREES: Vec<Arc<Structure>> = Structure::load_group("mangrove_trees");
pub static ref QUIRKY: Vec<Arc<Structure>> = Structure::load_group("quirky");
pub static ref QUIRKY_DRY: Vec<Arc<Structure>> = Structure::load_group("quirky_dry");
}

View File

@ -95,16 +95,16 @@ impl Civs {
// Flatten ground around sites
for site in this.sites.iter() {
if let SiteKind::Settlement = &site.kind {
} else {
continue;
}
let radius = 48i32;
let wpos = site.center * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32);
// Flatten ground
let flatten_radius = 10.0;
let flatten_radius = match &site.kind {
SiteKind::Settlement => 10.0,
SiteKind::Dungeon => 2.0,
};
if let Some(center_alt) = ctx.sim.get_alt_approx(wpos) {
for offs in Spiral2d::new().take(radius.pow(2) as usize) {
let center_alt = center_alt
@ -335,7 +335,7 @@ impl Civs {
let site = self.sites.insert(site_fn(place));
// Find neighbors
const MAX_NEIGHBOR_DISTANCE: f32 = 250.0;
const MAX_NEIGHBOR_DISTANCE: f32 = 500.0;
let mut nearby = self
.sites
.iter_ids()

View File

@ -4,6 +4,7 @@ use crate::{
sim::WorldSim,
site::BlockMask,
util::{attempt, Grid, RandomField, Sampler, CARDINALS, DIRS},
block::block_from_structure,
};
use common::{
assets,
@ -11,11 +12,12 @@ use common::{
comp,
generation::{ChunkSupplement, EntityInfo},
store::{Id, Store},
terrain::{Block, BlockKind, TerrainChunkSize},
terrain::{Block, BlockKind, TerrainChunkSize, Structure},
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, Vox, WriteVol},
};
use lazy_static::lazy_static;
use rand::prelude::*;
use std::f32;
use std::{sync::Arc, f32};
use vek::*;
impl WorldSim {
@ -34,6 +36,7 @@ impl WorldSim {
pub struct Dungeon {
origin: Vec2<i32>,
alt: i32,
seed: u32,
#[allow(dead_code)]
noise: RandomField,
floors: Vec<Floor>,
@ -44,6 +47,8 @@ pub struct GenCtx<'a, R: Rng> {
rng: &'a mut R,
}
const ALT_OFFSET: i32 = 2;
impl Dungeon {
pub fn generate(wpos: Vec2<i32>, sim: Option<&WorldSim>, rng: &mut impl Rng) -> Self {
let mut ctx = GenCtx { sim, rng };
@ -54,6 +59,7 @@ impl Dungeon {
.and_then(|sim| sim.get_alt_approx(wpos))
.unwrap_or(0.0) as i32
+ 6,
seed: ctx.rng.gen(),
noise: RandomField::new(ctx.rng.gen()),
floors: (0..6)
.scan(Vec2::zero(), |stair_tile, level| {
@ -71,8 +77,9 @@ impl Dungeon {
pub fn radius(&self) -> f32 { 1200.0 }
pub fn spawn_rules(&self, _wpos: Vec2<i32>) -> SpawnRules {
pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
SpawnRules {
trees: wpos.distance_squared(self.origin) > 64i32.pow(2),
..SpawnRules::default()
}
}
@ -80,9 +87,15 @@ impl Dungeon {
pub fn apply_to<'a>(
&'a self,
wpos2d: Vec2<i32>,
_get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
) {
lazy_static! {
pub static ref ENTRANCES: Vec<Arc<Structure>> = Structure::load_group("dungeon_entrances");
}
let entrance = &ENTRANCES[self.seed as usize % ENTRANCES.len()];
for y in 0..vol.size_xy().y as i32 {
for x in 0..vol.size_xy().x as i32 {
let offs = Vec2::new(x, y);
@ -90,7 +103,28 @@ impl Dungeon {
let wpos2d = wpos2d + offs;
let rpos = wpos2d - self.origin;
let mut z = self.alt;
// Apply the dungeon entrance
let col_sample = if let Some(col) = get_column(offs) {
col
} else {
continue
};
for z in entrance.get_bounds().min.z..entrance.get_bounds().max.z {
let wpos = Vec3::new(offs.x, offs.y, self.alt + z + ALT_OFFSET);
let spos = Vec3::new(rpos.x - TILE_SIZE / 2, rpos.y - TILE_SIZE / 2, z);
if let Some(block) = entrance
.get(spos)
.ok()
.copied()
.map(|sb| block_from_structure(sb, spos, self.origin, self.seed, col_sample))
.unwrap_or(None)
{
let _ = vol.set(wpos, block);
}
}
// Apply the dungeon internals
let mut z = self.alt + ALT_OFFSET;
for floor in &self.floors {
z -= floor.total_depth();
@ -133,7 +167,7 @@ impl Dungeon {
);
}
let mut z = self.alt;
let mut z = self.alt + ALT_OFFSET;
for floor in &self.floors {
z -= floor.total_depth();
let origin = Vec3::new(self.origin.x, self.origin.y, z);