Merge branch 'zesterer/world-changes' into 'master'

Dungeon entrances

See merge request veloren/veloren!955
This commit is contained in:
Monty Marz 2020-04-29 15:36:57 +00:00
commit dc95efa95b
55 changed files with 193 additions and 182 deletions

View File

@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `/sudo` command
- Added a Level of Detail (LoD) system for terrain sprites and entities
- Added owl, hyena, parrot npcs
- Added dungeon entrances
### Changed

View File

@ -0,0 +1,48 @@
(
[ (
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)
),
(
specifier: "world.structure.dungeon.temperate_entrance.ruins_4",
center: (13, 11, 14)
),
(
specifier: "world.structure.dungeon.misc_entrance.tower-ruin",
center: (13, 16, 9)
),
]
)

View File

@ -1,9 +1,5 @@
(
[
(
specifier: "world.structure.natural.tower-ruin",
center: (11, 14, 5)
),
[
(
specifier: "world.structure.natural.witch-hut",
center: (10, 13, 9)

Binary file not shown.

BIN
assets/world/module/human/chimney_roof.vox (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
assets/world/module/human/corner_roof.vox (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
assets/world/module/human/door_big.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/human/door_ground.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/human/floor_ground.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/human/floor_roof.vox (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
assets/world/module/human/stair_ground.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/human/wall_ground.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/human/wall_roof.vox (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/world/module/wall/corner_ground.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/corner_mid.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/corner_top.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/edge_ground.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/edge_mid.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/edge_top.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/end_top.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/module/wall/single_top.vox (Stored with Git LFS)

Binary file not shown.

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.

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/1.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/10.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/2.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/3.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/4.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/5.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/6.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/7.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/8.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/desert_palm_old/9.vox (Stored with Git LFS)

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,10 @@ 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 +641,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,21 +95,26 @@ 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);
let flatten_radius = match &site.kind {
SiteKind::Settlement => 10.0,
SiteKind::Dungeon => 2.0,
};
let (raise, raise_dist): (f32, i32) = match &site.kind {
SiteKind::Settlement => (10.0, 6),
_ => (0.0, 0),
};
// Flatten ground
let flatten_radius = 10.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
+ if offs.magnitude_squared() <= 6i32.pow(2) {
16.0
+ if offs.magnitude_squared() <= raise_dist.pow(2) {
raise
} else {
0.0
}; // Raise the town centre up a little
@ -335,7 +340,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

@ -1,5 +1,6 @@
use super::SpawnRules;
use crate::{
block::block_from_structure,
column::ColumnSample,
sim::WorldSim,
site::BlockMask,
@ -11,11 +12,12 @@ use common::{
comp,
generation::{ChunkSupplement, EntityInfo},
store::{Id, Store},
terrain::{Block, BlockKind, TerrainChunkSize},
terrain::{Block, BlockKind, Structure, TerrainChunkSize},
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, Vox, WriteVol},
};
use lazy_static::lazy_static;
use rand::prelude::*;
use std::f32;
use std::{f32, sync::Arc};
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,16 +47,19 @@ 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 };
let this = Self {
origin: wpos,
origin: wpos - TILE_SIZE / 2,
alt: ctx
.sim
.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,16 @@ 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 +104,30 @@ 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();
@ -123,17 +160,17 @@ impl Dungeon {
let offs = Vec2::new(rng.gen_range(-1.0, 1.0), rng.gen_range(-1.0, 1.0))
.try_normalized()
.unwrap_or(Vec2::unit_y())
* 16.0;
* 12.0;
supplement.add_entity(
EntityInfo::at(
Vec3::new(self.origin.x, self.origin.y, self.alt + 4).map(|e| e as f32)
Vec3::new(self.origin.x, self.origin.y, self.alt + 16).map(|e| e as f32)
+ Vec3::from(offs),
)
.into_waypoint(),
);
}
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);