This commit is contained in:
Dr. Dystopia 2021-06-11 13:25:00 +02:00
commit 690951648d
12 changed files with 123 additions and 108 deletions

View File

@ -1724,7 +1724,7 @@
], ],
), ),
"leather": ( "leather": (
output: ("common.items.crafting_ing.leather.thick_leather", 1), output: ("common.items.crafting_ing.leather.simple_leather", 1),
inputs: [ inputs: [
(Tag(Material(Leather)), 1), (Tag(Material(Leather)), 1),
], ],

View File

@ -21,13 +21,20 @@ common-base = { package = "veloren-common-base", path = "base" }
# Serde # Serde
serde = { version = "1.0.110", features = ["derive", "rc"] } serde = { version = "1.0.110", features = ["derive", "rc"] }
# Util
enum-iterator = "0.6"
vek = { version = "=0.14.1", features = ["serde"] }
# Strum
strum = "0.20"
strum_macros = "0.20"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
approx = "0.4.0" approx = "0.4.0"
clap = "2.33" clap = "2.33"
crossbeam-utils = "0.8.1" crossbeam-utils = "0.8.1"
bitflags = "1.2" bitflags = "1.2"
crossbeam-channel = "0.5" crossbeam-channel = "0.5"
enum-iterator = "0.6"
lazy_static = "1.4.0" lazy_static = "1.4.0"
num-derive = "0.3" num-derive = "0.3"
num-traits = "0.2" num-traits = "0.2"
@ -36,7 +43,6 @@ rayon = "1.5"
roots = "0.0.6" roots = "0.0.6"
spin_sleep = "1.0" spin_sleep = "1.0"
tracing = { version = "0.1", default-features = false } tracing = { version = "0.1", default-features = false }
vek = { version = "=0.14.1", features = ["serde"] }
uuid = { version = "0.8.1", default-features = false, features = ["serde", "v4"] } uuid = { version = "0.8.1", default-features = false, features = ["serde", "v4"] }
rand = "0.8" rand = "0.8"
@ -61,10 +67,6 @@ slotmap = { version = "1.0", features = ["serde"] }
indexmap = "1.3.0" indexmap = "1.3.0"
slab = "0.4.2" slab = "0.4.2"
# Strum
strum = "0.20"
strum_macros = "0.20"
# ECS # ECS
specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control", "nightly"], rev = "f985bec5d456f7b0dd8aae99848f9473c2cd9d46" } specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control", "nightly"], rev = "f985bec5d456f7b0dd8aae99848f9473c2cd9d46" }
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "8be2abcddf8f524cb5876e8dd20a7e47cfaf7573" } specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "8be2abcddf8f524cb5876e8dd20a7e47cfaf7573" }

View File

