diff --git a/common/src/generation.rs b/common/src/generation.rs index 65a70e6bf8..d3bb340817 100644 --- a/common/src/generation.rs +++ b/common/src/generation.rs @@ -8,6 +8,7 @@ pub enum EntityTemplate { Traveller, } +#[derive(Clone)] pub struct EntityInfo { pub pos: Vec3, pub is_waypoint: bool, // Edge case, overrides everything else diff --git a/server/src/lib.rs b/server/src/lib.rs index f8c47f60d3..caef411514 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -532,7 +532,7 @@ impl Server { // despawning if the entity walks outside of a valid chunk // briefly. If the entity isn't even near a loaded chunk then we get // rid of it. - Spiral2d::new().all(|offs| terrain.get_key(chunk_key + offs).is_none()) + Spiral2d::new().take(9).all(|offs| terrain.get_key(chunk_key + offs).is_none()) }) .map(|(entity, _, _)| entity) .collect::>() diff --git a/world/src/layer/wildlife.rs b/world/src/layer/wildlife.rs index 7d188e4309..ad20178fec 100644 --- a/world/src/layer/wildlife.rs +++ b/world/src/layer/wildlife.rs @@ -1,9 +1,9 @@ use crate::{column::ColumnSample, sim::SimChunk, util::RandomField, IndexRef, CONFIG}; use common::{ - comp::{Alignment, quadruped_medium, quadruped_small}, + comp::{quadruped_low, quadruped_medium, quadruped_small, Alignment}, + generation::{ChunkSupplement, EntityInfo}, terrain::{Block, SpriteKind}, vol::{BaseVol, ReadVol, RectSizedVol, WriteVol}, - generation::{ChunkSupplement, EntityInfo}, }; use noise::NoiseFn; use rand::prelude::*; @@ -29,54 +29,168 @@ pub fn apply_wildlife_supplement<'a, R: Rng>( ) { let scatter: &[( fn(Vec3, &mut R) -> EntityInfo, // Entity - Range, // Group size range - bool, // Underwater? + Range, // Group size range + bool, // Underwater? fn(&SimChunk, &ColumnSample) -> f32, // Density )] = &[ // Wolves ( - |pos, rng| EntityInfo::at(pos) - .with_body(quadruped_medium::Body::random_with(rng, &quadruped_medium::Species::Wolf).into()) - .with_alignment(Alignment::Enemy), + |pos, rng| { + EntityInfo::at(pos) + .with_body( + quadruped_medium::Body::random_with(rng, &quadruped_medium::Species::Wolf) + .into(), + ) + .with_alignment(Alignment::Enemy) + }, 3..8, false, |c, col| close(c.temp, CONFIG.snow_temp, 0.7) * col.tree_density * BASE_DENSITY * 0.3, ), // Frostfang ( - |pos, rng| EntityInfo::at(pos) - .with_body(quadruped_medium::Body::random_with(rng, &quadruped_medium::Species::Frostfang).into()) - .with_alignment(Alignment::Enemy), + |pos, rng| { + EntityInfo::at(pos) + .with_body( + quadruped_medium::Body::random_with( + rng, + &quadruped_medium::Species::Frostfang, + ) + .into(), + ) + .with_alignment(Alignment::Enemy) + }, 1..4, false, |c, col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.15, ), // Bonerattler ( - |pos, rng| EntityInfo::at(pos) - .with_body(quadruped_medium::Body::random_with(rng, &quadruped_medium::Species::Bonerattler).into()) - .with_alignment(Alignment::Enemy), + |pos, rng| { + EntityInfo::at(pos) + .with_body( + quadruped_medium::Body::random_with( + rng, + &quadruped_medium::Species::Bonerattler, + ) + .into(), + ) + .with_alignment(Alignment::Enemy) + }, 1..3, false, |c, col| close(c.humidity, CONFIG.desert_hum, 0.3) * BASE_DENSITY * 0.5, ), - // Deer + // Forest herd (Deer, Hirdrasil, etc.) ( - |pos, rng| EntityInfo::at(pos) - .with_body(quadruped_medium::Body::random_with(rng, &quadruped_medium::Species::Deer).into()) - .with_alignment(Alignment::Wild), - 4..10, + |pos, rng| { + EntityInfo::at(pos) + .with_body(match rng.gen_range(0, 10) { + 0 => quadruped_medium::Body::random_with( + rng, + &quadruped_medium::Species::Deer, + ) + .into(), + 1 => quadruped_medium::Body::random_with( + rng, + &quadruped_medium::Species::Hirdrasil, + ) + .into(), + 2 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Rabbit, + ) + .into(), + 3 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Jackalope, + ) + .into(), + 4 => { + quadruped_small::Body::random_with(rng, &quadruped_small::Species::Boar) + .into() + }, + 5 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Sheep, + ) + .into(), + 6 => { + quadruped_small::Body::random_with(rng, &quadruped_small::Species::Pig) + .into() + }, + 7 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Truffler, + ) + .into(), + 8 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Squirrel, + ) + .into(), + _ => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Porcupine, + ) + .into(), + }) + .with_alignment(Alignment::Wild) + }, + 3..8, false, - |c, col| close(c.temp, CONFIG.temperate_temp, 0.7) * col.tree_density * BASE_DENSITY * 0.5, + |c, col| { + close(c.temp, CONFIG.temperate_temp, 0.7) * col.tree_density * BASE_DENSITY * 1.5 + }, ), - // Frog + // Amphibians (Frog, Axolotl, Crocodile, etc.) ( - |pos, rng| EntityInfo::at(pos) - .with_body(quadruped_small::Body::random_with(rng, &quadruped_small::Species::Frog).into()) - .with_alignment(Alignment::Wild), + |pos, rng| { + EntityInfo::at(pos) + .with_body(match rng.gen_range(0, 6) { + 0 => { + quadruped_small::Body::random_with(rng, &quadruped_small::Species::Frog) + .into() + }, + 1 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Axolotl, + ) + .into(), + 2 => quadruped_small::Body::random_with( + rng, + &quadruped_small::Species::Fungome, + ) + .into(), + // WE GROW 'EM BIG 'ERE + 3 => quadruped_low::Body::random_with( + rng, + &quadruped_low::Species::Crocodile, + ) + .into(), + 4 => quadruped_low::Body::random_with( + rng, + &quadruped_low::Species::Alligator, + ) + .into(), + _ => quadruped_low::Body::random_with( + rng, + &quadruped_low::Species::Salamander, + ) + .into(), + }) + .with_alignment(Alignment::Wild) + }, 1..3, false, - |c, col| close(col.temp, CONFIG.tropical_temp, 0.8) * if col.water_dist.map(|d| d < 10.0).unwrap_or(false) { 0.0005 } else { 0.0 }, + |c, col| { + close(col.temp, CONFIG.tropical_temp, 0.8) + * if col.water_dist.map(|d| d < 10.0).unwrap_or(false) { + 0.001 + } else { + 0.0 + } + }, ), ]; @@ -95,10 +209,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>( let underwater = col_sample.water_level > col_sample.alt; - let entity_group = scatter - .iter() - .enumerate() - .find_map(|(i, (make_entity, group_size, is_underwater, f))| { + let entity_group = scatter.iter().enumerate().find_map( + |(i, (make_entity, group_size, is_underwater, f))| { let density = f(chunk, col_sample); if density > 0.0 && RandomField::new(i as u32 * 7) @@ -109,7 +221,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>( } else { None } - }); + }, + ); if let Some((make_entity, group_size)) = entity_group { let alt = col_sample.alt as i32; @@ -131,11 +244,14 @@ pub fn apply_wildlife_supplement<'a, R: Rng>( }) { let group_size = dynamic_rng.gen_range(group_size.start, group_size.end); + let entity = make_entity( + Vec3::new(wpos2d.x, wpos2d.y, alt + solid_end).map(|e| e as f32), + dynamic_rng, + ); for _ in 0..group_size { - let pos = Vec3::new(wpos2d.x, wpos2d.y, alt + solid_end) - .map(|e| e as f32 + dynamic_rng.gen::()); - supplement.add_entity(make_entity(pos, dynamic_rng) - .with_automatic_name()); + let mut entity = entity.clone(); + entity.pos = entity.pos.map(|e| e + dynamic_rng.gen::()); + supplement.add_entity(entity.with_automatic_name()); } } }