@ -1,7 +1,7 @@
use crate::comp::buff::{Buff, BuffChange, BuffData, BuffKind, BuffSource};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use crate::{ use crate::{
comp::{ comp::{
buff::{Buff, BuffChange, BuffData, BuffKind, BuffSource},
inventory::{ inventory::{
item::{ item::{
armor::Protection, armor::Protection,
@ -814,6 +814,7 @@ pub fn get_weapons(inv: &Inventory) -> (Option<ToolKind>, Option<ToolKind>) {
) )
} }
#[cfg(not(target_arch = "wasm32"))]
pub fn weapon_rating<T: ItemDesc>(item: &T, msm: &MaterialStatManifest) -> f32 { pub fn weapon_rating<T: ItemDesc>(item: &T, msm: &MaterialStatManifest) -> f32 {
const DAMAGE_WEIGHT: f32 = 2.0; const DAMAGE_WEIGHT: f32 = 2.0;
const POISE_WEIGHT: f32 = 1.0; const POISE_WEIGHT: f32 = 1.0;
@ -834,6 +835,7 @@ pub fn weapon_rating<T: ItemDesc>(item: &T, msm: &MaterialStatManifest) -> f32 {
} }
} }
#[cfg(not(target_arch = "wasm32"))]
fn weapon_skills(inventory: &Inventory, skill_set: &SkillSet) -> f32 { fn weapon_skills(inventory: &Inventory, skill_set: &SkillSet) -> f32 {
let (mainhand, offhand) = get_weapons(inventory); let (mainhand, offhand) = get_weapons(inventory);
let mainhand_skills = if let Some(tool) = mainhand { let mainhand_skills = if let Some(tool) = mainhand {
@ -849,6 +851,7 @@ fn weapon_skills(inventory: &Inventory, skill_set: &SkillSet) -> f32 {
mainhand_skills.max(offhand_skills) mainhand_skills.max(offhand_skills)
} }
#[cfg(not(target_arch = "wasm32"))]
fn get_weapon_rating(inventory: &Inventory, msm: &MaterialStatManifest) -> f32 { fn get_weapon_rating(inventory: &Inventory, msm: &MaterialStatManifest) -> f32 {
let mainhand_rating = let mainhand_rating =
if let Some((item, _)) = equipped_item_and_tool(inventory, EquipSlot::ActiveMainhand) { if let Some((item, _)) = equipped_item_and_tool(inventory, EquipSlot::ActiveMainhand) {
@ -901,6 +904,7 @@ pub fn combat_rating(
combined_rating * body.combat_multiplier() combined_rating * body.combat_multiplier()
} }
#[cfg(not(target_arch = "wasm32"))]
pub fn compute_crit_mult(inventory: Option<&Inventory>) -> f32 { pub fn compute_crit_mult(inventory: Option<&Inventory>) -> f32 {
// Starts with a value of 1.25 when summing the stats from each armor piece, and // Starts with a value of 1.25 when summing the stats from each armor piece, and
// defaults to a value of 1.25 if no inventory is equipped // defaults to a value of 1.25 if no inventory is equipped
@ -918,6 +922,7 @@ pub fn compute_crit_mult(inventory: Option<&Inventory>) -> f32 {
} }
/// Computes the energy reward modifer from worn armor /// Computes the energy reward modifer from worn armor
#[cfg(not(target_arch = "wasm32"))]
pub fn compute_energy_reward_mod(inventory: Option<&Inventory>) -> f32 { pub fn compute_energy_reward_mod(inventory: Option<&Inventory>) -> f32 {
// Starts with a value of 1.0 when summing the stats from each armor piece, and // Starts with a value of 1.0 when summing the stats from each armor piece, and
// defaults to a value of 1.0 if no inventory is present // defaults to a value of 1.0 if no inventory is present
@ -936,6 +941,7 @@ pub fn compute_energy_reward_mod(inventory: Option<&Inventory>) -> f32 {
/// Computes the modifier that should be applied to max energy from the /// Computes the modifier that should be applied to max energy from the
/// currently equipped items /// currently equipped items
#[cfg(not(target_arch = "wasm32"))]
pub fn compute_max_energy_mod(energy: &Energy, inventory: Option<&Inventory>) -> f32 { pub fn compute_max_energy_mod(energy: &Energy, inventory: Option<&Inventory>) -> f32 {
// Defaults to a value of 0 if no inventory is present // Defaults to a value of 0 if no inventory is present
let energy_increase = inventory.map_or(0, |inv| { let energy_increase = inventory.map_or(0, |inv| {

View File

@ -1,5 +1,5 @@
#[cfg(not(target_arch = "wasm32"))]
use crate::uid::Uid; use crate::uid::Uid;
use core::{cmp::Ordering, time::Duration};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use hashbrown::HashMap; use hashbrown::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -7,8 +7,6 @@ use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage}; use specs::{Component, DerefFlaggedStorage};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
#[cfg(not(target_arch = "wasm32"))]
use std::{cmp::Ordering, time::Duration};
use strum_macros::EnumIter; use strum_macros::EnumIter;
/// De/buff Kind. /// De/buff Kind.
@ -101,7 +99,6 @@ impl BuffKind {
} }
// Struct used to store data relevant to a buff // Struct used to store data relevant to a buff
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct BuffData { pub struct BuffData {
pub strength: f32, pub strength: f32,
@ -116,7 +113,6 @@ impl BuffData {
/// De/buff category ID. /// De/buff category ID.
/// Similar to `BuffKind`, but to mark a category (for more generic usage, like /// Similar to `BuffKind`, but to mark a category (for more generic usage, like
/// positive/negative buffs). /// positive/negative buffs).
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)] #[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub enum BuffCategory { pub enum BuffCategory {
Natural, Natural,
@ -127,7 +123,6 @@ pub enum BuffCategory {
FromAura(bool), // bool used to check if buff recently set by aura FromAura(bool), // bool used to check if buff recently set by aura
} }
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ModifierKind { pub enum ModifierKind {
Additive, Additive,
@ -135,7 +130,6 @@ pub enum ModifierKind {
} }
/// Data indicating and configuring behaviour of a de/buff. /// Data indicating and configuring behaviour of a de/buff.
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BuffEffect { pub enum BuffEffect {
/// Periodically damages or heals entity /// Periodically damages or heals entity
@ -175,7 +169,6 @@ pub enum BuffEffect {
/// ///
/// To provide more classification info when needed, /// To provide more classification info when needed,
/// buff can be in one or more buff category. /// buff can be in one or more buff category.
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Buff { pub struct Buff {
pub kind: BuffKind, pub kind: BuffKind,
@ -188,7 +181,6 @@ pub struct Buff {
/// Information about whether buff addition or removal was requested. /// Information about whether buff addition or removal was requested.
/// This to implement "on_add" and "on_remove" hooks for constant buffs. /// This to implement "on_add" and "on_remove" hooks for constant buffs.
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum BuffChange { pub enum BuffChange {
/// Adds this buff. /// Adds this buff.
@ -371,7 +363,6 @@ impl PartialEq for Buff {
} }
/// Source of the de/buff /// Source of the de/buff
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] #[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
pub enum BuffSource { pub enum BuffSource {
/// Applied by a character /// Applied by a character
@ -485,7 +476,6 @@ impl Buffs {
} }
} }
#[cfg(not(target_arch = "wasm32"))]
pub type BuffId = u64; pub type BuffId = u64;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]

View File

@ -1,7 +1,6 @@
use super::{ #[cfg(not(target_arch = "wasm32"))]
body::{object, Body}, use super::body::{object, Body};
Density, Ori, Vel, use super::{Density, Ori, Vel};
};
use crate::{ use crate::{
consts::{AIR_DENSITY, WATER_DENSITY}, consts::{AIR_DENSITY, WATER_DENSITY},
util::{Dir, Plane, Projection}, util::{Dir, Plane, Projection},
@ -93,6 +92,7 @@ pub struct Wings {
pub ori: Ori, pub ori: Ori,
} }
#[cfg(not(target_arch = "wasm32"))]
impl Body { impl Body {
pub fn aerodynamic_forces( pub fn aerodynamic_forces(
&self, &self,

View File

@ -12,8 +12,10 @@ mod character_state;
pub mod compass; pub mod compass;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
mod controller; mod controller;
#[cfg(not(target_arch = "wasm32"))]
pub mod dialogue; pub mod dialogue;
#[cfg(not(target_arch = "wasm32"))] mod energy; #[cfg(not(target_arch = "wasm32"))] mod energy;
#[cfg(not(target_arch = "wasm32"))]
pub mod fluid_dynamics; pub mod fluid_dynamics;
#[cfg(not(target_arch = "wasm32"))] pub mod group; #[cfg(not(target_arch = "wasm32"))] pub mod group;
mod health; mod health;

View File

@ -17,6 +17,7 @@
)] )]
/// Re-exported crates /// Re-exported crates
#[cfg(not(target_arch = "wasm32"))]
pub use uuid; pub use uuid;
// modules // modules
@ -31,7 +32,6 @@ pub mod character;
#[cfg(not(target_arch = "wasm32"))] pub mod cmd; #[cfg(not(target_arch = "wasm32"))] pub mod cmd;
pub mod combat; pub mod combat;
pub mod comp; pub mod comp;
#[cfg(not(target_arch = "wasm32"))]
pub mod consts; pub mod consts;
#[cfg(not(target_arch = "wasm32"))] pub mod depot; #[cfg(not(target_arch = "wasm32"))] pub mod depot;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
@ -46,9 +46,7 @@ pub mod generation;
#[cfg(not(target_arch = "wasm32"))] pub mod grid; #[cfg(not(target_arch = "wasm32"))] pub mod grid;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub mod lottery; pub mod lottery;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))] pub mod npc;
#[cfg(not(target_arch = "wasm32"))]
pub mod npc;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub mod outcome; pub mod outcome;
#[cfg(not(target_arch = "wasm32"))] pub mod path; #[cfg(not(target_arch = "wasm32"))] pub mod path;
@ -61,6 +59,7 @@ pub mod resources;
#[cfg(not(target_arch = "wasm32"))] pub mod rtsim; #[cfg(not(target_arch = "wasm32"))] pub mod rtsim;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub mod skillset_builder; pub mod skillset_builder;
#[cfg(not(target_arch = "wasm32"))]
pub mod slowjob; pub mod slowjob;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub mod spiral; pub mod spiral;

View File

@ -1,5 +1,7 @@
#[cfg(not(target_arch = "wasm32"))]
use crate::comp::Pos; use crate::comp::Pos;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(not(target_arch = "wasm32"))]
use specs::Entity; use specs::Entity;
/// A resource that stores the time of day. /// A resource that stores the time of day.
@ -14,6 +16,7 @@ pub struct Time(pub f64);
#[derive(Default)] #[derive(Default)]
pub struct DeltaTime(pub f32); pub struct DeltaTime(pub f32);
#[cfg(not(target_arch = "wasm32"))]
#[derive(Default)] #[derive(Default)]
pub struct EntitiesDiedLastTick(pub Vec<(Entity, Pos)>); pub struct EntitiesDiedLastTick(pub Vec<(Entity, Pos)>);
@ -34,6 +37,7 @@ pub enum GameMode {
/// A resource that stores the player's entity (on the client), and None on the /// A resource that stores the player's entity (on the client), and None on the
/// server /// server
#[cfg(not(target_arch = "wasm32"))]
#[derive(Copy, Clone, Default, Debug)] #[derive(Copy, Clone, Default, Debug)]
pub struct PlayerEntity(pub Option<Entity>); pub struct PlayerEntity(pub Option<Entity>);
@ -65,6 +69,7 @@ impl PlayerPhysicsSetting {
/// List of which players are using client-authoratative vs server-authoratative /// List of which players are using client-authoratative vs server-authoratative
/// physics, as a stop-gap until we can use server-authoratative physics for /// physics, as a stop-gap until we can use server-authoratative physics for
/// everyone /// everyone
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Default, Debug)] #[derive(Clone, Default, Debug)]
pub struct PlayerPhysicsSettings { pub struct PlayerPhysicsSettings {
pub settings: hashbrown::HashMap<uuid::Uuid, PlayerPhysicsSetting>, pub settings: hashbrown::HashMap<uuid::Uuid, PlayerPhysicsSetting>,

View File

@ -300,7 +300,7 @@ impl Server {
let map = world.get_map_data(index.as_index_ref(), &state.thread_pool()); let map = world.get_map_data(index.as_index_ref(), &state.thread_pool());
#[cfg(not(feature = "worldgen"))] #[cfg(not(feature = "worldgen"))]
let (world, index) = World::generate(settings.world_seed, &state.thread_pool()); let (world, index) = World::generate(settings.world_seed);
#[cfg(not(feature = "worldgen"))] #[cfg(not(feature = "worldgen"))]
let map = WorldMapMsg { let map = WorldMapMsg {
dimensions_lg: Vec2::zero(), dimensions_lg: Vec2::zero(),
@ -310,6 +310,7 @@ impl Server {
sea_level: 0.0, sea_level: 0.0,
alt: Grid::new(Vec2::new(1, 1), 1), alt: Grid::new(Vec2::new(1, 1), 1),
sites: Vec::new(), sites: Vec::new(),
pois: Vec::new(),
}; };
#[cfg(feature = "worldgen")] #[cfg(feature = "worldgen")]

View File

@ -1,5 +1,6 @@
use common::{ use common::{
generation::{ChunkSupplement, EntityInfo}, generation::{ChunkSupplement, EntityInfo},
resources::TimeOfDay,
terrain::{ terrain::{
Block, BlockKind, MapSizeLg, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize, Block, BlockKind, MapSizeLg, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize,
}, },
@ -48,6 +49,7 @@ impl World {
_index: IndexRef, _index: IndexRef,
chunk_pos: Vec2<i32>, chunk_pos: Vec2<i32>,
_should_continue: impl FnMut() -> bool, _should_continue: impl FnMut() -> bool,
_time: Option<TimeOfDay>,
) -> Result<(TerrainChunk, ChunkSupplement), ()> { ) -> Result<(TerrainChunk, ChunkSupplement), ()> {
let (x, y) = chunk_pos.map(|e| e.to_le_bytes()).into_tuple(); let (x, y) = chunk_pos.map(|e| e.to_le_bytes()).into_tuple();
let mut rng = SmallRng::from_seed([ let mut rng = SmallRng::from_seed([

View File

@ -439,15 +439,18 @@ pub fn apply_caves_supplement<'a>(
let cave_depth = (col_sample.alt - cave.alt).max(0.0); //slightly different from earlier cave depth? let cave_depth = (col_sample.alt - cave.alt).max(0.0); //slightly different from earlier cave depth?
// Scatter things in caves // Scatter things in caves
if let Some(z) = (-4..8).map(|z| cave_base + z).find(|z| {
(0..2).all(|z_offs| {
vol.get(offs.with_z(z + z_offs))
.map_or(true, |b| b.is_fluid())
})
}) {
if RandomField::new(index.seed).chance(wpos2d.into(), 0.0018) if RandomField::new(index.seed).chance(wpos2d.into(), 0.0018)
&& cave_base < surface_z as i32 - 40 && cave_base < surface_z as i32 - 40
{ {
let is_hostile: bool; let is_hostile: bool;
let entity = EntityInfo::at(Vec3::new( let entity =
wpos2d.x as f32, EntityInfo::at(Vec3::new(wpos2d.x as f32, wpos2d.y as f32, z as f32))
wpos2d.y as f32,
cave_base as f32,
))
.with_body(if cave_depth < 70.0 { .with_body(if cave_depth < 70.0 {
is_hostile = false; is_hostile = false;
let species = match dynamic_rng.gen_range(0..4) { let species = match dynamic_rng.gen_range(0..4) {
@ -456,7 +459,8 @@ pub fn apply_caves_supplement<'a>(
2 => comp::quadruped_small::Species::Holladon, 2 => comp::quadruped_small::Species::Holladon,
_ => comp::quadruped_small::Species::Batfox, _ => comp::quadruped_small::Species::Batfox,
}; };
comp::quadruped_small::Body::random_with(dynamic_rng, &species).into() comp::quadruped_small::Body::random_with(dynamic_rng, &species)
.into()
} else if cave_depth < 120.0 { } else if cave_depth < 120.0 {
is_hostile = true; is_hostile = true;
let species = match dynamic_rng.gen_range(0..3) { let species = match dynamic_rng.gen_range(0..3) {
@ -464,7 +468,8 @@ pub fn apply_caves_supplement<'a>(
1 => comp::quadruped_low::Species::Salamander, 1 => comp::quadruped_low::Species::Salamander,
_ => comp::quadruped_low::Species::Asp, _ => comp::quadruped_low::Species::Asp,
}; };
comp::quadruped_low::Body::random_with(dynamic_rng, &species).into() comp::quadruped_low::Body::random_with(dynamic_rng, &species)
.into()
} else if cave_depth < 200.0 { } else if cave_depth < 200.0 {
is_hostile = true; is_hostile = true;
let species = match dynamic_rng.gen_range(0..3) { let species = match dynamic_rng.gen_range(0..3) {
@ -472,7 +477,8 @@ pub fn apply_caves_supplement<'a>(
1 => comp::quadruped_low::Species::Lavadrake, 1 => comp::quadruped_low::Species::Lavadrake,
_ => comp::quadruped_low::Species::Basilisk, _ => comp::quadruped_low::Species::Basilisk,
}; };
comp::quadruped_low::Body::random_with(dynamic_rng, &species).into() comp::quadruped_low::Body::random_with(dynamic_rng, &species)
.into()
} else { } else {
is_hostile = true; is_hostile = true;
let species = match dynamic_rng.gen_range(0..5) { let species = match dynamic_rng.gen_range(0..5) {
@ -485,7 +491,8 @@ pub fn apply_caves_supplement<'a>(
}, },
_ => comp::biped_large::Species::Troll, _ => comp::biped_large::Species::Troll,
}; };
comp::biped_large::Body::random_with(dynamic_rng, &species).into() comp::biped_large::Body::random_with(dynamic_rng, &species)
.into()
}) })
.with_alignment(if is_hostile { .with_alignment(if is_hostile {
comp::Alignment::Enemy comp::Alignment::Enemy
@ -500,6 +507,7 @@ pub fn apply_caves_supplement<'a>(
} }
} }
} }
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn apply_coral_to(canvas: &mut Canvas) { pub fn apply_coral_to(canvas: &mut Canvas) {

View File

@ -1063,37 +1063,37 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
}, },
); );
if let Some((make_entity, group_size)) = entity_group {
let alt = col_sample.alt as i32; let alt = col_sample.alt as i32;
// Find the intersection between ground and air, if there is one near the
// surface if let Some((make_entity, group_size)) = entity_group {
if let Some(solid_end) = (-4..8)
.find(|z| {
vol.get(Vec3::new(offs.x, offs.y, alt + z))
.map(|b| b.is_solid())
.unwrap_or(false)
})
.and_then(|solid_start| {
(1..8).map(|z| solid_start + z).find(|z| {
vol.get(Vec3::new(offs.x, offs.y, alt + z))
.map(|b| !b.is_solid())
.unwrap_or(true)
})
})
{
let group_size = dynamic_rng.gen_range(group_size.start..group_size.end); let group_size = dynamic_rng.gen_range(group_size.start..group_size.end);
let entity = make_entity( let entity = make_entity(
Vec3::new(wpos2d.x, wpos2d.y, alt + solid_end).map(|e| e as f32), (wpos2d.map(|e| e as f32) + 0.5).with_z(alt as f32),
dynamic_rng, dynamic_rng,
); );
for e in 0..group_size { for e in 0..group_size {
let mut entity = entity.clone(); // Choose a nearby position
entity.pos = entity.pos.map(|e| e + dynamic_rng.gen::<f32>()) let offs_wpos2d = (Vec2::new(
+ Vec3::new(
(e as f32 / group_size as f32 * 2.0 * f32::consts::PI).sin(), (e as f32 / group_size as f32 * 2.0 * f32::consts::PI).sin(),
(e as f32 / group_size as f32 * 2.0 * f32::consts::PI).cos(), (e as f32 / group_size as f32 * 2.0 * f32::consts::PI).cos(),
0.0, ) * (5.0 + dynamic_rng.gen::<f32>().powf(0.5) * 5.0))
) * (5.0 + dynamic_rng.gen::<f32>().powf(0.5) * 5.0); .map(|e| e as i32);
// Clamp position to chunk
let offs_wpos2d = (offs + offs_wpos2d)
.clamped(Vec2::zero(), vol.size_xy().map(|e| e as i32) - 1)
- offs;
// Find the intersection between ground and air, if there is one near the
// surface
if let Some(solid_end) = (-8..8).find(|z| {
(0..2).all(|z2| {
vol.get(Vec3::new(offs.x, offs.y, alt) + offs_wpos2d.with_z(z + z2))
.map(|b| !b.is_solid())
.unwrap_or(true)
})
}) {
let mut entity = entity.clone();
entity.pos += offs_wpos2d.with_z(solid_end).map(|e| e as f32);
supplement.add_entity(entity.with_automatic_name()); supplement.add_entity(entity.with_automatic_name());
} }
} }