From ec310efb3cf1467725e5710b97d8ebbe28e49f1b Mon Sep 17 00:00:00 2001 From: Syniis Date: Wed, 7 Feb 2024 00:12:07 +0100 Subject: [PATCH 01/24] More cave features --- Cargo.lock | 14 ++ assets/world/features.ron | 22 +-- world/Cargo.toml | 2 +- world/src/layer/cave.rs | 282 +++++++++++++++++++++++++++++++++++--- 4 files changed, 286 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7cf4d7688..c0a443b765 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3150,8 +3150,22 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6acddbefae08bfba73e27f55513f491f35c365d84bf3002bf85ba9b916c5e5f" dependencies = [ + "inline_tweak_derive", "lazy_static", + "proc-macro2 1.0.78", "rustc-hash", + "syn 2.0.48", +] + +[[package]] +name = "inline_tweak_derive" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d62a0a3b6af04d4eee8e7251cd758ce74b0ed86253d3e4ac8a1b297a75f4a0" +dependencies = [ + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] diff --git a/assets/world/features.ron b/assets/world/features.ron index 53a2053d77..dae9a4ee75 100644 --- a/assets/world/features.ron +++ b/assets/world/features.ron @@ -3,17 +3,17 @@ ( caverns: false, // TODO: Disabled by default until cave overhaul - caves: true, - rocks: true, - shrubs: true, - trees: true, + caves: false, + rocks: false, + shrubs: false, + trees: false, scatter: true, - paths: true, - spots: true, - site2_towns: true, - site2_giant_trees: true, - wildlife_density: 1.0, - peak_naming: true, - biome_naming: true, + paths: false, + spots: false, + site2_towns: false, + site2_giant_trees: false, + wildlife_density: 0.0, + peak_naming: false, + biome_naming: false, train_tracks: false, // TODO: train stations, train entities ) diff --git a/world/Cargo.toml b/world/Cargo.toml index 2b13bb50cd..9f104d990d 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -39,7 +39,7 @@ packed_simd = { version = "0.3.9", optional = true } rayon = { workspace = true } serde = { workspace = true } ron = { workspace = true } -inline_tweak = { workspace = true } +inline_tweak = { workspace = true, features = ["derive"] } kiddo = "0.2" strum = { workspace = true } diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index c8521f4749..8c10c6b3b3 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -11,6 +11,7 @@ use common::{ SpriteKind, }, }; +use inline_tweak::{tweak, tweak_fn}; use noise::NoiseFn; use rand::prelude::*; use std::{ @@ -90,6 +91,7 @@ impl Tunnel { .map(|e| e as f32) } + #[tweak_fn] fn z_range_at(&self, wposf: Vec2, info: CanvasInfo) -> Option<(Range, f64)> { let start = self.a.wpos.map(|e| e as f64 + 0.5); let end = self.b.wpos.map(|e| e as f64 + 0.5); @@ -102,19 +104,29 @@ impl Tunnel { let dist = closest.distance(wposf); let radius = 8.0..64.0; if dist < radius.end + 1.0 { - let radius = Lerp::lerp( + let horizontal = Lerp::lerp( radius.start, radius.end, (info.index().noise.cave_fbm_nz.get( - (wposf.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 200.0) + (wposf.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 256.0) .into_array(), - ) * 2.0 - * 0.5 - + 0.5) + ) + 0.5) .clamped(0.0, 1.0) .powf(3.0), ); - let height_here = (1.0 - dist / radius).max(0.0).powf(0.3) * radius; + let vertical = Lerp::lerp( + radius.start, + radius.end, + (info.index().noise.cave_fbm_nz.get( + (wposf.with_z(info.land().get_alt_approx(self.b.wpos) as f64) / 256.0) + .into_array(), + ) + 0.5) + .clamped(0.0, 1.0) + .powf(3.0), + ) + .clamped(radius.start + 4.0, radius.end); + let height_here = (1.0 - dist / horizontal).max(0.0).powf(0.3) * vertical; + if height_here > 0.0 { let z_offs = info .index() @@ -132,7 +144,7 @@ impl Tunnel { .min(alt_here as f64); Some(( (base - height_here * 0.3) as i32..(base + height_here * 1.35) as i32, - radius, + vertical, )) } else { None @@ -145,13 +157,14 @@ impl Tunnel { } } + #[inline_tweak::tweak_fn] fn biome_at(&self, wpos: Vec3, info: &CanvasInfo) -> Biome { let Some(col) = info.col_or_gen(wpos.xy()) else { return Biome::default(); }; // Below the ground - let below = ((col.alt - wpos.z as f32) / 120.0).clamped(0.0, 1.0); + let below = ((col.alt - wpos.z as f32) / AVG_LEVEL_DEPTH as f32).clamped(0.0, 1.0); let depth = (col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32); let humidity = Lerp::lerp( @@ -181,13 +194,16 @@ impl Tunnel { .index() .noise .cave_nz - .get(wpos.xy().map(|e| e as f64 / 256.0).into_array()) + .get(wpos.xy().map(|e| e as f64 / 512.0).into_array()) .mul(0.5) - .add(0.5) as f32; + .add( + ((col.alt as f64 - wpos.z as f64) / (AVG_LEVEL_DEPTH as f64 * LAYERS as f64 * 0.5)) + .clamped(0.0, 2.0), + ) as f32; let underground = ((col.alt - wpos.z as f32) / 80.0 - 1.0).clamped(0.0, 1.0); - let [barren, mushroom, fire, leafy, dusty, icy] = { + let [barren, mushroom, fire, leafy, dusty, icy, crystal, sandy] = { let barren = 0.01; let mushroom = underground * close(humidity, 1.0, 0.75) * close(temp, 0.0, 0.9); let fire = underground @@ -195,10 +211,17 @@ impl Tunnel { * close(temp, 2.0, 1.0) * close(depth, 1.0, 0.65); let leafy = underground * close(humidity, 1.0, 0.85) * close(temp, 0.45, 0.8); - let dusty = close(humidity, 0.0, 0.5) * close(temp, -0.3, 0.5); + let dusty = + close(humidity, 0.0, 0.2) * close(temp, -0.4, 0.5) * close(mineral, 0.0, 0.6); let icy = close(temp, -1.0, 0.3); + let crystal = underground + * (close(humidity, 0.0, 0.5) + close(humidity, 1.0, 0.5)) + * (close(temp, 1.5, 0.8) + close(temp, -1.0, 0.3)) + * close(depth, 1.0, 0.6) + * close(mineral, 2.5, 1.8); + let sandy = close(humidity, 0.1, 0.2) * close(temp, 0.0, 0.4) * close(depth, 0.4, 0.4); - let biomes = [barren, mushroom, fire, leafy, dusty, icy]; + let biomes = [barren, mushroom, fire, leafy, dusty, icy, crystal, sandy]; let max = biomes .into_iter() .max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)) @@ -215,6 +238,8 @@ impl Tunnel { leafy, dusty, icy, + crystal, + sandy, depth, } } @@ -324,6 +349,7 @@ pub fn tunnel_bounds_at<'a>( pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { let info = canvas.info(); let mut mushroom_cache = HashMap::new(); + let mut crystal_cache = HashMap::new(); canvas.foreach_col(|canvas, wpos2d, col| { let land = info.land(); @@ -345,6 +371,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { z_range.clone(), tunnel, &mut mushroom_cache, + &mut crystal_cache, rng, ); } @@ -361,6 +388,8 @@ struct Biome { leafy: f32, dusty: f32, icy: f32, + crystal: f32, + sandy: f32, depth: f32, } @@ -370,6 +399,18 @@ struct Mushroom { head_color: Rgb, } +struct Crystal { + dir: Vec3, + length: f64, + radius: f64, +} +struct CrystalCluster { + pos: Vec3, + crystals: Vec, + color: Rgb, +} + +#[inline_tweak::tweak_fn] fn write_column( canvas: &mut Canvas, col: &ColumnSample, @@ -378,9 +419,11 @@ fn write_column( z_range: Range, tunnel: Tunnel, mushroom_cache: &mut HashMap<(Vec3, Vec2), Option>, + crystal_cache: &mut HashMap<(Vec3, Vec2), Option>, rng: &mut R, ) { mushroom_cache.clear(); + crystal_cache.clear(); let info = canvas.info(); // Exposed to the sky, or some other void above @@ -437,13 +480,39 @@ fn write_column( 0.0 }; + let bump = { + let cavern_height = (z_range.end - z_range.start) as f64; + info.index() + .noise + .cave_nz + .get(wpos2d.map(|e| e as f64 / 8.0).into_array()) + .add(1.0) + .mul(0.5) + .mul(((col.alt as f64 - z_range.end as f64) / 16.0).clamped(0.0, 1.0)) + .mul({ + let (val, total) = [ + (biome.sandy as f64 - 0.2, 0.9), + (biome.dusty as f64 - 0.1, 0.5), + (biome.icy as f64 - 0.1, 0.1), + (biome.leafy as f64 - 0.2, 0.8), + (biome.barren as f64 - 0.15, 0.6), + (biome.mushroom as f64 - 0.3, 0.2), + (biome.fire as f64 - 0.5, 0.2), + ] + .into_iter() + .fold((0.0, 0.0), |a, x| (a.0 + x.0.max(0.0) * x.1, a.1 + x.1)); + val / total + }) + .mul(0.0 + cavern_height * 0.4) + }; + let rand = RandomField::new(37 + level); let is_ice = biome.icy + col.marble * 0.2 > 0.5 && col.marble > 0.6; let dirt = 1 + (!is_ice) as i32; let bedrock = z_range.start + lava as i32; - let base = bedrock + (stalactite * 0.4) as i32; + let base = bedrock + (stalactite * 0.4) as i32 + bump as i32; let floor = base + dirt; let ceiling = z_range.end - stalactite as i32; @@ -555,6 +624,139 @@ fn write_column( None }; + let mut is_crystal = |wpos: Vec3| { + let colors = vec![ + Rgb::new(209, 106, 255), + Rgb::new(187, 86, 240), + Rgb::new(251, 238, 255), + Rgb::new(243, 204, 255), + Rgb::new(231, 154, 255), + ]; + for (wpos2d, seed) in StructureGen2d::new(112358, 32, 6).get(wpos.xy()) { + let cluster = if let Some(crystal) = crystal_cache + .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) + .or_insert_with(|| { + let mut rng = RandomPerm::new(seed); + let (z_range, radius) = + tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; + + let on_ground = rng.gen_bool(0.6); + let pos = wpos2d.with_z(if on_ground { + z_range.start + } else { + z_range.end + }); + + if rng + .gen_bool(0.8 * close(tunnel.biome_at(pos, &info).crystal, 1.0, 0.5) as f64) + && !tunnel_bounds_at(pos.xy(), &info, &info.land()) + .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) + { + let mut crystals: Vec = Vec::new(); + + let max_length = 32.0; + let main_length = rng.gen_range(8.0..max_length); + let main_radius = Lerp::lerp( + 2.0, + 4.5, + main_length / max_length + rng.gen_range(-0.2..0.2), + ); + let main_dir = Vec3::new( + rng.gen_range(tweak!(-3.0)..tweak!(3.0)), + rng.gen_range(tweak!(-3.0)..tweak!(3.0)), + rng.gen_range(0.0..10.0) * if on_ground { 1.0 } else { -1.0 }, + ) + .normalized(); + + let main_crystal = Crystal { + dir: main_dir, + length: main_length, + radius: main_radius, + }; + crystals.push(main_crystal); + + (0..12).for_each(|_| { + let side_radius = main_radius * rng.gen_range(tweak!(0.5)..tweak!(0.8)); + let side_length = main_length * rng.gen_range(tweak!(0.3)..tweak!(0.8)); + if side_radius < 1.5 { + return; + } + let side_crystal = Crystal { + dir: Vec3::new( + rng.gen_range(-1.0..1.0), + rng.gen_range(-1.0..1.0), + main_dir.z + rng.gen_range(-0.2..0.2), + ) + .normalized(), + length: side_length, + radius: side_radius, + }; + crystals.push(side_crystal); + }); + + let mut color: Rgb = *(colors.choose(&mut rng).unwrap()); + if tunnel.biome_at(pos, &info).icy > 0.125 { + color.r = color.r.saturating_sub(150u8); + color.g = color.g.saturating_sub(40u8); + color.b = color.b.saturating_add(0u8); + } + Some(CrystalCluster { + pos, + crystals, + color, + }) + } else { + None + } + }) { + crystal + } else { + continue; + }; + let wposf = wpos.map(|e| e as f64); + let cluster_pos = cluster.pos.map(|e| e as f64); + for crystal in &cluster.crystals { + let rpos = wposf - cluster_pos; + let line = LineSegment3 { + start: cluster_pos, + end: cluster_pos + crystal.dir * crystal.length, + }; + + let line_length = line.start.distance_squared(line.end); + let taper = if line_length < 0.001 { + 0.0 + } else { + rpos.dot(line.end - line.start) / line_length + }; + + let projected = line.projected_point(wposf); + let dist_sq = projected.distance_squared(wposf); + + let extreme_taper_cutoff = 0.8; + let taper_factor = 0.8; + let extreme_taper_factor = 0.4; + + let crystal_radius = if taper > extreme_taper_cutoff { + let taper = + (taper - extreme_taper_cutoff) * (1.0 - extreme_taper_cutoff).recip(); + Lerp::lerp( + crystal.radius * taper_factor, + crystal.radius * extreme_taper_factor, + taper, + ) + } else { + let taper = taper * extreme_taper_cutoff.recip(); + Lerp::lerp(crystal.radius, crystal.radius * taper_factor, taper) + }; + + if dist_sq < crystal_radius.powi(2) { + return Some(Block::new(BlockKind::GlowingRock, cluster.color)); + } + } + } + None + }; + for z in bedrock..z_range.end { let wpos = wpos2d.with_z(z); let mut try_spawn_entity = false; @@ -575,13 +777,25 @@ fn write_column( } else if (z < base && !void_below) || (z >= ceiling && !void_above) { let stalactite: Rgb = Lerp::lerp( Lerp::lerp( - Lerp::lerp(Rgb::new(80, 100, 150), Rgb::new(0, 75, 200), biome.mushroom), Lerp::lerp( - Rgb::new(100, 40, 40), - Rgb::new(100, 75, 100), - col.marble_small, + Lerp::lerp( + Rgb::new(80, 100, 150), + Rgb::new(0, 75, 200), + biome.mushroom, + ), + Lerp::lerp( + Rgb::new(100, 40, 40), + Rgb::new(100, 75, 100), + col.marble_small, + ), + biome.fire, ), - biome.fire, + Lerp::lerp( + Rgb::new(238, 198, 139), + Rgb::new(111, 99, 64), + col.marble_mid, + ), + biome.sandy, ), Lerp::lerp(Rgb::new(100, 150, 255), Rgb::new(100, 120, 255), col.marble), biome.icy, @@ -589,6 +803,8 @@ fn write_column( Block::new( if rand.chance(wpos, (biome.mushroom * biome.mineral).max(biome.icy)) { BlockKind::GlowingWeakRock + } else if rand.chance(wpos, biome.sandy) { + BlockKind::Sand } else { BlockKind::WeakRock }, @@ -621,6 +837,22 @@ fn write_column( biome.leafy, ), (Rgb::new(170, 195, 255), biome.icy), + ( + Lerp::lerp( + Rgb::new(105, 25, 131), + Rgb::new(251, 238, 255), + col.marble_mid, + ), + biome.crystal, + ), + ( + Lerp::lerp( + Rgb::new(201, 174, 116), + Rgb::new(244, 239, 227), + col.marble_small, + ), + biome.sandy, + ), ] .into_iter() .fold((Rgb::::zero(), 0.0), |a, x| { @@ -638,6 +870,8 @@ fn write_column( BlockKind::Snow } else if biome.fire > 0.5 { BlockKind::Rock + } else if biome.crystal > 0.5 { + BlockKind::GlowingRock } else { BlockKind::Sand }, @@ -677,7 +911,7 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(2), biome.dusty * 0.01) { + } else if rand.chance(wpos2d.with_z(2), biome.dusty.max(biome.sandy) * 0.01) { [ (SpriteKind::Bones, 0.5), (SpriteKind::Stones, 1.5), @@ -699,7 +933,7 @@ fn write_column( .map(|s| s.0) } else if rand.chance( wpos2d.with_z(3), - close(biome.humidity, 0.0, 0.5) * biome.mineral * 0.005, + close(biome.humidity, 0.0, 0.5) * biome.mineral.max(biome.crystal) * 0.005, ) { Some(SpriteKind::CrystalLow) } else if rand.chance(wpos2d.with_z(13), biome.fire * 0.001) { @@ -792,7 +1026,9 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(5), 0.0075) { + } else if rand + .chance(wpos2d.with_z(5), biome.mineral.max(biome.crystal) * 0.0075) + { Some(*[SpriteKind::CrystalHigh].choose(rng).unwrap()) } else { None @@ -801,6 +1037,8 @@ fn write_column( .flatten() { Block::air(sprite) + } else if let Some(block) = is_crystal(wpos) { + block } else { get_mushroom(wpos, rng).unwrap_or(Block::air(SpriteKind::Empty)) } From 148eef48051e60e8c5ae04c7b64f7f27ae30147a Mon Sep 17 00:00:00 2001 From: Syniis Date: Fri, 9 Feb 2024 03:53:40 +0100 Subject: [PATCH 02/24] Various changes to crystal generation and WIP flowers --- world/src/layer/cave.rs | 207 +++++++++++++++++++++++++++++----------- 1 file changed, 151 insertions(+), 56 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 8c10c6b3b3..85a84275be 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -11,7 +11,7 @@ use common::{ SpriteKind, }, }; -use inline_tweak::{tweak, tweak_fn}; +use inline_tweak::tweak_fn; use noise::NoiseFn; use rand::prelude::*; use std::{ @@ -124,7 +124,7 @@ impl Tunnel { .clamped(0.0, 1.0) .powf(3.0), ) - .clamped(radius.start + 4.0, radius.end); + .clamped(radius.start + 0.0, radius.end); let height_here = (1.0 - dist / horizontal).max(0.0).powf(0.3) * vertical; if height_here > 0.0 { @@ -215,10 +215,10 @@ impl Tunnel { close(humidity, 0.0, 0.2) * close(temp, -0.4, 0.5) * close(mineral, 0.0, 0.6); let icy = close(temp, -1.0, 0.3); let crystal = underground - * (close(humidity, 0.0, 0.5) + close(humidity, 1.0, 0.5)) - * (close(temp, 1.5, 0.8) + close(temp, -1.0, 0.3)) + * (close(humidity, 0.0, 0.5).max(close(humidity, 1.0, 0.5))) + * (close(temp, 1.6, 0.9).max(close(temp, -1.0, 0.3))) * close(depth, 1.0, 0.6) - * close(mineral, 2.5, 1.8); + * close(mineral, 2.5, 2.0); let sandy = close(humidity, 0.1, 0.2) * close(temp, 0.0, 0.4) * close(depth, 0.4, 0.4); let biomes = [barren, mushroom, fire, leafy, dusty, icy, crystal, sandy]; @@ -350,6 +350,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { let info = canvas.info(); let mut mushroom_cache = HashMap::new(); let mut crystal_cache = HashMap::new(); + let mut flower_cache = HashMap::new(); canvas.foreach_col(|canvas, wpos2d, col| { let land = info.land(); @@ -372,6 +373,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { tunnel, &mut mushroom_cache, &mut crystal_cache, + &mut flower_cache, rng, ); } @@ -400,16 +402,23 @@ struct Mushroom { } struct Crystal { - dir: Vec3, - length: f64, - radius: f64, + dir: Vec3, + length: f32, + radius: f32, } + struct CrystalCluster { pos: Vec3, crystals: Vec, color: Rgb, } +struct Flower { + pos: Vec3, + stalk: f32, + petals: usize, +} + #[inline_tweak::tweak_fn] fn write_column( canvas: &mut Canvas, @@ -420,6 +429,7 @@ fn write_column( tunnel: Tunnel, mushroom_cache: &mut HashMap<(Vec3, Vec2), Option>, crystal_cache: &mut HashMap<(Vec3, Vec2), Option>, + flower_cache: &mut HashMap<(Vec3, Vec2), Option>, rng: &mut R, ) { mushroom_cache.clear(); @@ -526,7 +536,7 @@ fn write_column( let (z_range, radius) = tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; let pos = wpos2d.with_z(z_range.start); - if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) + if rng.gen_bool(0.5* close(radius as f32, 64.0, 48.0) as f64) && tunnel.biome_at(pos, &info).mushroom > 0.5 // Ensure that we're not placing the mushroom over a void && !tunnel_bounds_at(pos.xy(), &info, &info.land()) @@ -632,7 +642,7 @@ fn write_column( Rgb::new(243, 204, 255), Rgb::new(231, 154, 255), ]; - for (wpos2d, seed) in StructureGen2d::new(112358, 32, 6).get(wpos.xy()) { + for (wpos2d, seed) in StructureGen2d::new(112358, 20, 8).get(wpos.xy()) { let cluster = if let Some(crystal) = crystal_cache .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) .or_insert_with(|| { @@ -647,23 +657,24 @@ fn write_column( z_range.end }); - if rng - .gen_bool(0.8 * close(tunnel.biome_at(pos, &info).crystal, 1.0, 0.5) as f64) - && !tunnel_bounds_at(pos.xy(), &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) + if rng.gen_bool( + 0.65 * close(tunnel.biome_at(pos, &info).crystal, 1.0, 0.7) as f64, + ) && !tunnel_bounds_at(pos.xy(), &info, &info.land()) + .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) { let mut crystals: Vec = Vec::new(); - let max_length = 32.0; + let max_length = (32.0 * close(radius as f32, 64.0, 52.0)).max(12.0); let main_length = rng.gen_range(8.0..max_length); - let main_radius = Lerp::lerp( + let main_radius = Lerp::lerp_unclamped( 2.0, 4.5, - main_length / max_length + rng.gen_range(-0.2..0.2), + main_length / max_length + rng.gen_range(-0.1..0.1), ); + let main_dir = Vec3::new( - rng.gen_range(tweak!(-3.0)..tweak!(3.0)), - rng.gen_range(tweak!(-3.0)..tweak!(3.0)), + rng.gen_range(-3.0..3.0), + rng.gen_range(-3.0..3.0), rng.gen_range(0.0..10.0) * if on_ground { 1.0 } else { -1.0 }, ) .normalized(); @@ -675,19 +686,15 @@ fn write_column( }; crystals.push(main_crystal); - (0..12).for_each(|_| { - let side_radius = main_radius * rng.gen_range(tweak!(0.5)..tweak!(0.8)); - let side_length = main_length * rng.gen_range(tweak!(0.3)..tweak!(0.8)); - if side_radius < 1.5 { - return; - } + (0..4).for_each(|_| { + let side_radius = (main_radius * rng.gen_range(0.5..0.8)).max(1.0); + let side_length = main_length * rng.gen_range(0.3..0.8); let side_crystal = Crystal { dir: Vec3::new( rng.gen_range(-1.0..1.0), rng.gen_range(-1.0..1.0), - main_dir.z + rng.gen_range(-0.2..0.2), - ) - .normalized(), + (main_dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), + ), length: side_length, radius: side_radius, }; @@ -713,50 +720,136 @@ fn write_column( } else { continue; }; - let wposf = wpos.map(|e| e as f64); - let cluster_pos = cluster.pos.map(|e| e as f64); + let wposf = wpos.map(|e| e as f32); + let cluster_pos = cluster.pos.map(|e| e as f32); for crystal in &cluster.crystals { - let rpos = wposf - cluster_pos; let line = LineSegment3 { start: cluster_pos, end: cluster_pos + crystal.dir * crystal.length, }; - let line_length = line.start.distance_squared(line.end); - let taper = if line_length < 0.001 { - 0.0 - } else { - rpos.dot(line.end - line.start) / line_length - }; - let projected = line.projected_point(wposf); let dist_sq = projected.distance_squared(wposf); + if dist_sq < crystal.radius.powi(2) { + let rpos = wposf - cluster_pos; + let line_length = line.start.distance_squared(line.end); + let taper = if line_length < 0.001 { + 0.0 + } else { + rpos.dot(line.end - line.start) / line_length + }; - let extreme_taper_cutoff = 0.8; - let taper_factor = 0.8; - let extreme_taper_factor = 0.4; + let peak_cutoff = 0.8; + let taper_factor = 0.7; + let peak_taper = 0.3; - let crystal_radius = if taper > extreme_taper_cutoff { - let taper = - (taper - extreme_taper_cutoff) * (1.0 - extreme_taper_cutoff).recip(); - Lerp::lerp( - crystal.radius * taper_factor, - crystal.radius * extreme_taper_factor, - taper, - ) - } else { - let taper = taper * extreme_taper_cutoff.recip(); - Lerp::lerp(crystal.radius, crystal.radius * taper_factor, taper) - }; + let crystal_radius = if taper > peak_cutoff { + let taper = (taper - peak_cutoff) * 5.0; + Lerp::lerp( + crystal.radius * taper_factor, + crystal.radius * peak_taper, + taper, + ) + } else { + let taper = taper * 1.25; + Lerp::lerp(crystal.radius, crystal.radius * taper_factor, taper) + }; - if dist_sq < crystal_radius.powi(2) { - return Some(Block::new(BlockKind::GlowingRock, cluster.color)); + if dist_sq < crystal_radius.powi(2) { + return Some(Block::new(BlockKind::GlowingRock, cluster.color)); + } } } } None }; + let mut get_flower = |wpos: Vec3| { + for (wpos2d, seed) in StructureGen2d::new(1602, 32, 8).get(wpos.xy()) { + let flower = if let Some(flower) = flower_cache + .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) + .or_insert_with(|| { + let mut rng = RandomPerm::new(seed); + let (z_range, radius) = + tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; + let pos = wpos2d.with_z(z_range.start); + if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) + && tunnel.biome_at(pos, &info).leafy > 0.9 + && !tunnel_bounds_at(pos.xy(), &info, &info.land()) + .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) + { + Some(Flower { + pos, + stalk: 8.0 + + rng.gen::().powf(2.0) + * (z_range.end - z_range.start - 8) as f32 + * 0.75, + petals: rng.gen_range(1..5) * 2 + 1, + }) + } else { + None + } + }) { + flower + } else { + continue; + }; + + let wposf = wpos.map(|e| e as f64); + let warp_freq = 1.0 / 32.0; + let warp_amp = Vec3::new(3.0, 3.0, 3.0); + let wposf_warped = wposf.map(|e| e as f32) + + Vec3::new( + FastNoise::new(seed).get(wposf * warp_freq), + FastNoise::new(seed + 1).get(wposf * warp_freq), + FastNoise::new(seed + 2).get(wposf * warp_freq), + ) * warp_amp + * (wposf.z as f32 - flower.pos.z as f32) + .mul(0.1) + .clamped(0.0, 1.0); + + let rpos = wposf_warped - flower.pos.map(|e| e as f32); + + let stalk_radius = 2.5f32; + let petal_radius = 12.0f32; + let petal_height = 8.0; + let petal_thickness = 3.0; + + let dist = rpos.xy().magnitude_squared(); + let petal_radius = petal_radius.powi(2); + if dist < petal_radius { + let petal_height_at = (dist / petal_radius).powf(0.5) * petal_height; + if rpos.z > flower.stalk + petal_height_at + && rpos.z <= flower.stalk + petal_height_at + petal_thickness + { + let away = dist / petal_radius; + if away > 0.2 { + let near = (rpos.x.atan2(rpos.y)) + .rem_euclid(std::f32::consts::TAU / flower.petals as f32); + let inset = close(near, -1.0, 0.85).max(close(near, 1.0, 0.85)); + if dist / petal_radius < inset { + return Some(Block::new(BlockKind::Wood, Rgb::new(240, 50, 50))); + } + } else { + return Some(Block::new(BlockKind::Wood, Rgb::new(240, 50, 50))); + } + } + + if rpos.z <= flower.stalk + 3.0 + && dist < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / flower.stalk)).powi(2) + { + if flower.stalk - rpos.z - 0.0 + 0.0 >= 0.0 { + return Some(Block::new(BlockKind::Wood, Rgb::new(40, 244, 150))); + } + // Stalk + return Some(Block::new(BlockKind::Wood, Rgb::new(150, 244, 40))); + } + } + } + + None + }; + for z in bedrock..z_range.end { let wpos = wpos2d.with_z(z); let mut try_spawn_entity = false; @@ -841,7 +934,7 @@ fn write_column( Lerp::lerp( Rgb::new(105, 25, 131), Rgb::new(251, 238, 255), - col.marble_mid, + col.marble_small, ), biome.crystal, ), @@ -1039,6 +1132,8 @@ fn write_column( Block::air(sprite) } else if let Some(block) = is_crystal(wpos) { block + } else if let Some(block) = get_flower(wpos) { + block } else { get_mushroom(wpos, rng).unwrap_or(Block::air(SpriteKind::Empty)) } From 993afad63998059ac9475e2e3d780d706f2c7474 Mon Sep 17 00:00:00 2001 From: Syniis Date: Sun, 11 Feb 2024 15:10:30 +0100 Subject: [PATCH 03/24] Use same structure gen for each cave structure --- world/src/layer/cave.rs | 465 +++++++++++++++++++--------------------- 1 file changed, 218 insertions(+), 247 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 85a84275be..a0205c8c35 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -11,12 +11,12 @@ use common::{ SpriteKind, }, }; +use hashbrown::HashMap; use inline_tweak::tweak_fn; use noise::NoiseFn; use rand::prelude::*; use std::{ cmp::Ordering, - collections::HashMap, f64::consts::PI, ops::{Add, Mul, Range, Sub}, }; @@ -92,7 +92,7 @@ impl Tunnel { } #[tweak_fn] - fn z_range_at(&self, wposf: Vec2, info: CanvasInfo) -> Option<(Range, f64)> { + fn z_range_at(&self, wposf: Vec2, info: CanvasInfo) -> Option<(Range, f64, f64)> { let start = self.a.wpos.map(|e| e as f64 + 0.5); let end = self.b.wpos.map(|e| e as f64 + 0.5); @@ -145,6 +145,7 @@ impl Tunnel { Some(( (base - height_here * 0.3) as i32..(base + height_here * 1.35) as i32, vertical, + horizontal, )) } else { None @@ -325,7 +326,8 @@ pub fn tunnel_bounds_at<'a>( tunnels_at(wpos2d, level, land) .chain(tunnels_down_from(wpos2d, level - 1, land)) .filter_map(move |tunnel| { - let (z_range, radius) = tunnel.z_range_at(wposf, *info)?; + let (z_range, vertical, horizontal) = tunnel.z_range_at(wposf, *info)?; + let radius = vertical.min(horizontal); // Avoid cave entrances intersecting water let z_range = Lerp::lerp( z_range.end, @@ -348,9 +350,9 @@ pub fn tunnel_bounds_at<'a>( pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { let info = canvas.info(); - let mut mushroom_cache = HashMap::new(); - let mut crystal_cache = HashMap::new(); - let mut flower_cache = HashMap::new(); + let mut structure_cache = HashMap::new(); + // let mut structure_cache = + // StructureGenCache::::new(StructureGen2d::new(34537, 24, 8)); canvas.foreach_col(|canvas, wpos2d, col| { let land = info.land(); @@ -371,9 +373,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { wpos2d, z_range.clone(), tunnel, - &mut mushroom_cache, - &mut crystal_cache, - &mut flower_cache, + &mut structure_cache, rng, ); } @@ -395,6 +395,12 @@ struct Biome { depth: f32, } +enum CaveStructure { + Mushroom(Mushroom), + Crystal(CrystalCluster), + Flower(Flower), +} + struct Mushroom { pos: Vec3, stalk: f32, @@ -427,13 +433,9 @@ fn write_column( wpos2d: Vec2, z_range: Range, tunnel: Tunnel, - mushroom_cache: &mut HashMap<(Vec3, Vec2), Option>, - crystal_cache: &mut HashMap<(Vec3, Vec2), Option>, - flower_cache: &mut HashMap<(Vec3, Vec2), Option>, + structure_cache: &mut HashMap<(Vec3, Vec2), Option>, rng: &mut R, ) { - mushroom_cache.clear(); - crystal_cache.clear(); let info = canvas.info(); // Exposed to the sky, or some other void above @@ -456,7 +458,7 @@ fn write_column( .mul(2.0) // No stalactites near entrances .mul(((col.alt as f64 - z_range.end as f64) / 8.0).clamped(0.0, 1.0)) - .mul(8.0 + cavern_height * 0.4) + .mul(8.0 + cavern_height * (0.4 + (biome.sandy as f64 - 0.5).max(0.0))) }; let basalt = if biome.fire > 0.0 { @@ -526,25 +528,24 @@ fn write_column( let floor = base + dirt; let ceiling = z_range.end - stalactite as i32; - // Get mushroom block, if any, at a position - let mut get_mushroom = |wpos: Vec3, dynamic_rng: &mut R| { + let mut get_structure = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { - let mushroom = if let Some(mushroom) = mushroom_cache + let structure = if let Some(structure) = structure_cache .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) .or_insert_with(|| { let mut rng = RandomPerm::new(seed); - let (z_range, radius) = + let (z_range, vertical, horizontal) = tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; + let radius = vertical.min(horizontal); let pos = wpos2d.with_z(z_range.start); - if rng.gen_bool(0.5* close(radius as f32, 64.0, 48.0) as f64) + + if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) && tunnel.biome_at(pos, &info).mushroom > 0.5 - // Ensure that we're not placing the mushroom over a void && !tunnel_bounds_at(pos.xy(), &info, &info.land()) .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) - // && pos.z as i32 > water_level - 2 { let purp = rng.gen_range(0..50); - Some(Mushroom { + Some(CaveStructure::Mushroom(Mushroom { pos, stalk: 8.0 + rng.gen::().powf(2.0) @@ -555,116 +556,28 @@ fn write_column( rng.gen_range(60..120), rng.gen_range(80..200) + purp, ), - }) - } else { - None - } - }) { - mushroom - } else { - continue; - }; - - let wposf = wpos.map(|e| e as f64); - let warp_freq = 1.0 / 32.0; - let warp_amp = Vec3::new(12.0, 12.0, 12.0); - let wposf_warped = wposf.map(|e| e as f32) - + Vec3::new( - FastNoise::new(seed).get(wposf * warp_freq), - FastNoise::new(seed + 1).get(wposf * warp_freq), - FastNoise::new(seed + 2).get(wposf * warp_freq), - ) * warp_amp - * (wposf.z as f32 - mushroom.pos.z as f32) - .mul(0.1) - .clamped(0.0, 1.0); - - let rpos = wposf_warped - mushroom.pos.map(|e| e as f32); - - let stalk_radius = 2.5f32; - let head_radius = 12.0f32; - let head_height = 14.0; - - let dist_sq = rpos.xy().magnitude_squared(); - if dist_sq < head_radius.powi(2) { - let dist = dist_sq.sqrt(); - let head_dist = ((rpos - Vec3::unit_z() * mushroom.stalk) - / Vec2::broadcast(head_radius).with_z(head_height)) - .magnitude(); - - let stalk = mushroom.stalk + Lerp::lerp(head_height * 0.5, 0.0, dist / head_radius); - - // Head - if rpos.z > stalk - && rpos.z <= mushroom.stalk + head_height - && dist - < head_radius * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) - { - if head_dist < 0.85 { - let radial = (rpos.x.atan2(rpos.y) * 10.0).sin() * 0.5 + 0.5; - return Some(Block::new( - BlockKind::GlowingMushroom, - Rgb::new(30, 50 + (radial * 100.0) as u8, 100 - (radial * 50.0) as u8), - )); - } else if head_dist < 1.0 { - return Some(Block::new(BlockKind::Wood, mushroom.head_color)); - } - } - - if rpos.z <= mushroom.stalk + head_height - 1.0 - && dist_sq - < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / mushroom.stalk)).powi(2) - { - // Stalk - return Some(Block::new(BlockKind::Wood, Rgb::new(25, 60, 90))); - } else if ((mushroom.stalk - 0.1)..(mushroom.stalk + 0.9)).contains(&rpos.z) // Hanging orbs - && dist > head_radius * 0.85 - && dynamic_rng.gen_bool(0.1) - { - use SpriteKind::*; - let sprites = if dynamic_rng.gen_bool(0.1) { - &[Beehive, Lantern] as &[_] - } else { - &[Orb, CavernMycelBlue, CavernMycelBlue] as &[_] - }; - return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); - } - } - } - - None - }; - - let mut is_crystal = |wpos: Vec3| { - let colors = vec![ - Rgb::new(209, 106, 255), - Rgb::new(187, 86, 240), - Rgb::new(251, 238, 255), - Rgb::new(243, 204, 255), - Rgb::new(231, 154, 255), - ]; - for (wpos2d, seed) in StructureGen2d::new(112358, 20, 8).get(wpos.xy()) { - let cluster = if let Some(crystal) = crystal_cache - .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) - .or_insert_with(|| { - let mut rng = RandomPerm::new(seed); - let (z_range, radius) = - tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; - - let on_ground = rng.gen_bool(0.6); - let pos = wpos2d.with_z(if on_ground { - z_range.start - } else { - z_range.end - }); - - if rng.gen_bool( - 0.65 * close(tunnel.biome_at(pos, &info).crystal, 1.0, 0.7) as f64, - ) && !tunnel_bounds_at(pos.xy(), &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) + })) + } else if rng + .gen_bool(0.8 * close(tunnel.biome_at(pos, &info).crystal, 1.0, 0.7) as f64) + && !tunnel_bounds_at(pos.xy(), &info, &info.land()) + .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) { + let colors = [ + Rgb::new(209, 106, 255), + Rgb::new(187, 86, 240), + Rgb::new(251, 238, 255), + Rgb::new(243, 204, 255), + ]; + let on_ground = rng.gen_bool(0.6); + let pos = wpos2d.with_z(if on_ground { + z_range.start + } else { + z_range.end + }); + let mut crystals: Vec = Vec::new(); - let max_length = (32.0 * close(radius as f32, 64.0, 52.0)).max(12.0); + let max_length = (48.0 * close(radius as f32, 64.0, 52.0)).max(12.0); let main_length = rng.gen_range(8.0..max_length); let main_radius = Lerp::lerp_unclamped( 2.0, @@ -707,146 +620,208 @@ fn write_column( color.g = color.g.saturating_sub(40u8); color.b = color.b.saturating_add(0u8); } - Some(CrystalCluster { + Some(CaveStructure::Crystal(CrystalCluster { pos, crystals, color, - }) - } else { - None - } - }) { - crystal - } else { - continue; - }; - let wposf = wpos.map(|e| e as f32); - let cluster_pos = cluster.pos.map(|e| e as f32); - for crystal in &cluster.crystals { - let line = LineSegment3 { - start: cluster_pos, - end: cluster_pos + crystal.dir * crystal.length, - }; - - let projected = line.projected_point(wposf); - let dist_sq = projected.distance_squared(wposf); - if dist_sq < crystal.radius.powi(2) { - let rpos = wposf - cluster_pos; - let line_length = line.start.distance_squared(line.end); - let taper = if line_length < 0.001 { - 0.0 - } else { - rpos.dot(line.end - line.start) / line_length - }; - - let peak_cutoff = 0.8; - let taper_factor = 0.7; - let peak_taper = 0.3; - - let crystal_radius = if taper > peak_cutoff { - let taper = (taper - peak_cutoff) * 5.0; - Lerp::lerp( - crystal.radius * taper_factor, - crystal.radius * peak_taper, - taper, - ) - } else { - let taper = taper * 1.25; - Lerp::lerp(crystal.radius, crystal.radius * taper_factor, taper) - }; - - if dist_sq < crystal_radius.powi(2) { - return Some(Block::new(BlockKind::GlowingRock, cluster.color)); - } - } - } - } - None - }; - - let mut get_flower = |wpos: Vec3| { - for (wpos2d, seed) in StructureGen2d::new(1602, 32, 8).get(wpos.xy()) { - let flower = if let Some(flower) = flower_cache - .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) - .or_insert_with(|| { - let mut rng = RandomPerm::new(seed); - let (z_range, radius) = - tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; - let pos = wpos2d.with_z(z_range.start); - if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) + })) + } else if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) && tunnel.biome_at(pos, &info).leafy > 0.9 && !tunnel_bounds_at(pos.xy(), &info, &info.land()) .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) { - Some(Flower { + Some(CaveStructure::Flower(Flower { pos, stalk: 8.0 + rng.gen::().powf(2.0) * (z_range.end - z_range.start - 8) as f32 * 0.75, petals: rng.gen_range(1..5) * 2 + 1, - }) + })) } else { None } }) { - flower + structure } else { continue; }; - let wposf = wpos.map(|e| e as f64); - let warp_freq = 1.0 / 32.0; - let warp_amp = Vec3::new(3.0, 3.0, 3.0); - let wposf_warped = wposf.map(|e| e as f32) - + Vec3::new( - FastNoise::new(seed).get(wposf * warp_freq), - FastNoise::new(seed + 1).get(wposf * warp_freq), - FastNoise::new(seed + 2).get(wposf * warp_freq), - ) * warp_amp - * (wposf.z as f32 - flower.pos.z as f32) - .mul(0.1) - .clamped(0.0, 1.0); + match structure { + CaveStructure::Mushroom(mushroom) => { + let wposf = wpos.map(|e| e as f64); + let warp_freq = 1.0 / 32.0; + let warp_amp = Vec3::new(12.0, 12.0, 12.0); + let wposf_warped = wposf.map(|e| e as f32) + + Vec3::new( + FastNoise::new(seed).get(wposf * warp_freq), + FastNoise::new(seed + 1).get(wposf * warp_freq), + FastNoise::new(seed + 2).get(wposf * warp_freq), + ) * warp_amp + * (wposf.z as f32 - mushroom.pos.z as f32) + .mul(0.1) + .clamped(0.0, 1.0); - let rpos = wposf_warped - flower.pos.map(|e| e as f32); + let rpos = wposf_warped - mushroom.pos.map(|e| e as f32); - let stalk_radius = 2.5f32; - let petal_radius = 12.0f32; - let petal_height = 8.0; - let petal_thickness = 3.0; + let stalk_radius = 2.5f32; + let head_radius = 12.0f32; + let head_height = 14.0; - let dist = rpos.xy().magnitude_squared(); - let petal_radius = petal_radius.powi(2); - if dist < petal_radius { - let petal_height_at = (dist / petal_radius).powf(0.5) * petal_height; - if rpos.z > flower.stalk + petal_height_at - && rpos.z <= flower.stalk + petal_height_at + petal_thickness - { - let away = dist / petal_radius; - if away > 0.2 { - let near = (rpos.x.atan2(rpos.y)) - .rem_euclid(std::f32::consts::TAU / flower.petals as f32); - let inset = close(near, -1.0, 0.85).max(close(near, 1.0, 0.85)); - if dist / petal_radius < inset { - return Some(Block::new(BlockKind::Wood, Rgb::new(240, 50, 50))); + let dist_sq = rpos.xy().magnitude_squared(); + if dist_sq < head_radius.powi(2) { + let dist = dist_sq.sqrt(); + let head_dist = ((rpos - Vec3::unit_z() * mushroom.stalk) + / Vec2::broadcast(head_radius).with_z(head_height)) + .magnitude(); + + let stalk = + mushroom.stalk + Lerp::lerp(head_height * 0.5, 0.0, dist / head_radius); + + // Head + if rpos.z > stalk + && rpos.z <= mushroom.stalk + head_height + && dist + < head_radius + * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) + { + if head_dist < 0.85 { + let radial = (rpos.x.atan2(rpos.y) * 10.0).sin() * 0.5 + 0.5; + return Some(Block::new( + BlockKind::GlowingMushroom, + Rgb::new( + 30, + 50 + (radial * 100.0) as u8, + 100 - (radial * 50.0) as u8, + ), + )); + } else if head_dist < 1.0 { + return Some(Block::new(BlockKind::Wood, mushroom.head_color)); + } } - } else { - return Some(Block::new(BlockKind::Wood, Rgb::new(240, 50, 50))); - } - } - if rpos.z <= flower.stalk + 3.0 - && dist < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / flower.stalk)).powi(2) - { - if flower.stalk - rpos.z - 0.0 + 0.0 >= 0.0 { - return Some(Block::new(BlockKind::Wood, Rgb::new(40, 244, 150))); + if rpos.z <= mushroom.stalk + head_height - 1.0 + && dist_sq + < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / mushroom.stalk)) + .powi(2) + { + // Stalk + return Some(Block::new(BlockKind::Wood, Rgb::new(25, 60, 90))); + } else if ((mushroom.stalk - 0.1)..(mushroom.stalk + 0.9)).contains(&rpos.z) // Hanging orbs + && dist > head_radius * 0.85 + && dynamic_rng.gen_bool(0.1) + { + use SpriteKind::*; + let sprites = if dynamic_rng.gen_bool(0.1) { + &[Beehive, Lantern] as &[_] + } else { + &[Orb, CavernMycelBlue, CavernMycelBlue] as &[_] + }; + return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); + } } - // Stalk - return Some(Block::new(BlockKind::Wood, Rgb::new(150, 244, 40))); - } + }, + CaveStructure::Crystal(cluster) => { + let wposf = wpos.map(|e| e as f32); + let cluster_pos = cluster.pos.map(|e| e as f32); + for crystal in &cluster.crystals { + let line = LineSegment3 { + start: cluster_pos, + end: cluster_pos + crystal.dir * crystal.length, + }; + + let projected = line.projected_point(wposf); + let dist_sq = projected.distance_squared(wposf); + if dist_sq < crystal.radius.powi(2) { + let rpos = wposf - cluster_pos; + let line_length = line.start.distance_squared(line.end); + let taper = if line_length < 0.001 { + 0.0 + } else { + rpos.dot(line.end - line.start) / line_length + }; + + let peak_cutoff = 0.8; + let taper_factor = 0.55; + let peak_taper = 0.3; + + let crystal_radius = if taper > peak_cutoff { + let taper = (taper - peak_cutoff) * 5.0; + Lerp::lerp( + crystal.radius * taper_factor, + crystal.radius * peak_taper, + taper, + ) + } else { + let taper = taper * 1.25; + Lerp::lerp(crystal.radius, crystal.radius * taper_factor, taper) + }; + + if dist_sq < crystal_radius.powi(2) { + return Some(Block::new(BlockKind::GlowingRock, cluster.color)); + } + } + } + }, + CaveStructure::Flower(flower) => { + let wposf = wpos.map(|e| e as f64); + let warp_freq = 1.0 / 32.0; + let warp_amp = Vec3::new(3.0, 3.0, 3.0); + let wposf_warped = wposf.map(|e| e as f32) + + Vec3::new( + FastNoise::new(seed).get(wposf * warp_freq), + FastNoise::new(seed + 1).get(wposf * warp_freq), + FastNoise::new(seed + 2).get(wposf * warp_freq), + ) * warp_amp + * (wposf.z as f32 - flower.pos.z as f32) + .mul(0.1) + .clamped(0.0, 1.0); + + let rpos = wposf_warped - flower.pos.map(|e| e as f32); + + let stalk_radius = 2.5f32; + let petal_radius = 12.0f32; + let petal_height = 8.0; + let petal_thickness = 3.0; + + let dist = rpos.xy().magnitude_squared(); + let petal_radius = petal_radius.powi(2); + if dist < petal_radius { + let petal_height_at = (dist / petal_radius).powf(0.5) * petal_height; + if rpos.z > flower.stalk + petal_height_at + && rpos.z <= flower.stalk + petal_height_at + petal_thickness + { + let away = dist / petal_radius; + if away > 0.2 { + let near = (rpos.x.atan2(rpos.y)) + .rem_euclid(std::f32::consts::TAU / flower.petals as f32); + let inset = close(near, -1.0, 0.85).max(close(near, 1.0, 0.85)); + if dist / petal_radius < inset { + return Some(Block::new( + BlockKind::Wood, + Rgb::new(240, 50, 50), + )); + } + } else { + return Some(Block::new(BlockKind::Wood, Rgb::new(240, 50, 50))); + } + } + + if rpos.z <= flower.stalk + 3.0 + && dist + < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / flower.stalk)) + .powi(2) + { + if flower.stalk - rpos.z - 0.0 + 0.0 >= 0.0 { + return Some(Block::new(BlockKind::Wood, Rgb::new(40, 244, 150))); + } + // Stalk + return Some(Block::new(BlockKind::Wood, Rgb::new(150, 244, 40))); + } + } + }, } } - None }; @@ -934,7 +909,7 @@ fn write_column( Lerp::lerp( Rgb::new(105, 25, 131), Rgb::new(251, 238, 255), - col.marble_small, + col.marble_mid, ), biome.crystal, ), @@ -1130,12 +1105,8 @@ fn write_column( .flatten() { Block::air(sprite) - } else if let Some(block) = is_crystal(wpos) { - block - } else if let Some(block) = get_flower(wpos) { - block } else { - get_mushroom(wpos, rng).unwrap_or(Block::air(SpriteKind::Empty)) + get_structure(wpos, rng).unwrap_or(Block::air(SpriteKind::Empty)) } }); From 20aa0dbce44edd6d68bc0cee3066e8b0814ec25f Mon Sep 17 00:00:00 2001 From: Syniis Date: Tue, 13 Feb 2024 15:04:52 +0100 Subject: [PATCH 04/24] Various tweaks to cave generation Changed biome distribution. Improved biome colors. Added cave ridges. Added ceiling cover --- world/src/layer/cave.rs | 327 +++++++++++++++++++++++++-------------- world/src/layer/shrub.rs | 2 +- world/src/layer/tree.rs | 2 +- 3 files changed, 215 insertions(+), 116 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index a0205c8c35..0f31cd593f 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -92,7 +92,11 @@ impl Tunnel { } #[tweak_fn] - fn z_range_at(&self, wposf: Vec2, info: CanvasInfo) -> Option<(Range, f64, f64)> { + fn z_range_at( + &self, + wposf: Vec2, + info: CanvasInfo, + ) -> Option<(Range, f64, f64, f64)> { let start = self.a.wpos.map(|e| e as f64 + 0.5); let end = self.b.wpos.map(|e| e as f64 + 0.5); @@ -108,7 +112,7 @@ impl Tunnel { radius.start, radius.end, (info.index().noise.cave_fbm_nz.get( - (wposf.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 256.0) + (closest.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 256.0) .into_array(), ) + 0.5) .clamped(0.0, 1.0) @@ -118,7 +122,7 @@ impl Tunnel { radius.start, radius.end, (info.index().noise.cave_fbm_nz.get( - (wposf.with_z(info.land().get_alt_approx(self.b.wpos) as f64) / 256.0) + (closest.with_z(info.land().get_alt_approx(self.b.wpos) as f64) / 256.0) .into_array(), ) + 0.5) .clamped(0.0, 1.0) @@ -144,8 +148,9 @@ impl Tunnel { .min(alt_here as f64); Some(( (base - height_here * 0.3) as i32..(base + height_here * 1.35) as i32, - vertical, horizontal, + vertical, + dist, )) } else { None @@ -165,9 +170,12 @@ impl Tunnel { }; // Below the ground - let below = ((col.alt - wpos.z as f32) / AVG_LEVEL_DEPTH as f32).clamped(0.0, 1.0); + let below = ((col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * 2.0)).clamped(0.0, 1.0); let depth = (col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32); + let underground = ((col.alt - wpos.z as f32) / 100.0 - 1.0).clamped(0.0, 1.0); + // TODO think about making rate of change of humidity and temp noise higher to + // effectively increase biome size let humidity = Lerp::lerp( col.humidity, info.index() @@ -176,6 +184,7 @@ impl Tunnel { .get(wpos.xy().map(|e| e as f64 / 1024.0).into_array()) as f32, below, ); + let temp = Lerp::lerp( col.temp, info.index() @@ -191,6 +200,7 @@ impl Tunnel { ) as f32, below, ); + let mineral = info .index() .noise @@ -198,31 +208,59 @@ impl Tunnel { .get(wpos.xy().map(|e| e as f64 / 512.0).into_array()) .mul(0.5) .add( - ((col.alt as f64 - wpos.z as f64) / (AVG_LEVEL_DEPTH as f64 * LAYERS as f64 * 0.5)) - .clamped(0.0, 2.0), + ((col.alt as f64 - wpos.z as f64) / (AVG_LEVEL_DEPTH as f64 * LAYERS as f64)) + .clamped(0.0, 1.5), ) as f32; - let underground = ((col.alt - wpos.z as f32) / 80.0 - 1.0).clamped(0.0, 1.0); - - let [barren, mushroom, fire, leafy, dusty, icy, crystal, sandy] = { + let [ + barren, + mushroom, + fire, + leafy, + dusty, + icy, + snowy, + crystal, + sandy, + ] = { + // Default biome, no other conditions apply let barren = 0.01; - let mushroom = underground * close(humidity, 1.0, 0.75) * close(temp, 0.0, 0.9); + // Mushrooms grow underground and thrive in a humid environment with moderate + // temperatures + let mushroom = underground + * close(humidity, 1.0, 0.7) + * close(temp, 0.25, 1.0) + * close(depth, 0.7, 1.0); + // Extremely hot and dry areas deep underground let fire = underground * close(humidity, 0.0, 0.9) - * close(temp, 2.0, 1.0) + * close(temp, 2.5, 1.5) * close(depth, 1.0, 0.65); - let leafy = underground * close(humidity, 1.0, 0.85) * close(temp, 0.45, 0.8); + // Overgrown with plants that need a moderate climate to survive + let leafy = underground + * close(humidity, 0.5, 0.7) + * close(temp, 0.6, 0.9) + * close(depth, 0.1, 0.7); + // Cool temperature, dry and devoid of value let dusty = - close(humidity, 0.0, 0.2) * close(temp, -0.4, 0.5) * close(mineral, 0.0, 0.6); - let icy = close(temp, -1.0, 0.3); + close(humidity, 0.0, 0.4) * close(temp, -0.3, 0.65) * close(mineral, -0.5, 1.5); + // Deep underground and freezing cold + let icy = underground * close(temp, -1.0, 0.3) * close(depth, 1.0, 0.5); + // Rocky cold cave that appear near the surface + let snowy = close(temp, -0.7, 0.5) * close(depth, 0.1, 0.4); + // Crystals grow deep underground in areas rich with minerals. They are present + // in areas with colder temperatures and low humidity let crystal = underground - * (close(humidity, 0.0, 0.5).max(close(humidity, 1.0, 0.5))) - * (close(temp, 1.6, 0.9).max(close(temp, -1.0, 0.3))) - * close(depth, 1.0, 0.6) - * close(mineral, 2.5, 2.0); - let sandy = close(humidity, 0.1, 0.2) * close(temp, 0.0, 0.4) * close(depth, 0.4, 0.4); + * close(humidity, 0.0, 0.65) + * close(temp, -0.1, 1.0) + * close(depth, 1.0, 0.45) + * close(mineral, 1.5, 1.0); + // Hot, dry and shallow + let sandy = close(humidity, 0.0, 0.2) * close(temp, 0.7, 0.8) * close(depth, 0.1, 0.5); - let biomes = [barren, mushroom, fire, leafy, dusty, icy, crystal, sandy]; + let biomes = [ + barren, mushroom, fire, leafy, dusty, icy, snowy, crystal, sandy, + ]; let max = biomes .into_iter() .max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)) @@ -239,6 +277,7 @@ impl Tunnel { leafy, dusty, icy, + snowy, crystal, sandy, depth, @@ -317,7 +356,7 @@ pub fn tunnel_bounds_at<'a>( wpos2d: Vec2, info: &'a CanvasInfo, land: &'a Land, -) -> impl Iterator, f64, Tunnel)> + 'a { +) -> impl Iterator, f64, f64, f64, Tunnel)> + 'a { let wposf = wpos2d.map(|e| e as f64 + 0.5); info.col_or_gen(wpos2d).into_iter().flat_map(move |col| { let col_alt = col.alt; @@ -326,8 +365,7 @@ pub fn tunnel_bounds_at<'a>( tunnels_at(wpos2d, level, land) .chain(tunnels_down_from(wpos2d, level - 1, land)) .filter_map(move |tunnel| { - let (z_range, vertical, horizontal) = tunnel.z_range_at(wposf, *info)?; - let radius = vertical.min(horizontal); + let (z_range, horizontal, vertical, dist) = tunnel.z_range_at(wposf, *info)?; // Avoid cave entrances intersecting water let z_range = Lerp::lerp( z_range.end, @@ -339,7 +377,7 @@ pub fn tunnel_bounds_at<'a>( - ((col_alt - z_range.end as f32 - 4.0) / 8.0).clamped(0.0, 1.0)), )..z_range.end; if z_range.end - z_range.start > 0 { - Some((level, z_range, radius, tunnel)) + Some((level, z_range, horizontal, vertical, dist, tunnel)) } else { None } @@ -351,21 +389,19 @@ pub fn tunnel_bounds_at<'a>( pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { let info = canvas.info(); let mut structure_cache = HashMap::new(); - // let mut structure_cache = - // StructureGenCache::::new(StructureGen2d::new(34537, 24, 8)); canvas.foreach_col(|canvas, wpos2d, col| { let land = info.land(); let tunnel_bounds = tunnel_bounds_at(wpos2d, &info, &land).collect::>(); // First, clear out tunnels - for (_, z_range, _, _) in &tunnel_bounds { + for (_, z_range, _, _, _, _) in &tunnel_bounds { for z in z_range.start..z_range.end.min(col.alt as i32 + 1) { canvas.set(wpos2d.with_z(z), Block::air(SpriteKind::Empty)); } } - for (level, z_range, _radius, tunnel) in tunnel_bounds { + for (level, z_range, horizontal, vertical, dist, tunnel) in tunnel_bounds { write_column( canvas, col, @@ -373,6 +409,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { wpos2d, z_range.clone(), tunnel, + (horizontal, vertical, dist), &mut structure_cache, rng, ); @@ -390,6 +427,7 @@ struct Biome { leafy: f32, dusty: f32, icy: f32, + snowy: f32, crystal: f32, sandy: f32, depth: f32, @@ -423,6 +461,7 @@ struct Flower { pos: Vec3, stalk: f32, petals: usize, + petal_height: f32, } #[inline_tweak::tweak_fn] @@ -433,6 +472,7 @@ fn write_column( wpos2d: Vec2, z_range: Range, tunnel: Tunnel, + dimensions: (f64, f64, f64), structure_cache: &mut HashMap<(Vec3, Vec2), Option>, rng: &mut R, ) { @@ -443,26 +483,40 @@ fn write_column( let void_below = !canvas.get(wpos2d.with_z(z_range.start - 1)).is_filled(); // Exposed to the sky let sky_above = z_range.end as f32 > col.alt; - + let cavern_height = (z_range.end - z_range.start) as f64; + let (cave_width, max_height, dist_cave_center) = dimensions; let biome = tunnel.biome_at(wpos2d.with_z(z_range.start), &info); let stalactite = { - let cavern_height = (z_range.end - z_range.start) as f64; info .index() .noise .cave_nz .get(wpos2d.map(|e| e as f64 / 16.0).into_array()) - .sub(0.5) + .sub(0.5 + (biome.leafy - 1.0).max(0.0) as f64) .max(0.0) .mul(2.0) + .add((biome.leafy - 1.0).max(0.0) as f64) // No stalactites near entrances .mul(((col.alt as f64 - z_range.end as f64) / 8.0).clamped(0.0, 1.0)) .mul(8.0 + cavern_height * (0.4 + (biome.sandy as f64 - 0.5).max(0.0))) }; + let ceiling_cover = if (biome.leafy - 0.3) + .max(biome.mushroom - 0.5) + .max(biome.snowy - 0.6) + .max(biome.crystal - 0.9) + .max(biome.sandy - 0.5) + > 0.0 + { + 1.0.mul(((col.alt - z_range.end as f32) / 8.0).clamped(0.0, 1.0)) + .mul(4.0 * (dist_cave_center / (cave_width)).powf(3.33) as f32) + .max(1.0) + } else { + 0.0 + }; + let basalt = if biome.fire > 0.0 { - let cavern_height = (z_range.end - z_range.start) as f64; info.index() .noise .cave_nz @@ -492,41 +546,60 @@ fn write_column( 0.0 }; - let bump = { - let cavern_height = (z_range.end - z_range.start) as f64; - info.index() - .noise - .cave_nz - .get(wpos2d.map(|e| e as f64 / 8.0).into_array()) - .add(1.0) - .mul(0.5) - .mul(((col.alt as f64 - z_range.end as f64) / 16.0).clamped(0.0, 1.0)) - .mul({ - let (val, total) = [ - (biome.sandy as f64 - 0.2, 0.9), - (biome.dusty as f64 - 0.1, 0.5), - (biome.icy as f64 - 0.1, 0.1), - (biome.leafy as f64 - 0.2, 0.8), - (biome.barren as f64 - 0.15, 0.6), - (biome.mushroom as f64 - 0.3, 0.2), - (biome.fire as f64 - 0.5, 0.2), - ] - .into_iter() - .fold((0.0, 0.0), |a, x| (a.0 + x.0.max(0.0) * x.1, a.1 + x.1)); - val / total - }) - .mul(0.0 + cavern_height * 0.4) - }; + let height_factor = (max_height / 24.0).clamped(0.0, 1.0).powf(2.0); + let width_factor = (cave_width / 16.0).clamped(0.0, 1.0).powf(2.0); + let ridge = info + .index() + .noise + .cave_nz + .get(wpos2d.map(|e| e as f64 / 512.0).into_array()) + .sub(0.25) + .max(0.0) + .mul(1.3) + .mul(height_factor) + .mul(width_factor) + .mul( + (0.75 * dist_cave_center) + + max_height + * (close( + dist_cave_center as f32, + cave_width as f32, + cave_width as f32 * 0.75, + )) as f64, + ); + + let bump = info + .index() + .noise + .cave_nz + .get(wpos2d.map(|e| e as f64 / 8.0).into_array()) + .add(1.0) + .mul(0.5) + .mul(((col.alt as f64 - z_range.end as f64) / 16.0).clamped(0.0, 1.0)) + .mul({ + let (val, total) = [ + (biome.sandy as f64 - 0.3, 0.9), + (biome.dusty as f64 - 0.2, 0.5), + (biome.leafy as f64 - 0.5, 0.6), + (biome.barren as f64 - 0.1, 0.6), + ] + .into_iter() + .fold((0.0, 0.0), |a, x| (a.0 + x.0.max(0.0) * x.1, a.1 + x.1)); + val / total + }) + .mul(cavern_height * 0.4); let rand = RandomField::new(37 + level); let is_ice = biome.icy + col.marble * 0.2 > 0.5 && col.marble > 0.6; + let is_snow = biome.snowy + col.marble_mid * 0.2 > 0.5 && col.marble_mid > 0.6; - let dirt = 1 + (!is_ice) as i32; + let dirt = 1 + (!is_ice) as i32 + (is_snow) as i32; let bedrock = z_range.start + lava as i32; - let base = bedrock + (stalactite * 0.4) as i32 + bump as i32; - let floor = base + dirt; - let ceiling = z_range.end - stalactite as i32; + let ridge_bedrock = bedrock + (ridge * 0.7) as i32; + let base = ridge_bedrock + (stalactite * 0.4) as i32; + let floor = base + dirt + (ridge * 0.3) as i32 + bump as i32; + let ceiling = z_range.end - stalactite as i32 - ceiling_cover as i32; let mut get_structure = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { @@ -534,15 +607,21 @@ fn write_column( .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) .or_insert_with(|| { let mut rng = RandomPerm::new(seed); - let (z_range, vertical, horizontal) = + let (z_range, _, vertical, _) = tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; - let radius = vertical.min(horizontal); let pos = wpos2d.with_z(z_range.start); - if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) - && tunnel.biome_at(pos, &info).mushroom > 0.5 - && !tunnel_bounds_at(pos.xy(), &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) + let biome = tunnel.biome_at(pos, &info); + let ground_below = !tunnel_bounds_at(pos.xy(), &info, &info.land()) + .any(|(_, z_range, _, _, _, _)| z_range.contains(&(z_range.start - 1))); + if !ground_below { + return None; + } + + if rng.gen_bool( + 0.5 * close(vertical as f32, 64.0, 48.0) as f64 + * close(biome.mushroom, 1.0, 0.7) as f64, + ) && biome.mushroom > 0.5 { let purp = rng.gen_range(0..50); Some(CaveStructure::Mushroom(Mushroom { @@ -557,11 +636,7 @@ fn write_column( rng.gen_range(80..200) + purp, ), })) - } else if rng - .gen_bool(0.8 * close(tunnel.biome_at(pos, &info).crystal, 1.0, 0.7) as f64) - && !tunnel_bounds_at(pos.xy(), &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) - { + } else if rng.gen_bool(0.6 * close(biome.crystal, 1.0, 0.7) as f64) { let colors = [ Rgb::new(209, 106, 255), Rgb::new(187, 86, 240), @@ -577,7 +652,7 @@ fn write_column( let mut crystals: Vec = Vec::new(); - let max_length = (48.0 * close(radius as f32, 64.0, 52.0)).max(12.0); + let max_length = (48.0 * close(vertical as f32, 64.0, 42.0)).max(12.0); let main_length = rng.gen_range(8.0..max_length); let main_radius = Lerp::lerp_unclamped( 2.0, @@ -588,7 +663,7 @@ fn write_column( let main_dir = Vec3::new( rng.gen_range(-3.0..3.0), rng.gen_range(-3.0..3.0), - rng.gen_range(0.0..10.0) * if on_ground { 1.0 } else { -1.0 }, + rng.gen_range(0.5..10.0) * if on_ground { 1.0 } else { -1.0 }, ) .normalized(); @@ -625,18 +700,19 @@ fn write_column( crystals, color, })) - } else if rng.gen_bool(0.5 * close(radius as f32, 64.0, 48.0) as f64) - && tunnel.biome_at(pos, &info).leafy > 0.9 - && !tunnel_bounds_at(pos.xy(), &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(z_range.start - 1))) + } else if rng.gen_bool( + 0.2 * close(vertical as f32, 64.0, 48.0) as f64 + * close(biome.leafy, 1.5, 0.8) as f64, + ) && biome.leafy > 0.8 { Some(CaveStructure::Flower(Flower { pos, - stalk: 8.0 + stalk: 4.0 + rng.gen::().powf(2.0) * (z_range.end - z_range.start - 8) as f32 - * 0.75, + * 0.6, petals: rng.gen_range(1..5) * 2 + 1, + petal_height: rng.gen_range(4.0..8.0), })) } else { None @@ -766,7 +842,7 @@ fn write_column( CaveStructure::Flower(flower) => { let wposf = wpos.map(|e| e as f64); let warp_freq = 1.0 / 32.0; - let warp_amp = Vec3::new(3.0, 3.0, 3.0); + let warp_amp = Vec3::new(4.0, 4.0, 4.0); let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( FastNoise::new(seed).get(wposf * warp_freq), @@ -781,18 +857,17 @@ fn write_column( let stalk_radius = 2.5f32; let petal_radius = 12.0f32; - let petal_height = 8.0; - let petal_thickness = 3.0; + let petal_thickness = 2.5; let dist = rpos.xy().magnitude_squared(); let petal_radius = petal_radius.powi(2); if dist < petal_radius { - let petal_height_at = (dist / petal_radius).powf(0.5) * petal_height; - if rpos.z > flower.stalk + petal_height_at + let petal_height_at = (dist / petal_radius).powf(1.5) * flower.petal_height; + if rpos.z > flower.stalk + petal_height_at - 1.0 && rpos.z <= flower.stalk + petal_height_at + petal_thickness { let away = dist / petal_radius; - if away > 0.2 { + if away > 0.3 { let near = (rpos.x.atan2(rpos.y)) .rem_euclid(std::f32::consts::TAU / flower.petals as f32); let inset = close(near, -1.0, 0.85).max(close(near, 1.0, 0.85)); @@ -807,16 +882,25 @@ fn write_column( } } - if rpos.z <= flower.stalk + 3.0 + let above_stalk = rpos.z - flower.stalk; + if above_stalk < 0.0 && dist - < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / flower.stalk)) + < (stalk_radius * Lerp::lerp(1.0, 0.75, rpos.z / flower.stalk)) .powi(2) { - if flower.stalk - rpos.z - 0.0 + 0.0 >= 0.0 { - return Some(Block::new(BlockKind::Wood, Rgb::new(40, 244, 150))); - } - // Stalk - return Some(Block::new(BlockKind::Wood, Rgb::new(150, 244, 40))); + return Some(Block::new(BlockKind::Wood, Rgb::new(0, 108, 0))); + } + + // pollen + let pollen_height = 5.0; + if above_stalk > 0.0 + && above_stalk < pollen_height + && dist + < (stalk_radius + * Lerp::lerp(0.5, 1.25, above_stalk / pollen_height)) + .powi(2) + { + return Some(Block::new(BlockKind::Wood, Rgb::new(239, 192, 0))); } } }, @@ -842,34 +926,44 @@ fn write_column( && !void_below { Block::new(BlockKind::Rock, Rgb::new(50, 35, 75)) + } else if z < ridge_bedrock && !void_below { + Block::new(BlockKind::Rock, col.stone_col) } else if (z < base && !void_below) || (z >= ceiling && !void_above) { let stalactite: Rgb = Lerp::lerp( Lerp::lerp( Lerp::lerp( Lerp::lerp( - Rgb::new(80, 100, 150), - Rgb::new(0, 75, 200), - biome.mushroom, + Lerp::lerp( + Rgb::new(80, 100, 150), + Rgb::new(0, 75, 200), + biome.mushroom, + ), + Lerp::lerp( + Rgb::new(100, 40, 40), + Rgb::new(100, 75, 100), + col.marble_small, + ), + biome.fire, ), Lerp::lerp( - Rgb::new(100, 40, 40), - Rgb::new(100, 75, 100), - col.marble_small, + Rgb::new(238, 198, 139), + Rgb::new(111, 99, 64), + col.marble_mid, ), - biome.fire, + biome.sandy, ), Lerp::lerp( - Rgb::new(238, 198, 139), - Rgb::new(111, 99, 64), - col.marble_mid, + Rgb::new(0, 100, 50), + Rgb::new(80, 100, 20), + col.marble_small, ), - biome.sandy, + biome.leafy, ), Lerp::lerp(Rgb::new(100, 150, 255), Rgb::new(100, 120, 255), col.marble), biome.icy, ); Block::new( - if rand.chance(wpos, (biome.mushroom * biome.mineral).max(biome.icy)) { + if rand.chance(wpos, (biome.mushroom * biome.mineral * 0.5).max(biome.icy)) { BlockKind::GlowingWeakRock } else if rand.chance(wpos, biome.sandy) { BlockKind::Sand @@ -881,11 +975,11 @@ fn write_column( } else if z >= base && z < floor && !void_below && !sky_above { let (net_col, total) = [ ( - Lerp::lerp(Rgb::new(40, 20, 0), Rgb::new(80, 80, 30), col.marble_small), + Lerp::lerp(Rgb::new(68, 62, 58), Rgb::new(97, 95, 85), col.marble_small), 0.05, ), ( - Lerp::lerp(Rgb::new(50, 50, 75), Rgb::new(75, 75, 50), col.marble_mid), + Lerp::lerp(Rgb::new(66, 37, 30), Rgb::new(88, 62, 45), col.marble_mid), biome.dusty, ), ( @@ -921,6 +1015,11 @@ fn write_column( ), biome.sandy, ), + ( + // Same as barren + Lerp::lerp(Rgb::new(68, 62, 58), Rgb::new(97, 95, 85), col.marble_small), + biome.snowy, + ), ] .into_iter() .fold((Rgb::::zero(), 0.0), |a, x| { @@ -930,13 +1029,15 @@ fn write_column( if is_ice { Block::new(BlockKind::Ice, Rgb::new(120, 160, 255)) + } else if is_snow { + Block::new(BlockKind::Snow, Rgb::new(170, 195, 255)) } else { Block::new( if biome.mushroom.max(biome.leafy) > 0.5 { BlockKind::Grass } else if biome.icy > 0.5 { BlockKind::Snow - } else if biome.fire > 0.5 { + } else if biome.fire.max(biome.snowy) > 0.5 { BlockKind::Rock } else if biome.crystal > 0.5 { BlockKind::GlowingRock @@ -1001,7 +1102,7 @@ fn write_column( .map(|s| s.0) } else if rand.chance( wpos2d.with_z(3), - close(biome.humidity, 0.0, 0.5) * biome.mineral.max(biome.crystal) * 0.005, + close(biome.humidity, 0.0, 0.5) * biome.mineral * 0.0025, ) { Some(SpriteKind::CrystalLow) } else if rand.chance(wpos2d.with_z(13), biome.fire * 0.001) { @@ -1088,15 +1189,13 @@ fn write_column( } else if rand.chance(wpos2d.with_z(4), biome.leafy * 0.015) { [ (SpriteKind::Liana, 1.0), - (SpriteKind::Orb, 0.35), + (SpriteKind::Orb, 1.7), (SpriteKind::CrystalHigh, 0.1), ] .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand - .chance(wpos2d.with_z(5), biome.mineral.max(biome.crystal) * 0.0075) - { + } else if rand.chance(wpos2d.with_z(5), biome.mineral * 0.005) { Some(*[SpriteKind::CrystalHigh].choose(rng).unwrap()) } else { None diff --git a/world/src/layer/shrub.rs b/world/src/layer/shrub.rs index e823281a7a..7458da215c 100644 --- a/world/src/layer/shrub.rs +++ b/world/src/layer/shrub.rs @@ -46,7 +46,7 @@ pub fn apply_shrubs_to(canvas: &mut Canvas, _dynamic_rng: &mut impl Rng) { && col.spawn_rate > 0.9 && col.path.map_or(true, |(d, _, _, _)| d > 6.0) && !tunnel_bounds_at(wpos, &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(col.alt as i32 - 1))) + .any(|(_, z_range, _, _, _, _)| z_range.contains(&(col.alt as i32 - 1))) { let kind = *info .chunks() diff --git a/world/src/layer/tree.rs b/world/src/layer/tree.rs index 5398f65a3f..55d5ae4d17 100644 --- a/world/src/layer/tree.rs +++ b/world/src/layer/tree.rs @@ -47,7 +47,7 @@ pub fn tree_valid_at( || col.path.map(|(d, _, _, _)| d < 12.0).unwrap_or(false) || info.map_or(false, |info| { tunnel_bounds_at(wpos, &info, &info.land()) - .any(|(_, z_range, _, _)| z_range.contains(&(col.alt as i32 - 2))) + .any(|(_, z_range, _, _, _, _)| z_range.contains(&(col.alt as i32 - 2))) }) { return false; From 6ecfa73c85ea880e9a1840972c413b877556e3a6 Mon Sep 17 00:00:00 2001 From: Syniis Date: Wed, 14 Feb 2024 01:15:57 +0100 Subject: [PATCH 05/24] Small biome tweaks and added patches in ceiling cover --- world/src/layer/cave.rs | 45 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 0f31cd593f..2063369432 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -230,24 +230,24 @@ impl Tunnel { let mushroom = underground * close(humidity, 1.0, 0.7) * close(temp, 0.25, 1.0) - * close(depth, 0.7, 1.0); + * close(depth, 0.8, 0.5); // Extremely hot and dry areas deep underground let fire = underground - * close(humidity, 0.0, 0.9) + * close(humidity, 0.0, 0.7) * close(temp, 2.5, 1.5) * close(depth, 1.0, 0.65); // Overgrown with plants that need a moderate climate to survive let leafy = underground - * close(humidity, 0.5, 0.7) + * close(humidity, 0.6, 0.4) * close(temp, 0.6, 0.9) - * close(depth, 0.1, 0.7); + * close(depth, 0.1, 0.6); // Cool temperature, dry and devoid of value let dusty = close(humidity, 0.0, 0.4) * close(temp, -0.3, 0.65) * close(mineral, -0.5, 1.5); // Deep underground and freezing cold let icy = underground * close(temp, -1.0, 0.3) * close(depth, 1.0, 0.5); // Rocky cold cave that appear near the surface - let snowy = close(temp, -0.7, 0.5) * close(depth, 0.1, 0.4); + let snowy = close(temp, -0.6, 0.3) * close(depth, 0.1, 0.4); // Crystals grow deep underground in areas rich with minerals. They are present // in areas with colder temperatures and low humidity let crystal = underground @@ -504,14 +504,29 @@ fn write_column( let ceiling_cover = if (biome.leafy - 0.3) .max(biome.mushroom - 0.5) - .max(biome.snowy - 0.6) - .max(biome.crystal - 0.9) + .max(biome.icy - 0.6) .max(biome.sandy - 0.5) + .max(biome.fire - 0.5) > 0.0 { - 1.0.mul(((col.alt - z_range.end as f32) / 8.0).clamped(0.0, 1.0)) - .mul(4.0 * (dist_cave_center / (cave_width)).powf(3.33) as f32) + 1.0.mul(((col.alt as f64 - z_range.end as f64) / 8.0).clamped(0.0, 1.0)) + .mul(cavern_height * (dist_cave_center / (cave_width)).powf(3.33)) .max(1.0) + .sub( + if col.marble_mid + > biome + .fire + .max(biome.icy - 0.6) + .max(biome.sandy - 0.3) + .max(biome.leafy - 0.4) + .max(biome.mushroom - 0.5) + { + cavern_height * col.marble_mid as f64 + } else { + 0.0 + }, + ) + .max(0.0) } else { 0.0 }; @@ -546,8 +561,8 @@ fn write_column( 0.0 }; - let height_factor = (max_height / 24.0).clamped(0.0, 1.0).powf(2.0); - let width_factor = (cave_width / 16.0).clamped(0.0, 1.0).powf(2.0); + let height_factor = (max_height / 32.0).clamped(0.0, 1.0).powf(2.0); + let width_factor = (cave_width / 32.0).clamped(0.0, 1.0).powf(2.0); let ridge = info .index() .noise @@ -564,7 +579,7 @@ fn write_column( * (close( dist_cave_center as f32, cave_width as f32, - cave_width as f32 * 0.75, + cave_width as f32 * 0.7, )) as f64, ); @@ -594,12 +609,12 @@ fn write_column( let is_ice = biome.icy + col.marble * 0.2 > 0.5 && col.marble > 0.6; let is_snow = biome.snowy + col.marble_mid * 0.2 > 0.5 && col.marble_mid > 0.6; - let dirt = 1 + (!is_ice) as i32 + (is_snow) as i32; + let dirt = 1 + (!is_ice) as i32 + is_snow as i32; let bedrock = z_range.start + lava as i32; let ridge_bedrock = bedrock + (ridge * 0.7) as i32; let base = ridge_bedrock + (stalactite * 0.4) as i32; let floor = base + dirt + (ridge * 0.3) as i32 + bump as i32; - let ceiling = z_range.end - stalactite as i32 - ceiling_cover as i32; + let ceiling = z_range.end - stalactite.max(ceiling_cover) as i32; let mut get_structure = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { @@ -1189,7 +1204,7 @@ fn write_column( } else if rand.chance(wpos2d.with_z(4), biome.leafy * 0.015) { [ (SpriteKind::Liana, 1.0), - (SpriteKind::Orb, 1.7), + (SpriteKind::Orb, 0.5), (SpriteKind::CrystalHigh, 0.1), ] .choose_weighted(rng, |(_, w)| *w) From e64d88e540ef3aa1ef09b8bed83e8dc3e1050196 Mon Sep 17 00:00:00 2001 From: Syniis Date: Thu, 15 Feb 2024 15:24:07 +0100 Subject: [PATCH 06/24] Mushroom ceiling mold --- world/src/layer/cave.rs | 44 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 2063369432..4b87d671f7 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -238,9 +238,9 @@ impl Tunnel { * close(depth, 1.0, 0.65); // Overgrown with plants that need a moderate climate to survive let leafy = underground - * close(humidity, 0.6, 0.4) + * close(humidity, 0.5, 0.3) * close(temp, 0.6, 0.9) - * close(depth, 0.1, 0.6); + * close(depth, 0.1, 0.5); // Cool temperature, dry and devoid of value let dusty = close(humidity, 0.0, 0.4) * close(temp, -0.3, 0.65) * close(mineral, -0.5, 1.5); @@ -924,8 +924,40 @@ fn write_column( None }; + let ceiling_mold = |wpos: Vec3| { + let wpos = wpos + wpos.xy().yx().with_z(0.0) * 0.2; + let dims = Vec2::new(3.0, 24.0); + let vine_posf = wpos + Vec2::unit_y() * (wpos.x / dims.x).floor() * 71.0 / dims; + let vine_pos = vine_posf.map(|e| e.floor() as i32); + let mut rng = RandomPerm::new(((vine_pos.x << 16) | vine_pos.y) as u32); + + if rng.gen_bool( + 0.15 * close(biome.mushroom, 1.0, 0.2) as f64 + * close(max_height as f32, 64.0, 56.0) as f64, + ) && ceiling_cover > 0.0 + { + let vine_base = z_range.end as f32; + let vine_y = (vine_posf.y.fract() - 0.5).abs() * 2.0 * dims.y; + let vine_reach = (vine_y * 0.05).powf(2.0).min(32.0); + let vine_z = vine_base - vine_reach; + + if Vec2::new(vine_posf.x.fract() * 2.0 - 1.0, (vine_z - wpos.z) / 4.0) + .magnitude_squared() + < 1.0f32 + { + let kind = BlockKind::GlowingMushroom; + Some(Block::new(kind, Rgb::new(0, 95, 200))) + } else { + None + } + } else { + None + } + }; + for z in bedrock..z_range.end { let wpos = wpos2d.with_z(z); + let wposf = wpos.map(|e| e as f32); let mut try_spawn_entity = false; canvas.map_resource(wpos, |_block| { if z < z_range.start - 4 && !void_below { @@ -1219,8 +1251,14 @@ fn write_column( .flatten() { Block::air(sprite) + } else if let Some(vine) = + ceiling_mold(wposf).or_else(|| ceiling_mold(wposf.xy().yx().with_z(wposf.z))) + { + vine + } else if let Some(structure_block) = get_structure(wpos, rng) { + structure_block } else { - get_structure(wpos, rng).unwrap_or(Block::air(SpriteKind::Empty)) + Block::empty() } }); From 6c5dc11d0d460bbb7b31965af655cf9845502c91 Mon Sep 17 00:00:00 2001 From: Syniis Date: Fri, 16 Feb 2024 20:12:23 +0100 Subject: [PATCH 07/24] Added new cave assets --- .cargo/config | 2 +- .../voxel/sprite/cave/cave_flower-0.vox | 3 + .../voxel/sprite/cave/cave_flower-1.vox | 3 + .../voxel/sprite/cave/cave_flower-2.vox | 3 + .../voxel/sprite/cave/cave_flower-3.vox | 3 + .../sprite/cave/cave_lantern_flower-0.vox | 3 + .../sprite/cave/cave_lantern_flower-1.vox | 3 + .../sprite/cave/cave_lantern_flower-2.vox | 3 + .../sprite/cave/cave_lantern_plant-0.vox | 3 + .../sprite/cave/cave_lantern_plant-1.vox | 3 + .../sprite/cave/cave_lantern_plant-2.vox | 3 + .../cave/ceiling/cave_lantern_flower-0.vox | 3 + .../cave/ceiling/cave_lantern_flower-1.vox | 3 + .../cave/ceiling/cave_lantern_flower-2.vox | 3 + .../cave/ceiling/cave_lantern_plant-0.vox | 3 + .../cave/ceiling/cave_lantern_plant-1.vox | 3 + .../voxel/sprite/cave/ceiling/mold-4.vox | 4 +- .../voxel/sprite/cave/ceiling/mold-5.vox | 4 +- .../voxel/sprite/cave/ceiling/mold-6.vox | 4 +- .../voxel/sprite/cave/ceiling/mycel-0.vox | 3 + .../voxel/sprite/cave/ceiling/mycel-1.vox | 3 + .../voxel/sprite/cave/ceiling/mycel-2.vox | 3 + .../voxel/sprite/cave/ceiling/mycel-3.vox | 3 + .../voxel/sprite/cave/ceiling/root-0.vox | 3 + .../voxel/sprite/cave/ceiling/root-1.vox | 3 + .../voxel/sprite/cave/ceiling/root-2.vox | 3 + .../voxel/sprite/cave/ceiling/root-3.vox | 3 + .../voxel/sprite/cave/ceiling/root-4.vox | 3 + .../voxel/sprite/cave/ceiling/root-5.vox | 3 + .../voxel/sprite/cave/ceiling/root-6.vox | 3 + .../voxel/sprite/cave/grass_blue_long-0.vox | 3 + .../voxel/sprite/cave/grass_blue_long-1.vox | 3 + .../voxel/sprite/cave/grass_blue_long-2.vox | 3 + .../voxel/sprite/cave/grass_blue_long-3.vox | 3 + .../voxel/sprite/cave/grass_blue_long-4.vox | 3 + .../voxel/sprite/cave/grass_blue_long-5.vox | 3 + .../voxel/sprite/cave/grass_blue_long-6.vox | 3 + .../voxel/sprite/cave/grass_blue_long-7.vox | 3 + .../voxel/sprite/cave/grass_blue_med-0.vox | 3 + .../voxel/sprite/cave/grass_blue_med-1.vox | 3 + .../voxel/sprite/cave/grass_blue_med-2.vox | 3 + .../voxel/sprite/cave/grass_blue_med-3.vox | 3 + .../grass_blue_short-0.vox} | 0 .../grass_blue_short-1.vox} | 0 .../grass_blue_short-2.vox} | 0 .../grass_blue_short-3.vox} | 0 .../grass_blue_short-4.vox} | 0 .../voxygen/voxel/sprite/cave/mushroom-10.vox | 3 + .../voxygen/voxel/sprite/cave/mushroom-11.vox | 3 + .../voxygen/voxel/sprite/cave/mushroom-9.vox | 3 + .../voxel/sprite/cave/spore_reed-0.vox | 3 + .../voxel/sprite/cave/spore_reed-1.vox | 3 + .../voxel/sprite/cave/spore_reed-2.vox | 3 + .../voxel/sprite/cave/spore_reed-3.vox | 3 + .../voxel/sprite/cavern/grass_long-0.vox | 3 - .../voxel/sprite/cavern/grass_long-1.vox | 3 - .../voxel/sprite/cavern/grass_long-2.vox | 3 - .../voxel/sprite/cavern/grass_long-3.vox | 3 - .../voxel/sprite/cavern/grass_long-4.vox | 3 - .../voxel/sprite/cavern/grass_long-5.vox | 3 - .../voxel/sprite/cavern/grass_long-6.vox | 3 - .../voxel/sprite/cavern/grass_long-7.vox | 3 - .../voxel/sprite/cavern/grass_med-0.vox | 3 - .../voxel/sprite/cavern/grass_med-1.vox | 3 - .../voxel/sprite/cavern/grass_med-2.vox | 3 - .../voxel/sprite/cavern/grass_med-3.vox | 3 - .../voxygen/voxel/sprite/cavern/mycel-0.vox | 3 - .../voxygen/voxel/sprite/cavern/mycel-1.vox | 3 - .../voxygen/voxel/sprite/cavern/mycel-2.vox | 3 - .../voxygen/voxel/sprite/cavern/mycel-3.vox | 3 - .../voxel/sprite/dead_plant/dead_plant-0.vox | 3 + .../voxel/sprite/dead_plant/dead_plant-1.vox | 3 + .../voxel/sprite/dead_plant/dead_plant-2.vox | 3 + .../voxel/sprite/dead_plant/dead_plant-3.vox | 3 + assets/voxygen/voxel/sprite/leafy_plant/1.vox | 4 +- .../voxygen/voxel/sprite/leafy_plant/10.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/2.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/3.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/4.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/5.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/6.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/7.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/8.vox | 4 +- assets/voxygen/voxel/sprite/leafy_plant/9.vox | 4 +- .../leafy_plant/jungle_plant_ceiling-0.vox | 3 + .../leafy_plant/jungle_plant_ceiling-1.vox | 3 + .../leafy_plant/jungle_plant_ceiling-2.vox | 3 + .../leafy_plant/jungle_plant_ceiling-3.vox | 3 + .../leafy_plant/jungle_plant_ceiling-4.vox | 3 + .../voxel/sprite/mushrooms/mushroom-0.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-1.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-10.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-2.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-3.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-4.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-5.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-6.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-7.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-8.vox | 4 +- .../voxel/sprite/mushrooms/mushroom-9.vox | 4 +- assets/voxygen/voxel/sprite_manifest.ron | 433 ++++++++++++++++-- common/src/terrain/block.rs | 19 +- common/src/terrain/sprite.rs | 85 ++-- world/src/layer/cave.rs | 71 ++- world/src/layer/mod.rs | 10 +- 105 files changed, 723 insertions(+), 203 deletions(-) create mode 100644 assets/voxygen/voxel/sprite/cave/cave_flower-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_flower-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_flower-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_flower-3.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_lantern_flower-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_lantern_flower-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_lantern_flower-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_lantern_plant-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_lantern_plant-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/cave_lantern_plant-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/mycel-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/mycel-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/mycel-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/mycel-3.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-3.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-4.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-5.vox create mode 100644 assets/voxygen/voxel/sprite/cave/ceiling/root-6.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-3.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-4.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-5.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-6.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_long-7.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_med-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_med-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_med-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/grass_blue_med-3.vox rename assets/voxygen/voxel/sprite/{cavern/grass_short-0.vox => cave/grass_blue_short-0.vox} (100%) rename assets/voxygen/voxel/sprite/{cavern/grass_short-1.vox => cave/grass_blue_short-1.vox} (100%) rename assets/voxygen/voxel/sprite/{cavern/grass_short-2.vox => cave/grass_blue_short-2.vox} (100%) rename assets/voxygen/voxel/sprite/{cavern/grass_short-3.vox => cave/grass_blue_short-3.vox} (100%) rename assets/voxygen/voxel/sprite/{cavern/grass_short-4.vox => cave/grass_blue_short-4.vox} (100%) create mode 100644 assets/voxygen/voxel/sprite/cave/mushroom-10.vox create mode 100644 assets/voxygen/voxel/sprite/cave/mushroom-11.vox create mode 100644 assets/voxygen/voxel/sprite/cave/mushroom-9.vox create mode 100644 assets/voxygen/voxel/sprite/cave/spore_reed-0.vox create mode 100644 assets/voxygen/voxel/sprite/cave/spore_reed-1.vox create mode 100644 assets/voxygen/voxel/sprite/cave/spore_reed-2.vox create mode 100644 assets/voxygen/voxel/sprite/cave/spore_reed-3.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-0.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-1.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-2.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-3.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-4.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-5.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-6.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-7.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-0.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-1.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-2.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-3.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-0.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-1.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-2.vox delete mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-3.vox create mode 100644 assets/voxygen/voxel/sprite/dead_plant/dead_plant-0.vox create mode 100644 assets/voxygen/voxel/sprite/dead_plant/dead_plant-1.vox create mode 100644 assets/voxygen/voxel/sprite/dead_plant/dead_plant-2.vox create mode 100644 assets/voxygen/voxel/sprite/dead_plant/dead_plant-3.vox create mode 100644 assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-0.vox create mode 100644 assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-1.vox create mode 100644 assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-2.vox create mode 100644 assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-3.vox create mode 100644 assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-4.vox diff --git a/.cargo/config b/.cargo/config index 5dbe6321db..87d684cbbf 100644 --- a/.cargo/config +++ b/.cargo/config @@ -31,4 +31,4 @@ dbg-voxygen = "run --bin veloren-voxygen --profile debuginfo" # misc swarm = "run --bin swarm --features client/bin_bot,client/tick_network --" ci-clippy = "clippy --all-targets --locked --features=bin_cmd_doc_gen,bin_compression,bin_csv,bin_graphviz,bin_bot,bin_asset_migrate,asset_tweak,bin,stat" -ci-clippy2 = "clippy -p veloren-voxygen --locked --no-default-features --features=default-publish" \ No newline at end of file +ci-clippy2 = "clippy -p veloren-voxygen --locked --no-default-features --features=default-publish" diff --git a/assets/voxygen/voxel/sprite/cave/cave_flower-0.vox b/assets/voxygen/voxel/sprite/cave/cave_flower-0.vox new file mode 100644 index 0000000000..bb6e51aa78 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_flower-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21ff5a60c0de91a802974a2d108f75aaf867ae131cf6f0fb83d7fbbff1a6f26b +size 1692 diff --git a/assets/voxygen/voxel/sprite/cave/cave_flower-1.vox b/assets/voxygen/voxel/sprite/cave/cave_flower-1.vox new file mode 100644 index 0000000000..3c81954969 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_flower-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b02a74066dba97ed9fc0be8f41a4dbfea8789d89cf7bb66b69fccb9b138266f +size 1692 diff --git a/assets/voxygen/voxel/sprite/cave/cave_flower-2.vox b/assets/voxygen/voxel/sprite/cave/cave_flower-2.vox new file mode 100644 index 0000000000..8a6b8371c8 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_flower-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbb1de9a0121e651eddaf1173e399d0b935987e6369184b7db4a132f45999b06 +size 1476 diff --git a/assets/voxygen/voxel/sprite/cave/cave_flower-3.vox b/assets/voxygen/voxel/sprite/cave/cave_flower-3.vox new file mode 100644 index 0000000000..825e09453d --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_flower-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e39792dd2ae936dc3b77bd97d11432cd2754bcc405d7437f5ce517ab0914240c +size 1468 diff --git a/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-0.vox b/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-0.vox new file mode 100644 index 0000000000..77b0341276 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a6d8454c26ac51af3b5ad1ab32b3f5dbe1793b116214fe2d62b2fe6d4602be5 +size 2616 diff --git a/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-1.vox b/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-1.vox new file mode 100644 index 0000000000..104f6d401e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08dcd4e0d3675f13584d6be67e567c021ac8284406d5f136a70b145c7f5e6724 +size 4092 diff --git a/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-2.vox b/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-2.vox new file mode 100644 index 0000000000..8dd74a6124 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_lantern_flower-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:059048f6a2fc9873817b7990baddaadd5ea5f4af522ab484657238d359798a98 +size 2080 diff --git a/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-0.vox b/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-0.vox new file mode 100644 index 0000000000..4240d8f408 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85e6a614536b62f034adc3fa05f28fbe4b2d41a111fd8947f373017a40d1bf4f +size 2212 diff --git a/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-1.vox b/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-1.vox new file mode 100644 index 0000000000..0512c9f088 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ce0a40c247311e02f0f3c547fd0d3c0d6d0b6a502500e0d9fec67ed483779ce +size 2116 diff --git a/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-2.vox b/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-2.vox new file mode 100644 index 0000000000..eef86a3165 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/cave_lantern_plant-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99db3fadfaa5f7a6202225aa543a8a35ee1a9fd5514828af7549daff49880cfa +size 1932 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-0.vox b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-0.vox new file mode 100644 index 0000000000..2706aaa80e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67e2193410f9cc0687e4ee62b9fdd02cdfdc41c6c21e7fa22fa0fe083434d0e4 +size 2616 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-1.vox b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-1.vox new file mode 100644 index 0000000000..7b72b2e4eb --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a904f1945610b0f69717acc9ad0f44a8aa315caad3d732b185901328846537e2 +size 4092 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-2.vox b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-2.vox new file mode 100644 index 0000000000..4e3bf99edb --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_flower-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f5228452cc894fb375708ca34c2d06ff13be205eae352880a69428a32271e6b +size 2080 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-0.vox b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-0.vox new file mode 100644 index 0000000000..e36bcfef97 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a2c8cc9cde6ac6605dc99140a25d71bf7b0f3e9c2922c2d14aaa7f851d64e7d +size 1932 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-1.vox b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-1.vox new file mode 100644 index 0000000000..56c319971a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/cave_lantern_plant-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6192326c37ca9e3faac1130a10e0206506af0e21faf4c3d2ca2c68e9b8977d4 +size 1884 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mold-4.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mold-4.vox index 3e27f7226e..759db915e7 100644 --- a/assets/voxygen/voxel/sprite/cave/ceiling/mold-4.vox +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mold-4.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80117ff139a0b28ddc8b00e26f3005abe25444abd8e61fe2179941d2dd060abe -size 2140 +oid sha256:ff62aa84976fe527082c55088a5230e9f401a557c3e99d54e41cead27a6b6f2b +size 1880 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mold-5.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mold-5.vox index bd1f28ddf7..b8360b1aee 100644 --- a/assets/voxygen/voxel/sprite/cave/ceiling/mold-5.vox +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mold-5.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:549d7ddb44c1a935fb72e9cdc089b381d8420b7e8635fe95d5dacc05f47d27e4 -size 2792 +oid sha256:60f1aa88e010a545c6aaa59da852b4bc9cbba3f66d9c0434a8691a166a620b22 +size 2244 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mold-6.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mold-6.vox index 8bab3a127b..f536bdd9db 100644 --- a/assets/voxygen/voxel/sprite/cave/ceiling/mold-6.vox +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mold-6.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:174071a1a2492ec08915df237cf6e02abe3f298485f772441133792d5ab49732 -size 2784 +oid sha256:c4e2e834176cd258169f499cb1a7b6046aa6fa3741e02ae16b04c8ab748d969d +size 2340 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mycel-0.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-0.vox new file mode 100644 index 0000000000..dd3469a4b3 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fed02ca946f0a3fc4113b10f940f160a84dcf852f2d0550c10b07138ef53f701 +size 1400 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mycel-1.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-1.vox new file mode 100644 index 0000000000..194be26809 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f38e1f4330ce5cf35d6d56ec118953bf266e5c9e9b98183a768e2639f591054 +size 1592 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mycel-2.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-2.vox new file mode 100644 index 0000000000..68f19ac0fc --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75862c5f9c5833683ea608e167315020b9cdae1793dfc01b2f713e2cdaabd322 +size 1476 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/mycel-3.vox b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-3.vox new file mode 100644 index 0000000000..9c19329bba --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/mycel-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc720540b281bc1e87ed506099b39a9c47b9ee2ea6d5df555135282eddaf090c +size 1652 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-0.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-0.vox new file mode 100644 index 0000000000..a233547634 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d499ec70026859f713267c8e79d2c5998a595ddf8e8f87791ba5366a65f7c41 +size 1692 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-1.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-1.vox new file mode 100644 index 0000000000..0271a5cb6a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:691b155b58faaaf67abc0a13351b5496665679a38440a1d951778cacd3e67c32 +size 1864 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-2.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-2.vox new file mode 100644 index 0000000000..0bbe18efea --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d48ae8e182d4693bf2c5a3999d95b3adabb7543c43b3f1a2a72d172ba377b7ef +size 1792 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-3.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-3.vox new file mode 100644 index 0000000000..dbdd10dcaf --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a5bad7db3a4b4ec642f8a1ecda4d8539d6ffd1cfc0a13887a9f1662566dbe161 +size 1712 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-4.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-4.vox new file mode 100644 index 0000000000..4bc04c93ae --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e73fec9396657bd52e53c1a472b849a892dbf9eb2114109a215214d458129afa +size 1632 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-5.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-5.vox new file mode 100644 index 0000000000..df216ee49b --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-5.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcc819c8c72db8da498cf30aa4774500ffe3d5ca1b0e83456a451752164ad6ac +size 1604 diff --git a/assets/voxygen/voxel/sprite/cave/ceiling/root-6.vox b/assets/voxygen/voxel/sprite/cave/ceiling/root-6.vox new file mode 100644 index 0000000000..3d6a00da78 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/ceiling/root-6.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eda7ec75b5a8c52d042cf933ad2fba8da806348f3ae3ff00f2882ad0645a86b9 +size 1808 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-0.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-0.vox new file mode 100644 index 0000000000..278b96b50f --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b76e8ca3d721f1cb45bcbf764937749d38d5526e79082ab3b1ab85a8ba842836 +size 1428 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-1.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-1.vox new file mode 100644 index 0000000000..c3d52b0290 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77f196647a7f74391d1f9957acf7cb559850618a27239ca64344a2eefbdc06f1 +size 1396 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-2.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-2.vox new file mode 100644 index 0000000000..d88f9951e7 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e99f856f05ce788529d5566a4ecf56c83433841a47bdbee6dc717bc3dda8d713 +size 1444 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-3.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-3.vox new file mode 100644 index 0000000000..8ef2f47d3e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f9419e6fb25313c7fec015305d18f209396f4e41527debbdf306b8c6c76c90b +size 1264 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-4.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-4.vox new file mode 100644 index 0000000000..8ffeb583d2 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e46639e32343a803de848030772ab9489defc4e77f2b3f776fb79ac43af902aa +size 1404 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-5.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-5.vox new file mode 100644 index 0000000000..ee35457b26 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-5.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:806f6b8887d9f7240d7dc82b135f7609d99d252d740e15a7da0f6150bea31149 +size 1432 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-6.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-6.vox new file mode 100644 index 0000000000..049a6b4da5 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-6.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4498b70c987f525a2b2feeb3a4974b86c940e5a9b9cfa8d9997f7d9501dbc05 +size 1428 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_long-7.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_long-7.vox new file mode 100644 index 0000000000..256dfaa07f --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_long-7.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:870d8b948b8c21704781825bb750b45477580562ee1d0088d9f1ab008c8e6e9c +size 1380 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_med-0.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_med-0.vox new file mode 100644 index 0000000000..a4184d8e90 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_med-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:941e19009fa39aae441c7fc03a12d0143de51d09c823fad0b8184c48f2263200 +size 1244 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_med-1.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_med-1.vox new file mode 100644 index 0000000000..e077f4f473 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_med-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6427235b7aa34db357e403e05ee54ed1ddba9d21a01abaa4d3a97aa1e22e685b +size 1248 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_med-2.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_med-2.vox new file mode 100644 index 0000000000..8a36087716 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_med-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f3fd71c567f456357c87216832ff606d8b123bcbe0732d36d119f1b9683be56 +size 1288 diff --git a/assets/voxygen/voxel/sprite/cave/grass_blue_med-3.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_med-3.vox new file mode 100644 index 0000000000..63e1bbd708 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/grass_blue_med-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0dfee4fc2ed0776a0ce8eb241392cef2c2f34bf972dfbfc7660dedffe7253808 +size 1232 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-0.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_short-0.vox similarity index 100% rename from assets/voxygen/voxel/sprite/cavern/grass_short-0.vox rename to assets/voxygen/voxel/sprite/cave/grass_blue_short-0.vox diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-1.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_short-1.vox similarity index 100% rename from assets/voxygen/voxel/sprite/cavern/grass_short-1.vox rename to assets/voxygen/voxel/sprite/cave/grass_blue_short-1.vox diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-2.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_short-2.vox similarity index 100% rename from assets/voxygen/voxel/sprite/cavern/grass_short-2.vox rename to assets/voxygen/voxel/sprite/cave/grass_blue_short-2.vox diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-3.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_short-3.vox similarity index 100% rename from assets/voxygen/voxel/sprite/cavern/grass_short-3.vox rename to assets/voxygen/voxel/sprite/cave/grass_blue_short-3.vox diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-4.vox b/assets/voxygen/voxel/sprite/cave/grass_blue_short-4.vox similarity index 100% rename from assets/voxygen/voxel/sprite/cavern/grass_short-4.vox rename to assets/voxygen/voxel/sprite/cave/grass_blue_short-4.vox diff --git a/assets/voxygen/voxel/sprite/cave/mushroom-10.vox b/assets/voxygen/voxel/sprite/cave/mushroom-10.vox new file mode 100644 index 0000000000..5b3f40c82e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/mushroom-10.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e7911ad1366527d4b9f602f5c5b2edfa15258a7b562de1798c5bf8efb70df5a +size 1452 diff --git a/assets/voxygen/voxel/sprite/cave/mushroom-11.vox b/assets/voxygen/voxel/sprite/cave/mushroom-11.vox new file mode 100644 index 0000000000..7a9cc2328a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/mushroom-11.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff20e12796992321a7d853ddad4dee3033dbf6eea010003879e3ba0854314be1 +size 1636 diff --git a/assets/voxygen/voxel/sprite/cave/mushroom-9.vox b/assets/voxygen/voxel/sprite/cave/mushroom-9.vox new file mode 100644 index 0000000000..27a871aef5 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/mushroom-9.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2330b55ec3cbf670db47c467006437a2dbc3b797ebdc017aef4aa341a93709be +size 1884 diff --git a/assets/voxygen/voxel/sprite/cave/spore_reed-0.vox b/assets/voxygen/voxel/sprite/cave/spore_reed-0.vox new file mode 100644 index 0000000000..3da0eec5f0 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/spore_reed-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d658194f30de7e43c0ac007c0f2751bd2cb11e4bf5701af8e7dad98e6af0d7e7 +size 1956 diff --git a/assets/voxygen/voxel/sprite/cave/spore_reed-1.vox b/assets/voxygen/voxel/sprite/cave/spore_reed-1.vox new file mode 100644 index 0000000000..f394a4b4c8 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/spore_reed-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6eacd8ee24218c4b3b62f5bdbf9465a464cbca9375c303926797c10e34810f6a +size 1740 diff --git a/assets/voxygen/voxel/sprite/cave/spore_reed-2.vox b/assets/voxygen/voxel/sprite/cave/spore_reed-2.vox new file mode 100644 index 0000000000..3b39f49588 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/spore_reed-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a087ceb292004756842c404465c36d0a192fa9a9ab4593b87db1c8a77b4e2fac +size 1648 diff --git a/assets/voxygen/voxel/sprite/cave/spore_reed-3.vox b/assets/voxygen/voxel/sprite/cave/spore_reed-3.vox new file mode 100644 index 0000000000..bd2135d722 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cave/spore_reed-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aecb94ae2810841d0a99fd72bbd9de1b0a23fa6d1f667d31c8412a2dc077287d +size 1372 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-0.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-0.vox deleted file mode 100644 index 02a7af7f8c..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-0.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:144bb2be7627de61e951085c96038284ae28eed216c6b2c04eb0db596df2f738 -size 1428 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-1.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-1.vox deleted file mode 100644 index 772cfe132a..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-1.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c76794542d91c94960373966c2b0232f57801d0a862a117090ba00a7ae934034 -size 1396 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-2.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-2.vox deleted file mode 100644 index e53115ea2a..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-2.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44d27165b605d477f769123ef5d93de7ad357f0b937263ad37ebb8c1480c4324 -size 1444 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-3.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-3.vox deleted file mode 100644 index 6157a2843f..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-3.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44745ce1fef2c4cc1834e82abde5ef6ea3af113b3d3a4cf7df223b833ec07207 -size 1264 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-4.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-4.vox deleted file mode 100644 index d1b9ac74e1..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-4.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9439482e006100f8219d27095e1929e15e4cfcd6303b8911a9ce638c30b76966 -size 1404 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-5.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-5.vox deleted file mode 100644 index 3e0c01f98a..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-5.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7261c47bb5683e0a0cb1461dc84c5980e7cc1b25f8063b667fef86657e145a68 -size 1432 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-6.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-6.vox deleted file mode 100644 index b8e51f934e..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-6.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3bfe9db4fc6e624aa477b04dc6c681e390df65d8c488bf0eb61a86e7d8b7430d -size 1428 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-7.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-7.vox deleted file mode 100644 index 5d7ffe064c..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_long-7.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eec0a1b111d12f022e973e14afaf2e8f81fd7c6e4676a29cbc2f698f75a13e95 -size 1380 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-0.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-0.vox deleted file mode 100644 index 452bd9f440..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_med-0.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7496e27724e51a4129955a304cc10a15447845687e817140464da7f69be92386 -size 1244 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-1.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-1.vox deleted file mode 100644 index 6f79383e6a..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_med-1.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7decc0743714a30208440e9437caaa77de79d730a9d7e060a4625c621ab30feb -size 1248 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-2.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-2.vox deleted file mode 100644 index 2f2f65d819..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_med-2.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:05c12e2e4d82b186c422f0da4617e17dd72f45b48071a3a7567fb186b581d4d2 -size 1288 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-3.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-3.vox deleted file mode 100644 index 4e657e7fe8..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/grass_med-3.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:92fbd926d0e40ae777286c85d1cd56547717a0fc74f6d34611394113d063c74b -size 1232 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-0.vox b/assets/voxygen/voxel/sprite/cavern/mycel-0.vox deleted file mode 100644 index 4f3d86f73b..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/mycel-0.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d7180c8469565f8836b1e795c94faecab5fb97c1d3d9b3c1d50fd202bb23d6f -size 1180 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-1.vox b/assets/voxygen/voxel/sprite/cavern/mycel-1.vox deleted file mode 100644 index 44ff474b6e..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/mycel-1.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:10c3aa05a02e9431d2bf25fa473218c4c91ad62252ee3d8383e82a57cbcff1bb -size 1220 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-2.vox b/assets/voxygen/voxel/sprite/cavern/mycel-2.vox deleted file mode 100644 index a63c1a67af..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/mycel-2.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0516877cbf4caa6370c2dbf3c957b294c12a93db8e805dd858e43c91d17ee36c -size 1152 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-3.vox b/assets/voxygen/voxel/sprite/cavern/mycel-3.vox deleted file mode 100644 index 764d35b66e..0000000000 --- a/assets/voxygen/voxel/sprite/cavern/mycel-3.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d3ceb2b40579d0b885280d80e8e52179d6696fe99ff4612ee2c9931ec0543bc -size 1256 diff --git a/assets/voxygen/voxel/sprite/dead_plant/dead_plant-0.vox b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-0.vox new file mode 100644 index 0000000000..82b695dcdb --- /dev/null +++ b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:325906029c1c3d0ae79f282677817e2b6e4634c40c665a9b413dfe23deb5b87e +size 1308 diff --git a/assets/voxygen/voxel/sprite/dead_plant/dead_plant-1.vox b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-1.vox new file mode 100644 index 0000000000..237fb7bc9c --- /dev/null +++ b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c59380ff24f6ddde29a2d2018ae5eee996dd6af7ea6b820974929677a74a35d +size 1280 diff --git a/assets/voxygen/voxel/sprite/dead_plant/dead_plant-2.vox b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-2.vox new file mode 100644 index 0000000000..d76b5745bb --- /dev/null +++ b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:891583126c09f134eda53b675a3c18bdfd299a84939e73dc276a5689d05de2f0 +size 1192 diff --git a/assets/voxygen/voxel/sprite/dead_plant/dead_plant-3.vox b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-3.vox new file mode 100644 index 0000000000..63e3970ac0 --- /dev/null +++ b/assets/voxygen/voxel/sprite/dead_plant/dead_plant-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0afa6f113b4f161f33f40d2dea097cb2ecc38eaf164478850190aa5ddccd7ebc +size 1236 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/1.vox b/assets/voxygen/voxel/sprite/leafy_plant/1.vox index 13258089d6..f4c6ee9973 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/1.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/1.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f7230dc9d14f13b7bad03fcc2cda7922e6898745c18791916d8fa59c5709bcb -size 1892 +oid sha256:9525a447698343edd41376d17ee9d3bbf994d09df56b79883e5f9dd78298c3e6 +size 1876 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/10.vox b/assets/voxygen/voxel/sprite/leafy_plant/10.vox index 73d3b3901d..f73c307a28 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/10.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/10.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63accce104181146bbe0e02f7c1f22f3d849387c4da7975c23e6d9aa0174f8fa -size 1160 +oid sha256:20d22e75a55607b46ad49f53f5bd24db8d9f08ed602e71bfee8b00fc0267e1ec +size 1236 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/2.vox b/assets/voxygen/voxel/sprite/leafy_plant/2.vox index daddc2cd70..0ee6c528e1 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/2.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/2.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56fff236d95573b242fa086eb7c9d0ea88199d1b1c4509d072a84ff389c43618 -size 1340 +oid sha256:52f494a4636c7fcc11a2d229a13c8ebc7b8f608807bcd29891b8d25a4e63bdb5 +size 1372 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/3.vox b/assets/voxygen/voxel/sprite/leafy_plant/3.vox index a4cb1b017d..803acab16e 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/3.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/3.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b376fd6ae77ee6b70b840ae836c3f45f9a534982793b6399b1e75e80f340ce40 -size 1432 +oid sha256:2ab99313cb91c8118067cfe1275affe766658da941d73a83a0e400f5c6e8c8a9 +size 2044 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/4.vox b/assets/voxygen/voxel/sprite/leafy_plant/4.vox index 21506dc484..2cb7810214 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/4.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/4.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b486ba258a8e9b780ce48a660814762593306520b901e058b5f803e50b4ed7f9 -size 1308 +oid sha256:1506b5b2e15404b1e17812c78bac8711c6def87fd61a0882a74341c67f6f5ab2 +size 1484 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/5.vox b/assets/voxygen/voxel/sprite/leafy_plant/5.vox index 6dca485f98..6b12574fb1 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/5.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/5.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96113dd1de793a91c1b4eda784f89cc65396c41aa930274c748ee7afce666de0 -size 1284 +oid sha256:db158665c455aacba759303c6fd3a0c95ddfbaac19a48aa3a1fc99a2246468b4 +size 1804 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/6.vox b/assets/voxygen/voxel/sprite/leafy_plant/6.vox index 1ea45c7fe1..453199fe24 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/6.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/6.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2546700413ad30593ca2f51c22f1b51dc9b94b43c9cbaa38ffecf18a7addbd07 -size 1292 +oid sha256:ad4413aa053b09002b355d509a45538ae2546e69f81eccd34499566626cb1827 +size 1580 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/7.vox b/assets/voxygen/voxel/sprite/leafy_plant/7.vox index 57d2ee507f..2cb0bdf5e1 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/7.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/7.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c50625eb6a07a0a3eb04975fa769b6301ad0f4f05f433adb1e3cb5b6b85b712d -size 1252 +oid sha256:45e171e6ce24371bbab7dc2a54023ef279a89a53af96c30577c1d9659bd3087f +size 1820 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/8.vox b/assets/voxygen/voxel/sprite/leafy_plant/8.vox index f75a876043..e940ba77cb 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/8.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/8.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d37384289721949cfeb63c6429454d0356470c52a0d682a1147be46e801fa4d -size 1340 +oid sha256:55c8036250c374478f37da3a3a09f18183a2af88daedf324cf8e846f1563c1fd +size 1608 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/9.vox b/assets/voxygen/voxel/sprite/leafy_plant/9.vox index b4996a9d93..9d480bba6a 100644 --- a/assets/voxygen/voxel/sprite/leafy_plant/9.vox +++ b/assets/voxygen/voxel/sprite/leafy_plant/9.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74ffee6cdbda6bfed82453eb285a8d6f3d4bbc01abed21d73a96caf1ef075188 -size 1188 +oid sha256:91d5a6cb6ec9b74cab5a57f5e480f7cbd0472f063fbb37e4449b817cbb032bc3 +size 1320 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-0.vox b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-0.vox new file mode 100644 index 0000000000..481987e1f1 --- /dev/null +++ b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:203199ae6be0e8c086262dac995e54dab02651b6de5238c3ae54625adc32b09d +size 1336 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-1.vox b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-1.vox new file mode 100644 index 0000000000..7890ecb1d9 --- /dev/null +++ b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd3386610963273712d388b8c580163ffa4a602bd82352e6ad7e4f158568ce9d +size 1472 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-2.vox b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-2.vox new file mode 100644 index 0000000000..dc20aee456 --- /dev/null +++ b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:277484b32c9ad55804b32ad9e960c1a1bf38729e7a92c134272b3f27ae69ca6c +size 1460 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-3.vox b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-3.vox new file mode 100644 index 0000000000..c9f4523644 --- /dev/null +++ b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6de8c164400d98aee06ef992add76601f41ad970305f2456cd542768d8bd2841 +size 1540 diff --git a/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-4.vox b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-4.vox new file mode 100644 index 0000000000..bba1499c91 --- /dev/null +++ b/assets/voxygen/voxel/sprite/leafy_plant/jungle_plant_ceiling-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e55f3b7dd4ab6825f670c739e91a29a454ee871b7556f68eb05043af833634c +size 1752 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-0.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-0.vox index a2824a0262..a8d38710b2 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-0.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-0.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65ed706fdb0b4ac5e66f22d2edcfc78dea308a51f3616e35cadac11ce8c22656 -size 1160 +oid sha256:b8e4af46fbeb52e2defd77354c5c4f0f3c5b6e0b61a56f0bda4de94ae746a3c4 +size 1460 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-1.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-1.vox index bd29d728cc..1d4dad4f95 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-1.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-1.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83ca8cf16bbac82da89a0102513e7c54edd75f3b772cdb5aa0981c117045db33 -size 1204 +oid sha256:d12bd2ec8a2b172acd40a7b85571a213dfe6cb426446eb0ca2fb7bc2bfae5f1a +size 1440 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-10.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-10.vox index f293502f1b..33662b1423 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-10.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-10.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bd2decf66c5b2c4712e7f2ae77ae4c530e79373a0ceed111f7254e98dbced6c -size 1448 +oid sha256:ad534b54ce5c7456e0e5b6365fe4ec2c7f3f8d7c7182899261e30bbb0ab29f59 +size 1748 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-2.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-2.vox index 5f2378a8d7..eb71303649 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-2.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-2.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b67de880999ab46de70e8579ed5054f3838c354a7a74ed382c4e2abc1ea16f27 -size 1160 +oid sha256:d51975bcb9e5bc73cf5edaf510cb76314457bc83ddebeaf3cb18668f76ab011f +size 1328 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-3.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-3.vox index fac5b3ca1f..5a736133fe 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-3.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-3.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d262dc556c2c28fbba8d964aa7c2c42d78bec410e3aa1ee71eb353a7701a8b0e -size 1244 +oid sha256:5e83595d72a91a33b298fdb350be172ec167cf3823d719d74eade52a32ea5246 +size 1368 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-4.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-4.vox index b7e0dba6dc..b993fb3141 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-4.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-4.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:192b8f2baddda973d5b9e55e2aaf0fe8dcb3ddc5be5d242cd6bab319b6f8a763 -size 1448 +oid sha256:7be406856dc790d50b73ff194a3cba8033751f2d819524a5759ef6d6d60fc5c1 +size 1648 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-5.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-5.vox index f32e812b5d..529935cb69 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-5.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-5.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5811aaf9f24505b2d089c9adc176ec906b746b506ae7e64434bc10638b3efd00 -size 1512 +oid sha256:c7d93cfbf41755b4fd14b2562de6f4b41a50032907d740ee70fd3c17eb7c1207 +size 2004 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-6.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-6.vox index a3af68eb4a..dc822fdadf 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-6.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-6.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:588d579a9c4dc18c5795459eb27b89082ace9ffabc2034815a0cff750464c9be -size 1340 +oid sha256:a505d307d4bc865bde485215a1d4eeaae48ed4b1284bfec90c9349e159f02b21 +size 1708 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-7.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-7.vox index 0a5fa93168..c853b7946d 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-7.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-7.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0c01c8e11e19b510b7762389782721d55737857ed49230b557a59f10c5e932c -size 1224 +oid sha256:deb044efce4e3012a5f3ba3164499dc8f08bdd80c82af4d09702518f0c9c468d +size 1372 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-8.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-8.vox index 9ce82ae5a2..4113f2ef47 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-8.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-8.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ba9246881224580ae0b3df4a4ed7da8119744c48c62f2ab68eec3bb988a9513 -size 1252 +oid sha256:61c68b179303f378fc018ec12f6e99d26a709970d14000df21f484a5528633b1 +size 1596 diff --git a/assets/voxygen/voxel/sprite/mushrooms/mushroom-9.vox b/assets/voxygen/voxel/sprite/mushrooms/mushroom-9.vox index a081aa830e..c8ca537dfd 100644 --- a/assets/voxygen/voxel/sprite/mushrooms/mushroom-9.vox +++ b/assets/voxygen/voxel/sprite/mushrooms/mushroom-9.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:845460d4711a46dfd8666ed99591d50e846d3c35cc78e1a8fb2db62eba459d93 -size 1432 +oid sha256:46986e4b3c3e9a84cc6e43656140e206a22c08fee63b02dacf61b116806b9869 +size 2116 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index f96cfae70f..69de6ff461 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -610,6 +610,139 @@ SewerMushroom: Some(( ], wind_sway: 0.0, )), +// Lush cave biome mushrooms +LushMushroom: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-0", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-1", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-2", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-4", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-5", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-6", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-9", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-1", + offset: (-5.0, -5.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +// Rocky cave biome mushrooms +RockyMushroom: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.mushroom-0", + offset: (-8.0, -8.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-2", + offset: (-5.5, -5.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-9", + offset: (-8.0, -8.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-10", + offset: (-8.0, -8.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-11", + offset: (-8.0, -8.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +// Mushroom cave biome mushrooms +GlowMushroom: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.mushroom-3", + offset: (-2.5, -2.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-4", + offset: (-1.5, -1.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-5", + offset: (-5.5, -5.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-6", + offset: (-8.5, -8.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-7", + offset: (-11.5, -11.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.mushroom-8", + offset: (-12.5, -15.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-3", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-7", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-8", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mushrooms.mushroom-10", + offset: (-6.0, -6.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), // Cave Mushrooms CaveMushroom: Some(( variations: [ @@ -679,6 +812,11 @@ CeilingMushroom: Some(( offset: (-11.5, -11.5, -17.0), lod_axes: (1.0, 1.0, 1.0), ), + ], + wind_sway: 0.0, +)), +Mold: Some(( + variations: [ ( model: "voxygen.voxel.sprite.cave.ceiling.mold-0", offset: (-5.5, -5.5, 0.0), @@ -696,22 +834,217 @@ CeilingMushroom: Some(( ), ( model: "voxygen.voxel.sprite.cave.ceiling.mold-3", - offset: (-5.5, -5.5, 2.0), + offset: (-5.5, -5.5, -2.0), lod_axes: (1.0, 1.0, 1.0), ), ( model: "voxygen.voxel.sprite.cave.ceiling.mold-4", - offset: (-2.0, -2.0, -49.0), + offset: (-5.5, -5.5, -13.0), lod_axes: (1.0, 1.0, 1.0), ), ( model: "voxygen.voxel.sprite.cave.ceiling.mold-5", - offset: (-2.0, -2.0, -79.0), + offset: (-5.5, -5.5, -19.0), lod_axes: (1.0, 1.0, 1.0), ), ( model: "voxygen.voxel.sprite.cave.ceiling.mold-6", - offset: (-2.0, -2.0, -79.0), + offset: (-5.5, -5.5, -24.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +Root: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-0", + offset: (-3.0, -2.5, -22.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-1", + offset: (-2.5, -2.5, -34.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-2", + offset: (-2.5, -2.5, -31.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-3", + offset: (-2.5, -2.5, -24.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-4", + offset: (-2.5, -2.5, -16.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-5", + offset: (-2.5, -2.5, -16.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.root-6", + offset: (-2.5, -2.5, -33.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +CeilingLanternPlant: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.ceiling.cave_lantern_plant-0", + offset: (-7.5, -5.5, -23.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.cave_lantern_plant-1", + offset: (-7.5, -5.5, -16.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +CeilingLanternFlower: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.ceiling.cave_lantern_flower-0", + offset: (-7.5, -7.5, 3.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.cave_lantern_flower-1", + offset: (-6.5, -6.5, 1.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.ceiling.cave_lantern_flower-2", + offset: (-7.5, -7.5, 4.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +CeilingJungleLeafyPlant: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.leafy_plant.jungle_plant_ceiling-0", + offset: (-5.5, -1.5, -1.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.leafy_plant.jungle_plant_ceiling-1", + offset: (-6.5, -2.5, -3.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.leafy_plant.jungle_plant_ceiling-2", + offset: (-6.5, -2.5, -5.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.leafy_plant.jungle_plant_ceiling-3", + offset: (-7.5, -2.5, -5.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.leafy_plant.jungle_plant_ceiling-4", + offset: (-7.5, -5.5, -11.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.4, +)), +LushFlower: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.cave_flower-0", + offset: (-5.0, -5.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_flower-1", + offset: (-5.5, -5.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_flower-2", + offset: (-4.5, -4.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_flower-3", + offset: (-5.5, -3.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +LanternFlower: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.cave_lantern_flower-0", + offset: (-7.5, -7.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_lantern_flower-1", + offset: (-11.5, -11.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_lantern_flower-2", + offset: (-7.5, -7.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +LanternPlant: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.cave_lantern_plant-0", + offset: (-7.5, -7.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_lantern_plant-1", + offset: (-11.5, -11.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.cave_lantern_plant-2", + offset: (-7.5, -7.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +SporeReed: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cave.spore_reed-0", + offset: (-5.5, -5.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.spore_reed-1", + offset: (-4.0, -5.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.spore_reed-2", + offset: (-4.5, -5.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.cave.spore_reed-3", + offset: (-3.0, -2.5, 0.0), lod_axes: (1.0, 1.0, 1.0), ), ], @@ -1594,6 +1927,32 @@ DeadBush: Some(( ], wind_sway: 0.2, )), +// Dead Plant +DeadPlant: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.dead_plant.dead_plant-0", + offset: (-6.0, -6.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.dead_plant.dead_plant-1", + offset: (-6.0, -6.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.dead_plant.dead_plant-2", + offset: (-6.0, -6.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.dead_plant.dead_plant-3", + offset: (-6.0, -6.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.2, +)), // Blueberries // NOTE: Why are these commented out? Blueberry: None/* ( @@ -4113,103 +4472,103 @@ Bones: Some(( ], wind_sway: 0.0, )), -// Short Cavern Grass Blue -CavernGrassBlueShort: Some(( +// Short Grass Blue +GrassBlueShort: Some(( variations: [ ( - model: "voxygen.voxel.sprite.cavern.grass_short-0", + model: "voxygen.voxel.sprite.cave.grass_blue_short-0", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_short-1", + model: "voxygen.voxel.sprite.cave.grass_blue_short-1", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_short-2", + model: "voxygen.voxel.sprite.cave.grass_blue_short-2", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_short-3", + model: "voxygen.voxel.sprite.cave.grass_blue_short-3", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_short-4", + model: "voxygen.voxel.sprite.cave.grass_blue_short-4", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ], wind_sway: 0.0, )), -// Medium Cavern Grass Blue -CavernGrassBlueMedium: Some(( +// Medium Grass Blue +GrassBlueMedium: Some(( variations: [ ( - model: "voxygen.voxel.sprite.cavern.grass_med-0", + model: "voxygen.voxel.sprite.cave.grass_blue_med-0", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_med-1", + model: "voxygen.voxel.sprite.cave.grass_blue_med-1", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_med-2", + model: "voxygen.voxel.sprite.cave.grass_blue_med-2", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_med-3", + model: "voxygen.voxel.sprite.cave.grass_blue_med-3", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ], wind_sway: 0.0, )), -// Long Cavern Grass Blue -CavernGrassBlueLong: Some(( +// Long Grass Blue +GrassBlueLong: Some(( variations: [ ( - model: "voxygen.voxel.sprite.cavern.grass_long-0", + model: "voxygen.voxel.sprite.cave.grass_blue_long-0", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-1", + model: "voxygen.voxel.sprite.cave.grass_blue_long-1", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-2", + model: "voxygen.voxel.sprite.cave.grass_blue_long-2", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-3", + model: "voxygen.voxel.sprite.cave.grass_blue_long-3", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-4", + model: "voxygen.voxel.sprite.cave.grass_blue_long-4", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-5", + model: "voxygen.voxel.sprite.cave.grass_blue_long-5", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-6", + model: "voxygen.voxel.sprite.cave.grass_blue_long-6", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.grass_long-7", + model: "voxygen.voxel.sprite.cave.grass_blue_long-7", offset: (-5.5, -5.5, 0.0), lod_axes: (0.0, 0.0, 1.0), ), @@ -4247,27 +4606,27 @@ CavernLillypadBlue: Some(( ], wind_sway: 0.0, )), -// Cavern Hanging Mycel Blue -CavernMycelBlue: Some(( +// Cave Hanging Mycel Blue +MycelBlue: Some(( variations: [ ( - model: "voxygen.voxel.sprite.cavern.mycel-0", - offset: (-0.5, -0.5, -21.0), + model: "voxygen.voxel.sprite.cave.ceiling.mycel-0", + offset: (-1.0, -1.0, -12.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.mycel-1", - offset: (-0.5, -0.5, -31.0), + model: "voxygen.voxel.sprite.cave.ceiling.mycel-1", + offset: (-1.0, -1.0, -25.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.mycel-2", - offset: (-0.5, -0.5, -14.0), + model: "voxygen.voxel.sprite.cave.ceiling.mycel-2", + offset: (-1.0, -1.0, -18.0), lod_axes: (0.0, 0.0, 1.0), ), ( - model: "voxygen.voxel.sprite.cavern.mycel-3", - offset: (-0.5, -0.5, -40.0), + model: "voxygen.voxel.sprite.cave.ceiling.mycel-3", + offset: (-1.0, -1.0, -29.0), lod_axes: (0.0, 0.0, 1.0), ), ], diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index bd2a4bc06a..35a2d3f8f3 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -354,7 +354,10 @@ impl Block { | SpriteKind::Turnip => Some(rtsim::ChunkResource::Vegetable), SpriteKind::Mushroom | SpriteKind::CaveMushroom - | SpriteKind::CeilingMushroom => Some(rtsim::ChunkResource::Mushroom), + | SpriteKind::CeilingMushroom + | SpriteKind::RockyMushroom + | SpriteKind::LushMushroom + | SpriteKind::GlowMushroom => Some(rtsim::ChunkResource::Mushroom), SpriteKind::Chest | SpriteKind::ChestBuried @@ -393,15 +396,21 @@ impl Block { SpriteKind::DiamondLight => 30, SpriteKind::Velorite | SpriteKind::VeloriteFrag - | SpriteKind::CavernGrassBlueShort - | SpriteKind::CavernGrassBlueMedium - | SpriteKind::CavernGrassBlueLong + | SpriteKind::GrassBlueShort + | SpriteKind::GrassBlueMedium + | SpriteKind::GrassBlueLong | SpriteKind::CavernLillypadBlue - | SpriteKind::CavernMycelBlue + | SpriteKind::MycelBlue + | SpriteKind::Mold | SpriteKind::CeilingMushroom => 6, SpriteKind::CaveMushroom + | SpriteKind::GlowMushroom | SpriteKind::CookingPot | SpriteKind::CrystalHigh + | SpriteKind::LanternFlower + | SpriteKind::CeilingLanternFlower + | SpriteKind::LanternPlant + | SpriteKind::CeilingLanternPlant | SpriteKind::CrystalLow => 10, SpriteKind::SewerMushroom => 16, SpriteKind::Amethyst diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index a5773b7da8..9eafd13111 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -160,41 +160,46 @@ sprites! { LargeCactus = 0x05, TallCactus = 0x06, // Flowers - BlueFlower = 0x10, - PinkFlower = 0x11, - PurpleFlower = 0x12, - RedFlower = 0x13, - WhiteFlower = 0x14, - YellowFlower = 0x15, - Sunflower = 0x16, - Moonbell = 0x17, - Pyrebloom = 0x18, + BlueFlower = 0x10, + PinkFlower = 0x11, + PurpleFlower = 0x12, + RedFlower = 0x13, + WhiteFlower = 0x14, + YellowFlower = 0x15, + Sunflower = 0x16, + Moonbell = 0x17, + Pyrebloom = 0x18, + LushFlower = 0x19, + LanternFlower = 0x1A, // Grasses, ferns, and other 'wild' plants/fungi // TODO: remove sizes, make part of the `Growth` attribute - LongGrass = 0x20, - MediumGrass = 0x21, - ShortGrass = 0x22, - Fern = 0x23, - LargeGrass = 0x24, - GrassSnow = 0x25, - Reed = 0x26, - GrassBlue = 0x27, - SavannaGrass = 0x28, - TallSavannaGrass = 0x29, - RedSavannaGrass = 0x2A, - SavannaBush = 0x2B, - Welwitch = 0x2C, - LeafyPlant = 0x2D, - DeadBush = 0x2E, - JungleFern = 0x2F, - CavernGrassBlueShort = 0x30, - CavernGrassBlueMedium = 0x31, - CavernGrassBlueLong = 0x32, - CavernLillypadBlue = 0x33, - EnsnaringVines = 0x34, - LillyPads = 0x35, - JungleLeafyPlant = 0x36, - JungleRedGrass = 0x37, + LongGrass = 0x20, + MediumGrass = 0x21, + ShortGrass = 0x22, + Fern = 0x23, + LargeGrass = 0x24, + GrassSnow = 0x25, + Reed = 0x26, + GrassBlue = 0x27, + SavannaGrass = 0x28, + TallSavannaGrass = 0x29, + RedSavannaGrass = 0x2A, + SavannaBush = 0x2B, + Welwitch = 0x2C, + LeafyPlant = 0x2D, + DeadBush = 0x2E, + JungleFern = 0x2F, + GrassBlueShort = 0x30, + GrassBlueMedium = 0x31, + GrassBlueLong = 0x32, + CavernLillypadBlue = 0x33, + EnsnaringVines = 0x34, + LillyPads = 0x35, + JungleLeafyPlant = 0x36, + JungleRedGrass = 0x37, + LanternPlant = 0x38, + SporeReed = 0x39, + DeadPlant = 0x3A, // Crops, berries, and fungi Corn = 0x40, WheatYellow = 0x41, @@ -213,6 +218,9 @@ sprites! { Cotton = 0x4E, WildFlax = 0x4F, SewerMushroom = 0x50, + LushMushroom = 0x51, + RockyMushroom = 0x52, + GlowMushroom = 0x53, // Seaweeds, corals, and other underwater plants StonyCoral = 0x60, SoftCoral = 0x61, @@ -227,9 +235,14 @@ sprites! { Seagrass = 0x6A, RedAlgae = 0x6B, // Danglying ceiling plants/fungi - Liana = 0x70, - CavernMycelBlue = 0x71, - CeilingMushroom = 0x72, + Liana = 0x70, + MycelBlue = 0x71, + CeilingMushroom = 0x72, + Mold = 0x73, + Root = 0x74, + CeilingLanternPlant = 0x75, + CeilingLanternFlower = 0x76, + CeilingJungleLeafyPlant = 0x77, }, // Solid resources // TODO: Remove small variants, make deposit size be an attribute diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 4b87d671f7..fcb78aedf4 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -778,8 +778,13 @@ fn write_column( { if head_dist < 0.85 { let radial = (rpos.x.atan2(rpos.y) * 10.0).sin() * 0.5 + 0.5; + let block_kind = if head_dist < 0.5 { + BlockKind::GlowingMushroom + } else { + BlockKind::Rock + }; return Some(Block::new( - BlockKind::GlowingMushroom, + block_kind, Rgb::new( 30, 50 + (radial * 100.0) as u8, @@ -806,7 +811,7 @@ fn write_column( let sprites = if dynamic_rng.gen_bool(0.1) { &[Beehive, Lantern] as &[_] } else { - &[Orb, CavernMycelBlue, CavernMycelBlue] as &[_] + &[/* Orb, */ MycelBlue, MycelBlue] as &[_] }; return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); } @@ -932,7 +937,8 @@ fn write_column( let mut rng = RandomPerm::new(((vine_pos.x << 16) | vine_pos.y) as u32); if rng.gen_bool( - 0.15 * close(biome.mushroom, 1.0, 0.2) as f64 + 0.025 + * close(biome.mushroom, 1.0, 0.2) as f64 * close(max_height as f32, 64.0, 56.0) as f64, ) && ceiling_cover > 0.0 { @@ -1011,7 +1017,8 @@ fn write_column( ); Block::new( if rand.chance(wpos, (biome.mushroom * biome.mineral * 0.5).max(biome.icy)) { - BlockKind::GlowingWeakRock + // BlockKind::GlowingWeakRock + BlockKind::WeakRock } else if rand.chance(wpos, biome.sandy) { BlockKind::Sand } else { @@ -1096,20 +1103,26 @@ fn write_column( } } else if let Some(sprite) = (z == floor && !void_below && !sky_above) .then(|| { - if rand.chance(wpos2d.with_z(1), biome.mushroom * 0.05) { + if rand.chance( + wpos2d.with_z(1), + biome.mushroom + * 0.3 + * col.marble_mid + * (col.marble_mid > 0.55) as u32 as f32, + ) { [ - (SpriteKind::CaveMushroom, 0.15), + (SpriteKind::GlowMushroom, 0.5), (SpriteKind::Mushroom, 0.25), - (SpriteKind::GrassBlue, 1.0), - (SpriteKind::CavernGrassBlueShort, 1.0), - (SpriteKind::CavernGrassBlueMedium, 1.0), - (SpriteKind::CavernGrassBlueLong, 1.0), + (SpriteKind::GrassBlue, 0.0), + (SpriteKind::GrassBlueMedium, 1.5), + (SpriteKind::GrassBlueLong, 2.0), (SpriteKind::Moonbell, 0.01), + (SpriteKind::SporeReed, 2.5), ] .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(15), biome.leafy * 0.05) { + } else if rand.chance(wpos2d.with_z(15), biome.leafy * 0.05 * col.marble_mid) { [ (SpriteKind::LongGrass, 1.0), (SpriteKind::MediumGrass, 2.0), @@ -1123,6 +1136,10 @@ fn write_column( (SpriteKind::LeafyPlant, 0.8), (SpriteKind::Twigs, 0.07), (SpriteKind::Wood, 0.03), + (SpriteKind::LanternPlant, 1.0), + (SpriteKind::LanternFlower, 0.6), + (SpriteKind::LushFlower, 0.75), + (SpriteKind::LushMushroom, 0.5), ] .choose_weighted(rng, |(_, w)| *w) .ok() @@ -1132,6 +1149,7 @@ fn write_column( (SpriteKind::Bones, 0.5), (SpriteKind::Stones, 1.5), (SpriteKind::DeadBush, 1.0), + (SpriteKind::DeadPlant, 1.5), (SpriteKind::EnsnaringWeb, 0.5), (SpriteKind::Mud, 0.025), ] @@ -1140,8 +1158,11 @@ fn write_column( .map(|s| s.0) } else if rand.chance(wpos2d.with_z(14), biome.barren * 0.003) { [ + (SpriteKind::Bones, 0.5), (SpriteKind::Welwitch, 0.5), (SpriteKind::DeadBush, 1.5), + (SpriteKind::DeadPlant, 1.5), + (SpriteKind::RockyMushroom, 1.5), (SpriteKind::Crate, 0.005), ] .choose_weighted(rng, |(_, w)| *w) @@ -1224,24 +1245,32 @@ fn write_column( } else if let Some(sprite) = (z == ceiling - 1 && !void_above) .then(|| { if rand.chance(wpos2d.with_z(3), biome.mushroom * 0.01) { - Some( - *[ - SpriteKind::CavernMycelBlue, - SpriteKind::CeilingMushroom, - SpriteKind::Orb, - ] - .choose(rng) - .unwrap(), - ) + [ + (SpriteKind::MycelBlue, 0.0), + (SpriteKind::CeilingMushroom, 0.0), + // (SpriteKind::Orb, 0.25), + (SpriteKind::Mold, 0.9), + ] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .map(|s| s.0) } else if rand.chance(wpos2d.with_z(4), biome.leafy * 0.015) { [ (SpriteKind::Liana, 1.0), - (SpriteKind::Orb, 0.5), + (SpriteKind::CeilingLanternPlant, 1.5), + (SpriteKind::CeilingLanternFlower, 1.25), + (SpriteKind::CeilingJungleLeafyPlant, 1.0), + // (SpriteKind::Orb, 0.0), (SpriteKind::CrystalHigh, 0.1), ] .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) + } else if rand.chance(wpos2d.with_z(5), biome.barren * 0.015) { + [(SpriteKind::Root, 1.5)] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .map(|s| s.0) } else if rand.chance(wpos2d.with_z(5), biome.mineral * 0.005) { Some(*[SpriteKind::CrystalHigh].choose(rng).unwrap()) } else { diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 01c085823a..b19b5db492 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -933,7 +933,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let sprites = if dynamic_rng.gen_bool(0.1) { &[Beehive, Lantern] as &[_] } else { - &[Orb, CavernMycelBlue, CavernMycelBlue] as &[_] + &[Orb, MycelBlue, MycelBlue] as &[_] }; return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); } @@ -1091,11 +1091,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { Block::air( *if dynamic_rng.gen_bool(0.9) { // High density - &[ - CavernGrassBlueShort, - CavernGrassBlueMedium, - CavernGrassBlueLong, - ] as &[_] + &[GrassBlueShort, GrassBlueMedium, GrassBlueLong] as &[_] } else if dynamic_rng.gen_bool(0.5) { // Medium density &[CaveMushroom] as &[_] @@ -1108,7 +1104,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { ) } else if z == cavern_top - 1 && dynamic_rng.gen_bool(0.001) { Block::air( - *[CrystalHigh, CeilingMushroom, Orb, CavernMycelBlue] + *[CrystalHigh, CeilingMushroom, Orb, MycelBlue] .choose(dynamic_rng) .unwrap(), ) From 156ced16c5d0c89d75cfa3bf8ca1e0fcddecb3c2 Mon Sep 17 00:00:00 2001 From: Gemu Peachems Date: Sat, 17 Feb 2024 02:01:01 +0100 Subject: [PATCH 08/24] Change various cave colors --- world/src/layer/cave.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index fcb78aedf4..6ba9cdc7cf 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -229,7 +229,7 @@ impl Tunnel { // temperatures let mushroom = underground * close(humidity, 1.0, 0.7) - * close(temp, 0.25, 1.0) + * close(temp, 0.25, 2.0) * close(depth, 0.8, 0.5); // Extremely hot and dry areas deep underground let fire = underground @@ -519,7 +519,7 @@ fn write_column( .max(biome.icy - 0.6) .max(biome.sandy - 0.3) .max(biome.leafy - 0.4) - .max(biome.mushroom - 0.5) + .max(biome.mushroom - 0.4) { cavern_height * col.marble_mid as f64 } else { @@ -787,8 +787,8 @@ fn write_column( block_kind, Rgb::new( 30, - 50 + (radial * 100.0) as u8, - 100 - (radial * 50.0) as u8, + 120 + (radial * 30.0) as u8, + 180 - (radial * 30.0) as u8, ), )); } else if head_dist < 1.0 { @@ -951,8 +951,8 @@ fn write_column( .magnitude_squared() < 1.0f32 { - let kind = BlockKind::GlowingMushroom; - Some(Block::new(kind, Rgb::new(0, 95, 200))) + let kind = BlockKind::GlowingRock; + Some(Block::new(kind, Rgb::new(10, 70, 148))) } else { None } @@ -987,8 +987,8 @@ fn write_column( Lerp::lerp( Lerp::lerp( Lerp::lerp( - Rgb::new(80, 100, 150), - Rgb::new(0, 75, 200), + Rgb::new(20, 21, 49), + Rgb::new(23, 44, 88), biome.mushroom, ), Lerp::lerp( @@ -1006,8 +1006,8 @@ fn write_column( biome.sandy, ), Lerp::lerp( - Rgb::new(0, 100, 50), - Rgb::new(80, 100, 20), + Rgb::new(0, 73, 12), + Rgb::new(49, 63, 12), col.marble_small, ), biome.leafy, From 0d373c045590f6240aec9094a29d47fb5865bcc7 Mon Sep 17 00:00:00 2001 From: Syniis Date: Sun, 18 Feb 2024 06:34:53 +0100 Subject: [PATCH 09/24] Roots, flowers, patches, biomes --- world/src/layer/cave.rs | 337 +++++++++++++++++++++++++--------------- 1 file changed, 214 insertions(+), 123 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 6ba9cdc7cf..a9b52bdd55 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -228,33 +228,33 @@ impl Tunnel { // Mushrooms grow underground and thrive in a humid environment with moderate // temperatures let mushroom = underground - * close(humidity, 1.0, 0.7) - * close(temp, 0.25, 2.0) - * close(depth, 0.8, 0.5); + * close(humidity, 1.0, 0.70) + * close(temp, 1.2, 1.0) + * close(depth, 1.0, 0.7); // Extremely hot and dry areas deep underground let fire = underground - * close(humidity, 0.0, 0.7) + * close(humidity, 0.0, 0.6) * close(temp, 2.5, 1.5) - * close(depth, 1.0, 0.65); + * close(depth, 1.0, 0.55); // Overgrown with plants that need a moderate climate to survive let leafy = underground - * close(humidity, 0.5, 0.3) - * close(temp, 0.6, 0.9) - * close(depth, 0.1, 0.5); + * close(humidity, 0.5, 0.7) + * close(temp, 0.8, 0.7) + * close(depth, 0.0, 0.75); // Cool temperature, dry and devoid of value let dusty = - close(humidity, 0.0, 0.4) * close(temp, -0.3, 0.65) * close(mineral, -0.5, 1.5); + close(humidity, 0.0, 0.5) * close(temp, -0.1, 0.6) * close(mineral, -1.0, 2.0); // Deep underground and freezing cold - let icy = underground * close(temp, -1.0, 0.3) * close(depth, 1.0, 0.5); + let icy = underground * close(temp, -1.0, 0.6) * close(depth, 1.0, 0.5); // Rocky cold cave that appear near the surface - let snowy = close(temp, -0.6, 0.3) * close(depth, 0.1, 0.4); + let snowy = close(temp, -0.5, 0.3) * close(depth, 0.0, 0.5); // Crystals grow deep underground in areas rich with minerals. They are present // in areas with colder temperatures and low humidity let crystal = underground * close(humidity, 0.0, 0.65) - * close(temp, -0.1, 1.0) - * close(depth, 1.0, 0.45) - * close(mineral, 1.5, 1.0); + * close(temp, -0.3, 0.9) + * close(depth, 1.0, 0.6) + * close(mineral, 1.5, 1.5); // Hot, dry and shallow let sandy = close(humidity, 0.0, 0.2) * close(temp, 0.7, 0.8) * close(depth, 0.1, 0.5); @@ -437,6 +437,11 @@ enum CaveStructure { Mushroom(Mushroom), Crystal(CrystalCluster), Flower(Flower), + GiantRoot { + pos: Vec3, + radius: f32, + height: f32, + }, } struct Mushroom { @@ -462,6 +467,8 @@ struct Flower { stalk: f32, petals: usize, petal_height: f32, + petal_radius: f32, + rotation: Mat3, } #[inline_tweak::tweak_fn] @@ -622,7 +629,7 @@ fn write_column( .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) .or_insert_with(|| { let mut rng = RandomPerm::new(seed); - let (z_range, _, vertical, _) = + let (z_range, horizontal, vertical, _) = tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; let pos = wpos2d.with_z(z_range.start); @@ -633,10 +640,11 @@ fn write_column( return None; } - if rng.gen_bool( - 0.5 * close(vertical as f32, 64.0, 48.0) as f64 - * close(biome.mushroom, 1.0, 0.7) as f64, - ) && biome.mushroom > 0.5 + if biome.mushroom > 0.7 + && rng.gen_bool( + 0.5 * close(vertical as f32, 64.0, 48.0) as f64 + * close(biome.mushroom, 1.0, 0.7) as f64, + ) { let purp = rng.gen_range(0..50); Some(CaveStructure::Mushroom(Mushroom { @@ -651,7 +659,9 @@ fn write_column( rng.gen_range(80..200) + purp, ), })) - } else if rng.gen_bool(0.6 * close(biome.crystal, 1.0, 0.7) as f64) { + } else if biome.crystal > 0.5 + && rng.gen_bool(0.6 * close(biome.crystal, 1.0, 0.7) as f64) + { let colors = [ Rgb::new(209, 106, 255), Rgb::new(187, 86, 240), @@ -715,20 +725,41 @@ fn write_column( crystals, color, })) - } else if rng.gen_bool( - 0.2 * close(vertical as f32, 64.0, 48.0) as f64 - * close(biome.leafy, 1.5, 0.8) as f64, - ) && biome.leafy > 0.8 + } else if biome.leafy > 0.8 + && rng.gen_bool( + 0.2 * close(vertical as f32, 64.0, 52.0) as f64 + * close(biome.leafy, 1.0, 0.2) as f64, + ) { Some(CaveStructure::Flower(Flower { pos, - stalk: 4.0 + stalk: 8.0 + rng.gen::().powf(2.0) * (z_range.end - z_range.start - 8) as f32 - * 0.6, + * 0.8, petals: rng.gen_range(1..5) * 2 + 1, petal_height: rng.gen_range(4.0..8.0), + petal_radius: rng.gen_range(10.0..18.0), + rotation: (Mat3::rotation_x( + -(rng.gen_bool(1.0) as u32 as f32) * std::f32::consts::PI + / rng.gen_range(3.0..16.0), + ) * Mat3::rotation_y( + std::f32::consts::PI / rng.gen_range(3.0..16.0), + )) + .transposed(), })) + } else if biome.leafy > 0.5 + && rng.gen_bool(0.6 * close(biome.leafy, 1.0, 0.5) as f64) + { + Some(CaveStructure::GiantRoot { + pos, + radius: rng.gen_range( + 3.0..(6.0 + + close(vertical as f32, 64.0, 32.0) * 2.0 + + close(horizontal as f32, 64.0, 32.0) * 2.0), + ), + height: (z_range.end - z_range.start) as f32, + }) } else { None } @@ -811,7 +842,7 @@ fn write_column( let sprites = if dynamic_rng.gen_bool(0.1) { &[Beehive, Lantern] as &[_] } else { - &[/* Orb, */ MycelBlue, MycelBlue] as &[_] + &[MycelBlue, MycelBlue] as &[_] }; return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); } @@ -860,41 +891,64 @@ fn write_column( } }, CaveStructure::Flower(flower) => { - let wposf = wpos.map(|e| e as f64); - let warp_freq = 1.0 / 32.0; - let warp_amp = Vec3::new(4.0, 4.0, 4.0); - let wposf_warped = wposf.map(|e| e as f32) - + Vec3::new( - FastNoise::new(seed).get(wposf * warp_freq), - FastNoise::new(seed + 1).get(wposf * warp_freq), - FastNoise::new(seed + 2).get(wposf * warp_freq), - ) * warp_amp - * (wposf.z as f32 - flower.pos.z as f32) - .mul(0.1) - .clamped(0.0, 1.0); + let wposf = wpos.map(|e| e as f32); - let rpos = wposf_warped - flower.pos.map(|e| e as f32); + let rpos = wposf - flower.pos.map(|e| e as f32); let stalk_radius = 2.5f32; - let petal_radius = 12.0f32; + let petal_radius = flower.petal_radius; let petal_thickness = 2.5; - let dist = rpos.xy().magnitude_squared(); - let petal_radius = petal_radius.powi(2); - if dist < petal_radius { - let petal_height_at = (dist / petal_radius).powf(1.5) * flower.petal_height; - if rpos.z > flower.stalk + petal_height_at - 1.0 - && rpos.z <= flower.stalk + petal_height_at + petal_thickness + let dist_sq = rpos.xy().magnitude_squared(); + if rpos.z < flower.stalk + && dist_sq + < (stalk_radius * Lerp::lerp(1.0, 0.75, rpos.z / flower.stalk)).powi(2) + { + return Some(Block::new(BlockKind::Wood, Rgb::new(0, 108, 0))); + } + + let rpos = wposf - flower.pos.map(|e| e as f32) - Vec3::unit_z() * flower.stalk; + let rpos = flower.rotation * (rpos - 0.5); + let dist_sq = rpos.xy().magnitude_squared(); + let petal_radius_sq = petal_radius.powi(2); + if dist_sq < petal_radius_sq { + let petal_height_at = + (dist_sq / petal_radius_sq).powf(1.5) * flower.petal_height; + if rpos.z > petal_height_at - 1.0 + && rpos.z <= petal_height_at + petal_thickness { - let away = dist / petal_radius; - if away > 0.3 { - let near = (rpos.x.atan2(rpos.y)) - .rem_euclid(std::f32::consts::TAU / flower.petals as f32); - let inset = close(near, -1.0, 0.85).max(close(near, 1.0, 0.85)); - if dist / petal_radius < inset { + let dist_ratio = dist_sq / petal_radius_sq; + let yellow = (60.0 * dist_ratio) as u8; + if dist_ratio < 0.175 && rpos.z > petal_height_at { + let near = (rpos.x.atan2(rpos.y)).rem_euclid( + std::f32::consts::TAU / (flower.petals as f32 * 1.5), + ); + let inset = close(near, 0.0, 0.475); + let inset2 = close(near, 0.0, 0.3); + if dist_ratio > inset { return Some(Block::new( BlockKind::Wood, - Rgb::new(240, 50, 50), + Rgb::new(240, 80 - yellow, 80 - yellow), + )); + } else if dist_ratio > inset2 { + return Some(Block::new( + BlockKind::Wood, + Rgb::new(33, 74, 238), + )); + } else { + return Some(Block::new( + BlockKind::Wood, + Rgb::new(249, 213, 237), + )); + } + } else if dist_ratio > 0.3 { + let near = (rpos.x.atan2(rpos.y)) + .rem_euclid(std::f32::consts::TAU / flower.petals as f32); + let inset = close(near, -1.0, 0.9).max(close(near, 1.0, 0.9)); + if dist_ratio < inset { + return Some(Block::new( + BlockKind::Wood, + Rgb::new(240, 80 - yellow, 80 - yellow), )); } } else { @@ -902,28 +956,50 @@ fn write_column( } } - let above_stalk = rpos.z - flower.stalk; - if above_stalk < 0.0 - && dist - < (stalk_radius * Lerp::lerp(1.0, 0.75, rpos.z / flower.stalk)) - .powi(2) - { - return Some(Block::new(BlockKind::Wood, Rgb::new(0, 108, 0))); - } - // pollen let pollen_height = 5.0; - if above_stalk > 0.0 - && above_stalk < pollen_height - && dist - < (stalk_radius - * Lerp::lerp(0.5, 1.25, above_stalk / pollen_height)) - .powi(2) + if rpos.z > 0.0 + && rpos.z < pollen_height + && dist_sq + < (stalk_radius * Lerp::lerp(0.5, 1.25, rpos.z / pollen_height)) + .powi(2) { - return Some(Block::new(BlockKind::Wood, Rgb::new(239, 192, 0))); + return Some(Block::new( + BlockKind::GlowingMushroom, + Rgb::new(239, 192, 0), + )); } } }, + CaveStructure::GiantRoot { + pos, + radius, + height, + } => { + let wposf = wpos.map(|e| e as f64); + let warp_freq = 1.0 / 32.0; + let warp_amp = Vec3::new(20.0, 20.0, 20.0); + let wposf_warped = wposf.map(|e| e as f32) + + Vec3::new( + FastNoise::new(seed).get(wposf * warp_freq), + FastNoise::new(seed + 1).get(wposf * warp_freq), + FastNoise::new(seed + 2).get(wposf * warp_freq), + ) * warp_amp; + let rpos = wposf_warped - pos.map(|e| e as f32); + let dist_sq = rpos.xy().magnitude_squared(); + if dist_sq < radius.powi(2) { + if col.marble_mid + > (std::f32::consts::PI * rpos.z / *height) + .sin() + .powf(2.0) + .mul(0.25) + .add(col.marble_small) + { + return Some(Block::new(BlockKind::Wood, Rgb::new(0, 73, 12))); + } + return Some(Block::new(BlockKind::Wood, Rgb::new(111, 78, 55))); + } + }, } } None @@ -931,28 +1007,26 @@ fn write_column( let ceiling_mold = |wpos: Vec3| { let wpos = wpos + wpos.xy().yx().with_z(0.0) * 0.2; - let dims = Vec2::new(3.0, 24.0); - let vine_posf = wpos + Vec2::unit_y() * (wpos.x / dims.x).floor() * 71.0 / dims; - let vine_pos = vine_posf.map(|e| e.floor() as i32); - let mut rng = RandomPerm::new(((vine_pos.x << 16) | vine_pos.y) as u32); + let dims = Vec2::new(4.0, 32.0); + let mold_posf = wpos + Vec2::unit_y() * (wpos.x / dims.x).floor() * 89.0 / dims; + let mold_pos = mold_posf.map(|e| e.floor() as i32); + let mut rng = RandomPerm::new(((mold_pos.x << 16) | mold_pos.y) as u32); - if rng.gen_bool( - 0.025 - * close(biome.mushroom, 1.0, 0.2) as f64 - * close(max_height as f32, 64.0, 56.0) as f64, - ) && ceiling_cover > 0.0 + if biome.mushroom > 0.7 + && ceiling_cover > 0.0 + && rng.gen_bool(0.025 * close(biome.mushroom, 1.0, 0.3) as f64) { - let vine_base = z_range.end as f32; - let vine_y = (vine_posf.y.fract() - 0.5).abs() * 2.0 * dims.y; - let vine_reach = (vine_y * 0.05).powf(2.0).min(32.0); - let vine_z = vine_base - vine_reach; + let mold_length = ((mold_posf.y.fract() - 0.5).abs() * 2.0 * dims.y) + .mul(0.05) + .powf(2.0) + .min(8.0); + let mold_z = z_range.end as f32 - mold_length; - if Vec2::new(vine_posf.x.fract() * 2.0 - 1.0, (vine_z - wpos.z) / 4.0) + if Vec2::new(mold_posf.x.fract() * 2.0 - 1.0, (mold_z - wpos.z) / 4.0) .magnitude_squared() < 1.0f32 { - let kind = BlockKind::GlowingRock; - Some(Block::new(kind, Rgb::new(10, 70, 148))) + Some(Block::new(BlockKind::GlowingRock, Rgb::new(10, 70, 148))) } else { None } @@ -1005,11 +1079,7 @@ fn write_column( ), biome.sandy, ), - Lerp::lerp( - Rgb::new(0, 73, 12), - Rgb::new(49, 63, 12), - col.marble_small, - ), + Lerp::lerp(Rgb::new(0, 73, 12), Rgb::new(49, 63, 12), col.marble_small), biome.leafy, ), Lerp::lerp(Rgb::new(100, 150, 255), Rgb::new(100, 120, 255), col.marble), @@ -1122,28 +1192,55 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(15), biome.leafy * 0.05 * col.marble_mid) { - [ - (SpriteKind::LongGrass, 1.0), - (SpriteKind::MediumGrass, 2.0), - (SpriteKind::ShortGrass, 2.0), - (SpriteKind::JungleFern, 0.5), - (SpriteKind::JungleLeafyPlant, 0.5), - (SpriteKind::JungleRedGrass, 0.35), - (SpriteKind::Mushroom, 0.15), - (SpriteKind::EnsnaringVines, 0.2), - (SpriteKind::Fern, 0.75), - (SpriteKind::LeafyPlant, 0.8), - (SpriteKind::Twigs, 0.07), - (SpriteKind::Wood, 0.03), - (SpriteKind::LanternPlant, 1.0), - (SpriteKind::LanternFlower, 0.6), - (SpriteKind::LushFlower, 0.75), - (SpriteKind::LushMushroom, 0.5), - ] - .choose_weighted(rng, |(_, w)| *w) - .ok() - .map(|s| s.0) + } else if rand.chance( + wpos2d.with_z(15), + biome.leafy * 0.45 * col.marble_mid * (col.marble_mid > 0.6) as u32 as f32, + ) { + let mixed = col.marble.add(col.marble_small.sub(0.5).mul(0.25)); + if (0.25..0.45).contains(&mixed) || (0.55..0.75).contains(&mixed) { + return [ + (SpriteKind::LongGrass, 1.0), + (SpriteKind::MediumGrass, 2.0), + (SpriteKind::ShortGrass, 2.0), + (SpriteKind::JungleFern, 0.5), + (SpriteKind::JungleRedGrass, 0.35), + (SpriteKind::Fern, 0.75), + (SpriteKind::LeafyPlant, 0.8), + (SpriteKind::JungleLeafyPlant, 0.5), + (SpriteKind::LanternPlant, 0.1), + (SpriteKind::LanternFlower, 0.1), + (SpriteKind::LushFlower, 0.2), + ] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .map(|s| s.0); + } else if (0.0..0.25).contains(&mixed) { + return Some(SpriteKind::LanternPlant); + } else if (0.75..1.0).contains(&mixed) { + return Some(SpriteKind::LushFlower); + } else { + return [ + (SpriteKind::LongGrass, 1.0), + (SpriteKind::MediumGrass, 2.0), + (SpriteKind::ShortGrass, 2.0), + (SpriteKind::JungleFern, 0.5), + (SpriteKind::JungleLeafyPlant, 0.5), + (SpriteKind::JungleRedGrass, 0.35), + (SpriteKind::Mushroom, 0.15), + (SpriteKind::EnsnaringVines, 0.2), + (SpriteKind::Fern, 0.75), + (SpriteKind::LeafyPlant, 0.8), + (SpriteKind::Twigs, 0.07), + (SpriteKind::Wood, 0.03), + (SpriteKind::LanternPlant, 0.3), + (SpriteKind::LanternFlower, 0.3), + (SpriteKind::LushFlower, 0.5), + (SpriteKind::LushMushroom, 1.0), + ] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .map(|s| s.0); + } } else if rand.chance(wpos2d.with_z(2), biome.dusty.max(biome.sandy) * 0.01) { [ (SpriteKind::Bones, 0.5), @@ -1245,22 +1342,16 @@ fn write_column( } else if let Some(sprite) = (z == ceiling - 1 && !void_above) .then(|| { if rand.chance(wpos2d.with_z(3), biome.mushroom * 0.01) { - [ - (SpriteKind::MycelBlue, 0.0), - (SpriteKind::CeilingMushroom, 0.0), - // (SpriteKind::Orb, 0.25), - (SpriteKind::Mold, 0.9), - ] - .choose_weighted(rng, |(_, w)| *w) - .ok() - .map(|s| s.0) + [(SpriteKind::MycelBlue, 0.75), (SpriteKind::Mold, 1.0)] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .map(|s| s.0) } else if rand.chance(wpos2d.with_z(4), biome.leafy * 0.015) { [ (SpriteKind::Liana, 1.0), (SpriteKind::CeilingLanternPlant, 1.5), (SpriteKind::CeilingLanternFlower, 1.25), (SpriteKind::CeilingJungleLeafyPlant, 1.0), - // (SpriteKind::Orb, 0.0), (SpriteKind::CrystalHigh, 0.1), ] .choose_weighted(rng, |(_, w)| *w) From 36ca473ea26252eb39e3f65c07e5a9397663a679 Mon Sep 17 00:00:00 2001 From: Gemu Peachems Date: Sun, 18 Feb 2024 17:07:28 +0100 Subject: [PATCH 10/24] Change various cave colors --- world/src/layer/cave.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index a9b52bdd55..3b0d9b11c1 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -933,12 +933,12 @@ fn write_column( } else if dist_ratio > inset2 { return Some(Block::new( BlockKind::Wood, - Rgb::new(33, 74, 238), + Rgb::new(200, 14, 132), )); } else { return Some(Block::new( BlockKind::Wood, - Rgb::new(249, 213, 237), + Rgb::new(249, 156, 218), )); } } else if dist_ratio > 0.3 { @@ -995,9 +995,9 @@ fn write_column( .mul(0.25) .add(col.marble_small) { - return Some(Block::new(BlockKind::Wood, Rgb::new(0, 73, 12))); + return Some(Block::new(BlockKind::Wood, Rgb::new(48, 70, 25))); } - return Some(Block::new(BlockKind::Wood, Rgb::new(111, 78, 55))); + return Some(Block::new(BlockKind::Wood, Rgb::new(66, 41, 26))); } }, } @@ -1201,7 +1201,7 @@ fn write_column( return [ (SpriteKind::LongGrass, 1.0), (SpriteKind::MediumGrass, 2.0), - (SpriteKind::ShortGrass, 2.0), + (SpriteKind::ShortGrass, 0.0), (SpriteKind::JungleFern, 0.5), (SpriteKind::JungleRedGrass, 0.35), (SpriteKind::Fern, 0.75), @@ -1222,7 +1222,7 @@ fn write_column( return [ (SpriteKind::LongGrass, 1.0), (SpriteKind::MediumGrass, 2.0), - (SpriteKind::ShortGrass, 2.0), + (SpriteKind::ShortGrass, 0.0), (SpriteKind::JungleFern, 0.5), (SpriteKind::JungleLeafyPlant, 0.5), (SpriteKind::JungleRedGrass, 0.35), From 5d9202337efe3e4f1399fb1c748b079c4dfb1521 Mon Sep 17 00:00:00 2001 From: Syniis Date: Sun, 18 Feb 2024 23:58:37 +0100 Subject: [PATCH 11/24] Some performance improvements --- world/src/layer/cave.rs | 35 +++++++++++++++++++++++------------ world/src/util/fast_noise.rs | 6 +++--- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 3b0d9b11c1..796035c2aa 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1,7 +1,7 @@ use super::scatter::close; use crate::{ - util::{sampler::Sampler, FastNoise, RandomField, RandomPerm, StructureGen2d, LOCALITY}, + util::{sampler::Sampler, FastNoise2d, RandomField, RandomPerm, StructureGen2d, LOCALITY}, Canvas, CanvasInfo, ColumnSample, Land, }; use common::{ @@ -774,11 +774,14 @@ fn write_column( let wposf = wpos.map(|e| e as f64); let warp_freq = 1.0 / 32.0; let warp_amp = Vec3::new(12.0, 12.0, 12.0); + let xy = wposf.xy(); + let xz = Vec2::new(wposf.x, wposf.z); + let yz = Vec2::new(wposf.y, wposf.z); let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( - FastNoise::new(seed).get(wposf * warp_freq), - FastNoise::new(seed + 1).get(wposf * warp_freq), - FastNoise::new(seed + 2).get(wposf * warp_freq), + FastNoise2d::new(seed).get(yz * warp_freq), + FastNoise2d::new(seed).get(xz * warp_freq), + FastNoise2d::new(seed).get(xy * warp_freq), ) * warp_amp * (wposf.z as f32 - mushroom.pos.z as f32) .mul(0.1) @@ -809,7 +812,7 @@ fn write_column( { if head_dist < 0.85 { let radial = (rpos.x.atan2(rpos.y) * 10.0).sin() * 0.5 + 0.5; - let block_kind = if head_dist < 0.5 { + let block_kind = if dynamic_rng.gen_bool(0.1) { BlockKind::GlowingMushroom } else { BlockKind::Rock @@ -979,11 +982,14 @@ fn write_column( let wposf = wpos.map(|e| e as f64); let warp_freq = 1.0 / 32.0; let warp_amp = Vec3::new(20.0, 20.0, 20.0); + let xy = wposf.xy(); + let xz = Vec2::new(wposf.x, wposf.z); + let yz = Vec2::new(wposf.y, wposf.z); let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( - FastNoise::new(seed).get(wposf * warp_freq), - FastNoise::new(seed + 1).get(wposf * warp_freq), - FastNoise::new(seed + 2).get(wposf * warp_freq), + FastNoise2d::new(seed).get(yz * warp_freq), + FastNoise2d::new(seed).get(xz * warp_freq), + FastNoise2d::new(seed).get(xy * warp_freq), ) * warp_amp; let rpos = wposf_warped - pos.map(|e| e as f32); let dist_sq = rpos.xy().magnitude_squared(); @@ -1086,9 +1092,10 @@ fn write_column( biome.icy, ); Block::new( - if rand.chance(wpos, (biome.mushroom * biome.mineral * 0.5).max(biome.icy)) { - // BlockKind::GlowingWeakRock - BlockKind::WeakRock + if rand.chance(wpos, biome.mushroom * 0.01) { + BlockKind::GlowingWeakRock + } else if rand.chance(wpos, biome.icy) { + BlockKind::GlowingWeakRock } else if rand.chance(wpos, biome.sandy) { BlockKind::Sand } else { @@ -1164,7 +1171,11 @@ fn write_column( } else if biome.fire.max(biome.snowy) > 0.5 { BlockKind::Rock } else if biome.crystal > 0.5 { - BlockKind::GlowingRock + if rand.chance(wpos, biome.crystal * 0.05) { + BlockKind::GlowingRock + } else { + BlockKind::Rock + } } else { BlockKind::Sand }, diff --git a/world/src/util/fast_noise.rs b/world/src/util/fast_noise.rs index 84ac0dc87a..8e4b3fcc8a 100644 --- a/world/src/util/fast_noise.rs +++ b/world/src/util/fast_noise.rs @@ -110,9 +110,9 @@ impl Sampler<'static> for FastNoise2d { f.powi(2) * (3.0 - 2.0 * f) }); - let v0 = v00 + factor.y * (v10 - v00); - let v1 = v01 + factor.y * (v11 - v01); + let v0 = v00 + factor.x * (v10 - v00); + let v1 = v01 + factor.x * (v11 - v01); - (v0 + factor.x * (v1 - v0)) * 2.0 - 1.0 + (v0 + factor.y * (v1 - v0)) * 2.0 - 1.0 } } From 53cbb90b373cf91172b5655652e61c4ab3b70138 Mon Sep 17 00:00:00 2001 From: Syniis Date: Mon, 19 Feb 2024 03:15:58 +0100 Subject: [PATCH 12/24] Adopt cave performance improvements from zoomy-worldgen --- world/src/layer/cave.rs | 465 ++++++++++++++++++++++------------------ 1 file changed, 252 insertions(+), 213 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 796035c2aa..0b29727cdc 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1,22 +1,25 @@ use super::scatter::close; use crate::{ - util::{sampler::Sampler, FastNoise2d, RandomField, RandomPerm, StructureGen2d, LOCALITY}, + util::{ + sampler::Sampler, FastNoise2d, RandomField, RandomPerm, StructureGen2d, LOCALITY, SQUARE_4, + }, Canvas, CanvasInfo, ColumnSample, Land, }; use common::{ generation::EntityInfo, terrain::{ quadratic_nearest_point, river_spline_coeffs, Block, BlockKind, CoordinateConversions, - SpriteKind, + SpriteKind, TerrainChunkSize, }, + vol::RectVolSize, }; -use hashbrown::HashMap; use inline_tweak::tweak_fn; use noise::NoiseFn; use rand::prelude::*; use std::{ cmp::Ordering, + collections::HashMap, f64::consts::PI, ops::{Add, Mul, Range, Sub}, }; @@ -39,6 +42,7 @@ fn to_wpos(cell: Vec2, level: u32) -> Vec2 { const AVG_LEVEL_DEPTH: i32 = 120; const LAYERS: u32 = 4; +const MAX_RADIUS: f32 = 64.0; fn node_at(cell: Vec2, level: u32, land: &Land) -> Option { let rand = RandomField::new(37 + level); @@ -76,6 +80,7 @@ pub fn surface_entrances<'a>(land: &'a Land) -> impl Iterator> .filter_map(|cell| Some(tunnel_below_from_cell(cell, 0, land)?.a.wpos)) } +#[derive(Copy, Clone)] pub struct Tunnel { a: Node, b: Node, @@ -83,6 +88,8 @@ pub struct Tunnel { } impl Tunnel { + const RADIUS_RANGE: Range = 8.0..MAX_RADIUS as f64; + fn ctrl_offset(&self) -> Vec2 { let start = self.a.wpos.map(|e| e as f64 + 0.5); let end = self.b.wpos.map(|e| e as f64 + 0.5); @@ -91,70 +98,77 @@ impl Tunnel { .map(|e| e as f32) } - #[tweak_fn] - fn z_range_at( - &self, - wposf: Vec2, - info: CanvasInfo, - ) -> Option<(Range, f64, f64, f64)> { + fn possibly_near(&self, wposf: Vec2, threshold: f64) -> Option<(f64, Vec2, f64)> { let start = self.a.wpos.map(|e| e as f64 + 0.5); let end = self.b.wpos.map(|e| e as f64 + 0.5); - if let Some((t, closest, _)) = quadratic_nearest_point( &river_spline_coeffs(start, self.ctrl_offset(), end), wposf, Vec2::new(start, end), ) { - let dist = closest.distance(wposf); - let radius = 8.0..64.0; - if dist < radius.end + 1.0 { - let horizontal = Lerp::lerp( - radius.start, - radius.end, - (info.index().noise.cave_fbm_nz.get( - (closest.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 256.0) - .into_array(), - ) + 0.5) - .clamped(0.0, 1.0) - .powf(3.0), - ); - let vertical = Lerp::lerp( - radius.start, - radius.end, - (info.index().noise.cave_fbm_nz.get( - (closest.with_z(info.land().get_alt_approx(self.b.wpos) as f64) / 256.0) - .into_array(), - ) + 0.5) - .clamped(0.0, 1.0) - .powf(3.0), - ) - .clamped(radius.start + 0.0, radius.end); - let height_here = (1.0 - dist / horizontal).max(0.0).powf(0.3) * vertical; + let dist2 = closest.distance_squared(wposf); + if dist2 < (Self::RADIUS_RANGE.end + threshold).powi(2) { + Some((t, closest, dist2.sqrt())) + } else { + None + } + } else { + None + } + } - if height_here > 0.0 { - let z_offs = info - .index() - .noise - .cave_fbm_nz - .get((wposf / 512.0).into_array()) - * 96.0 - * ((1.0 - (t - 0.5).abs() * 2.0) * 8.0).min(1.0); - let alt_here = info.land().get_alt_approx(closest.map(|e| e as i32)); - let base = (Lerp::lerp( - alt_here as f64 - self.a.depth as f64, - alt_here as f64 - self.b.depth as f64, - t, - ) + z_offs) - .min(alt_here as f64); - Some(( - (base - height_here * 0.3) as i32..(base + height_here * 1.35) as i32, - horizontal, - vertical, - dist, - )) - } else { - None - } + #[tweak_fn] + fn z_range_at( + &self, + wposf: Vec2, + info: CanvasInfo, + ) -> Option<(Range, f32, f32, f32)> { + let _start = self.a.wpos.map(|e| e as f64 + 0.5); + let _end = self.b.wpos.map(|e| e as f64 + 0.5); + if let Some((t, closest, dist)) = self.possibly_near(wposf, 1.0) { + let horizontal = Lerp::lerp( + Self::RADIUS_RANGE.start, + Self::RADIUS_RANGE.end, + (info.index().noise.cave_fbm_nz.get( + (closest.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 256.0) + .into_array(), + ) + 0.5) + .clamped(0.0, 1.0) + .powf(3.0), + ); + let vertical = Lerp::lerp( + Self::RADIUS_RANGE.start, + Self::RADIUS_RANGE.end, + (info.index().noise.cave_fbm_nz.get( + (closest.with_z(info.land().get_alt_approx(self.b.wpos) as f64) / 256.0) + .into_array(), + ) + 0.5) + .clamped(0.0, 1.0) + .powf(3.0), + ); + let height_here = (1.0 - dist / horizontal).max(0.0).powf(0.3) * vertical; + + if height_here > 0.0 { + let z_offs = info + .index() + .noise + .cave_fbm_nz + .get((wposf / 512.0).into_array()) + * 96.0 + * ((1.0 - (t - 0.5).abs() * 2.0) * 8.0).min(1.0); + let alt_here = info.land().get_alt_approx(closest.map(|e| e as i32)); + let base = (Lerp::lerp( + alt_here as f64 - self.a.depth as f64, + alt_here as f64 - self.b.depth as f64, + t, + ) + z_offs) + .min(alt_here as f64); + Some(( + (base - height_here * 0.3) as i32..(base + height_here * 1.35) as i32, + horizontal as f32, + vertical as f32, + dist as f32, + )) } else { None } @@ -178,39 +192,34 @@ impl Tunnel { // effectively increase biome size let humidity = Lerp::lerp( col.humidity, - info.index() - .noise - .cave_nz - .get(wpos.xy().map(|e| e as f64 / 1024.0).into_array()) as f32, + FastNoise2d::new(41) + .get(wpos.xy().map(|e| e as f64 / 768.0)) + .mul(1.2), below, ); let temp = Lerp::lerp( col.temp, - info.index() - .noise - .cave_nz - .get(wpos.xy().map(|e| e as f64 / 2048.0).into_array()) + FastNoise2d::new(42) + .get(wpos.xy().map(|e| e as f64 / 1536.0)) + .mul(1.15) .mul(2.0) .sub(1.0) .add( - ((col.alt as f64 - wpos.z as f64) - / (AVG_LEVEL_DEPTH as f64 * LAYERS as f64 * 0.5)) + ((col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32 * 0.5)) .clamped(0.0, 2.5), - ) as f32, + ), below, ); - let mineral = info - .index() - .noise - .cave_nz - .get(wpos.xy().map(|e| e as f64 / 512.0).into_array()) + let mineral = FastNoise2d::new(43) + .get(wpos.xy().map(|e| e as f64 / 320.0)) + .mul(1.15) .mul(0.5) .add( - ((col.alt as f64 - wpos.z as f64) / (AVG_LEVEL_DEPTH as f64 * LAYERS as f64)) + ((col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32)) .clamped(0.0, 1.5), - ) as f32; + ); let [ barren, @@ -228,35 +237,37 @@ impl Tunnel { // Mushrooms grow underground and thrive in a humid environment with moderate // temperatures let mushroom = underground - * close(humidity, 1.0, 0.70) - * close(temp, 1.2, 1.0) - * close(depth, 1.0, 0.7); + * close(humidity, 1.0, 0.7) + * close(temp, 1.5, 0.9) + * close(depth, 1.0, 0.6); // Extremely hot and dry areas deep underground let fire = underground * close(humidity, 0.0, 0.6) - * close(temp, 2.5, 1.5) - * close(depth, 1.0, 0.55); + * close(temp, 2.5, 1.4) + * close(depth, 1.0, 0.5); // Overgrown with plants that need a moderate climate to survive let leafy = underground - * close(humidity, 0.5, 0.7) - * close(temp, 0.8, 0.7) - * close(depth, 0.0, 0.75); + * close(humidity, 0.8, 0.8) + * close(temp, 1.0, 0.8) + * close(depth, 0.0, 0.6); // Cool temperature, dry and devoid of value - let dusty = - close(humidity, 0.0, 0.5) * close(temp, -0.1, 0.6) * close(mineral, -1.0, 2.0); + let dusty = close(humidity, 0.0, 0.5) * close(temp, -0.1, 0.6); // Deep underground and freezing cold - let icy = underground * close(temp, -1.0, 0.6) * close(depth, 1.0, 0.5); + let icy = underground + * close(temp, -1.0, 0.6) + * close(depth, 1.0, 0.5) + * close(humidity, 1.0, 0.7); // Rocky cold cave that appear near the surface - let snowy = close(temp, -0.5, 0.3) * close(depth, 0.0, 0.5); + let snowy = close(temp, -0.5, 0.3) * close(depth, 0.0, 0.4); // Crystals grow deep underground in areas rich with minerals. They are present // in areas with colder temperatures and low humidity let crystal = underground - * close(humidity, 0.0, 0.65) - * close(temp, -0.3, 0.9) - * close(depth, 1.0, 0.6) - * close(mineral, 1.5, 1.5); + * close(humidity, 0.0, 0.7) + * close(temp, -0.5, 0.8) + * close(depth, 1.0, 0.55) + * close(mineral, 1.5, 1.0); // Hot, dry and shallow - let sandy = close(humidity, 0.0, 0.2) * close(temp, 0.7, 0.8) * close(depth, 0.1, 0.5); + let sandy = close(humidity, 0.0, 0.3) * close(temp, 0.7, 0.9) * close(depth, 0.0, 0.6); let biomes = [ barren, mushroom, fire, leafy, dusty, icy, snowy, crystal, sandy, @@ -352,69 +363,109 @@ fn tunnels_down_from<'a>( .filter_map(move |rpos| tunnel_below_from_cell(col_cell + rpos, level, land)) } +fn all_tunnels_at<'a>( + wpos2d: Vec2, + _info: &'a CanvasInfo, + land: &'a Land, +) -> impl Iterator + 'a { + (1..LAYERS + 1).flat_map(move |level| { + tunnels_at(wpos2d, level, land) + .chain(tunnels_down_from(wpos2d, level - 1, land)) + .map(move |tunnel| (level, tunnel)) + }) +} + +fn tunnel_bounds_at_from<'a>( + wpos2d: Vec2, + info: &'a CanvasInfo, + _land: &'a Land, + tunnels: impl Iterator + 'a, +) -> impl Iterator, f32, f32, f32, Tunnel)> + 'a { + let wposf = wpos2d.map(|e| e as f64 + 0.5); + info.col_or_gen(wpos2d) + .map(move |col| { + let col_alt = col.alt; + let col_water_dist = col.water_dist; + tunnels.filter_map(move |(level, tunnel)| { + let (z_range, horizontal, vertical, dist) = tunnel.z_range_at(wposf, *info)?; + // Avoid cave entrances intersecting water + let z_range = Lerp::lerp( + z_range.end, + z_range.start, + 1.0 - (1.0 + - ((col_water_dist.unwrap_or(1000.0) - 4.0).max(0.0) / 32.0) + .clamped(0.0, 1.0)) + * (1.0 - ((col_alt - z_range.end as f32 - 4.0) / 8.0).clamped(0.0, 1.0)), + )..z_range.end; + if z_range.end - z_range.start > 0 { + Some((level, z_range, horizontal, vertical, dist, tunnel)) + } else { + None + } + }) + }) + .into_iter() + .flatten() +} + pub fn tunnel_bounds_at<'a>( wpos2d: Vec2, info: &'a CanvasInfo, land: &'a Land, -) -> impl Iterator, f64, f64, f64, Tunnel)> + 'a { - let wposf = wpos2d.map(|e| e as f64 + 0.5); - info.col_or_gen(wpos2d).into_iter().flat_map(move |col| { - let col_alt = col.alt; - let col_water_dist = col.water_dist; - (1..LAYERS + 1).flat_map(move |level| { - tunnels_at(wpos2d, level, land) - .chain(tunnels_down_from(wpos2d, level - 1, land)) - .filter_map(move |tunnel| { - let (z_range, horizontal, vertical, dist) = tunnel.z_range_at(wposf, *info)?; - // Avoid cave entrances intersecting water - let z_range = Lerp::lerp( - z_range.end, - z_range.start, - 1.0 - (1.0 - - ((col_water_dist.unwrap_or(1000.0) - 4.0).max(0.0) / 32.0) - .clamped(0.0, 1.0)) - * (1.0 - - ((col_alt - z_range.end as f32 - 4.0) / 8.0).clamped(0.0, 1.0)), - )..z_range.end; - if z_range.end - z_range.start > 0 { - Some((level, z_range, horizontal, vertical, dist, tunnel)) - } else { - None - } - }) - }) - }) +) -> impl Iterator, f32, f32, f32, Tunnel)> + 'a { + tunnel_bounds_at_from(wpos2d, info, land, all_tunnels_at(wpos2d, info, land)) } pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { let info = canvas.info(); - let mut structure_cache = HashMap::new(); - canvas.foreach_col(|canvas, wpos2d, col| { - let land = info.land(); + let land = info.land(); - let tunnel_bounds = tunnel_bounds_at(wpos2d, &info, &land).collect::>(); + let diagonal = (TerrainChunkSize::RECT_SIZE.map(|e| e * e).sum() as f32).sqrt() as f64; + let tunnels = all_tunnels_at( + info.wpos() + TerrainChunkSize::RECT_SIZE.map(|e| e as i32) / 2, + &info, + &land, + ) + .filter(|(_, tunnel)| { + SQUARE_4 + .into_iter() + .map(|rpos| info.wpos() + rpos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32)) + .any(|wpos| { + tunnel + .possibly_near(wpos.map(|e| e as f64), diagonal + 1.0) + .is_some() + }) + }) + .collect::>(); + if !tunnels.is_empty() { + let mut structure_cache = HashMap::new(); + canvas.foreach_col(|canvas, wpos2d, col| { + let tunnel_bounds = + tunnel_bounds_at_from(wpos2d, &info, &land, tunnels.iter().copied()) + .collect::>(); - // First, clear out tunnels - for (_, z_range, _, _, _, _) in &tunnel_bounds { - for z in z_range.start..z_range.end.min(col.alt as i32 + 1) { - canvas.set(wpos2d.with_z(z), Block::air(SpriteKind::Empty)); + // First, clear out tunnels + for (_, z_range, _, _, _, _) in &tunnel_bounds { + for z in z_range.start..z_range.end.min(col.alt as i32 + 1) { + canvas.set(wpos2d.with_z(z), Block::empty()); + } } - } - for (level, z_range, horizontal, vertical, dist, tunnel) in tunnel_bounds { - write_column( - canvas, - col, - level, - wpos2d, - z_range.clone(), - tunnel, - (horizontal, vertical, dist), - &mut structure_cache, - rng, - ); - } - }); + for (level, z_range, horizontal, vertical, dist, tunnel) in tunnel_bounds { + write_column( + canvas, + col, + level, + wpos2d, + z_range.clone(), + tunnel, + (horizontal, vertical, dist), + &mut structure_cache, + rng, + ); + } + }); + } } #[derive(Default)] @@ -479,7 +530,7 @@ fn write_column( wpos2d: Vec2, z_range: Range, tunnel: Tunnel, - dimensions: (f64, f64, f64), + dimensions: (f32, f32, f32), structure_cache: &mut HashMap<(Vec3, Vec2), Option>, rng: &mut R, ) { @@ -490,23 +541,21 @@ fn write_column( let void_below = !canvas.get(wpos2d.with_z(z_range.start - 1)).is_filled(); // Exposed to the sky let sky_above = z_range.end as f32 > col.alt; - let cavern_height = (z_range.end - z_range.start) as f64; + let cavern_height = (z_range.end - z_range.start) as f32; let (cave_width, max_height, dist_cave_center) = dimensions; let biome = tunnel.biome_at(wpos2d.with_z(z_range.start), &info); let stalactite = { - info - .index() - .noise - .cave_nz - .get(wpos2d.map(|e| e as f64 / 16.0).into_array()) - .sub(0.5 + (biome.leafy - 1.0).max(0.0) as f64) + FastNoise2d::new(35) + .get(wpos2d.map(|e| e as f64 / 8.0)) + .mul(1.0) + .sub(0.5 + (biome.leafy - 1.0).max(0.0)) .max(0.0) .mul(2.0) - .add((biome.leafy - 1.0).max(0.0) as f64) + .add((biome.leafy - 1.0).max(0.0)) // No stalactites near entrances - .mul(((col.alt as f64 - z_range.end as f64) / 8.0).clamped(0.0, 1.0)) - .mul(8.0 + cavern_height * (0.4 + (biome.sandy as f64 - 0.5).max(0.0))) + .mul(((col.alt - z_range.end as f32) / 32.0).clamped(0.0, 1.0)) + .mul(4.0 + cavern_height * (0.4 + (biome.sandy - 0.5).max(0.0))) }; let ceiling_cover = if (biome.leafy - 0.3) @@ -516,8 +565,8 @@ fn write_column( .max(biome.fire - 0.5) > 0.0 { - 1.0.mul(((col.alt as f64 - z_range.end as f64) / 8.0).clamped(0.0, 1.0)) - .mul(cavern_height * (dist_cave_center / (cave_width)).powf(3.33)) + 1.0.mul(((col.alt - z_range.end as f32) / 32.0).clamped(0.0, 1.0)) + .mul(cavern_height * (dist_cave_center / cave_width).powf(3.33)) .max(1.0) .sub( if col.marble_mid @@ -528,7 +577,7 @@ fn write_column( .max(biome.leafy - 0.4) .max(biome.mushroom - 0.4) { - cavern_height * col.marble_mid as f64 + cavern_height * col.marble_mid } else { 0.0 }, @@ -539,29 +588,26 @@ fn write_column( }; let basalt = if biome.fire > 0.0 { - info.index() - .noise - .cave_nz - .get(wpos2d.map(|e| e as f64 / 48.0).into_array()) + FastNoise2d::new(36) + .get(wpos2d.map(|e| e as f64 / 32.0)) + .mul(1.25) .sub(0.5) .max(0.0) .mul(6.0 + cavern_height * 0.5) - .mul(biome.fire as f64) + .mul(biome.fire) } else { 0.0 }; let lava = if biome.fire > 0.0 { - info.index() - .noise - .cave_nz - .get(wpos2d.map(|e| e as f64 / 64.0).into_array()) - .sub(0.5) + FastNoise2d::new(37) + .get(wpos2d.map(|e| e as f64 / 32.0)) + .mul(0.5) .abs() .sub(0.2) .min(0.0) // .mul((biome.temp as f64 - 1.5).mul(30.0).clamped(0.0, 1.0)) - .mul((biome.fire as f64 - 0.5).mul(30.0).clamped(0.0, 1.0)) + .mul((biome.fire - 0.5).mul(30.0).clamped(0.0, 1.0)) .mul(64.0) .max(-32.0) } else { @@ -570,11 +616,9 @@ fn write_column( let height_factor = (max_height / 32.0).clamped(0.0, 1.0).powf(2.0); let width_factor = (cave_width / 32.0).clamped(0.0, 1.0).powf(2.0); - let ridge = info - .index() - .noise - .cave_nz - .get(wpos2d.map(|e| e as f64 / 512.0).into_array()) + let ridge = FastNoise2d::new(38) + .get(wpos2d.map(|e| e as f64 / 512.0)) + .mul(1.0) .sub(0.25) .max(0.0) .mul(1.3) @@ -582,28 +626,22 @@ fn write_column( .mul(width_factor) .mul( (0.75 * dist_cave_center) - + max_height - * (close( - dist_cave_center as f32, - cave_width as f32, - cave_width as f32 * 0.7, - )) as f64, - ); + + max_height * (close(dist_cave_center, cave_width, cave_width * 0.7)), + ) + .mul(((col.alt - z_range.end as f32) / 64.0).clamped(0.0, 1.0)); - let bump = info - .index() - .noise - .cave_nz - .get(wpos2d.map(|e| e as f64 / 8.0).into_array()) + let bump = FastNoise2d::new(39) + .get(wpos2d.map(|e| e as f64 / 8.0)) + .mul(1.0) .add(1.0) .mul(0.5) - .mul(((col.alt as f64 - z_range.end as f64) / 16.0).clamped(0.0, 1.0)) + .mul(((col.alt - z_range.end as f32) / 16.0).clamped(0.0, 1.0)) .mul({ let (val, total) = [ - (biome.sandy as f64 - 0.3, 0.9), - (biome.dusty as f64 - 0.2, 0.5), - (biome.leafy as f64 - 0.5, 0.6), - (biome.barren as f64 - 0.1, 0.6), + (biome.sandy - 0.3, 0.9), + (biome.dusty - 0.2, 0.5), + (biome.leafy - 0.5, 0.6), + (biome.barren - 0.1, 0.6), ] .into_iter() .fold((0.0, 0.0), |a, x| (a.0 + x.0.max(0.0) * x.1, a.1 + x.1)); @@ -642,7 +680,7 @@ fn write_column( if biome.mushroom > 0.7 && rng.gen_bool( - 0.5 * close(vertical as f32, 64.0, 48.0) as f64 + 0.5 * close(vertical, MAX_RADIUS, 48.0) as f64 * close(biome.mushroom, 1.0, 0.7) as f64, ) { @@ -660,7 +698,7 @@ fn write_column( ), })) } else if biome.crystal > 0.5 - && rng.gen_bool(0.6 * close(biome.crystal, 1.0, 0.7) as f64) + && rng.gen_bool(0.4 * close(biome.crystal, 1.0, 0.7) as f64) { let colors = [ Rgb::new(209, 106, 255), @@ -677,7 +715,7 @@ fn write_column( let mut crystals: Vec = Vec::new(); - let max_length = (48.0 * close(vertical as f32, 64.0, 42.0)).max(12.0); + let max_length = (48.0 * close(vertical, MAX_RADIUS, 42.0)).max(12.0); let main_length = rng.gen_range(8.0..max_length); let main_radius = Lerp::lerp_unclamped( 2.0, @@ -715,7 +753,7 @@ fn write_column( }); let mut color: Rgb = *(colors.choose(&mut rng).unwrap()); - if tunnel.biome_at(pos, &info).icy > 0.125 { + if tunnel.biome_at(pos, &info).icy > 0.5 { color.r = color.r.saturating_sub(150u8); color.g = color.g.saturating_sub(40u8); color.b = color.b.saturating_add(0u8); @@ -727,19 +765,21 @@ fn write_column( })) } else if biome.leafy > 0.8 && rng.gen_bool( - 0.2 * close(vertical as f32, 64.0, 52.0) as f64 - * close(biome.leafy, 1.0, 0.2) as f64, + 0.2 * (close(vertical, MAX_RADIUS, MAX_RADIUS - 16.0) + * close(horizontal, MAX_RADIUS, MAX_RADIUS - 12.0) + * close(biome.leafy, 1.0, 0.2)) + as f64, ) { Some(CaveStructure::Flower(Flower { pos, - stalk: 8.0 + stalk: 4.0 + rng.gen::().powf(2.0) * (z_range.end - z_range.start - 8) as f32 - * 0.8, + * 0.75, petals: rng.gen_range(1..5) * 2 + 1, - petal_height: rng.gen_range(4.0..8.0), - petal_radius: rng.gen_range(10.0..18.0), + petal_height: rng.gen_range(4.0..16.0), + petal_radius: rng.gen_range(8.0..16.0), rotation: (Mat3::rotation_x( -(rng.gen_bool(1.0) as u32 as f32) * std::f32::consts::PI / rng.gen_range(3.0..16.0), @@ -748,15 +788,15 @@ fn write_column( )) .transposed(), })) - } else if biome.leafy > 0.5 - && rng.gen_bool(0.6 * close(biome.leafy, 1.0, 0.5) as f64) + } else if biome.leafy > 0.8 + && rng.gen_bool(0.4 * close(biome.leafy, 1.0, 0.4) as f64) { Some(CaveStructure::GiantRoot { pos, radius: rng.gen_range( - 3.0..(6.0 - + close(vertical as f32, 64.0, 32.0) * 2.0 - + close(horizontal as f32, 64.0, 32.0) * 2.0), + 2.0..(6.0 + + close(vertical, MAX_RADIUS, MAX_RADIUS / 2.0) * 2.0 + + close(horizontal, MAX_RADIUS, MAX_RADIUS / 2.0) * 2.0), ), height: (z_range.end - z_range.start) as f32, }) @@ -1018,7 +1058,8 @@ fn write_column( let mold_pos = mold_posf.map(|e| e.floor() as i32); let mut rng = RandomPerm::new(((mold_pos.x << 16) | mold_pos.y) as u32); - if biome.mushroom > 0.7 + if !void_above + && biome.mushroom > 0.7 && ceiling_cover > 0.0 && rng.gen_bool(0.025 * close(biome.mushroom, 1.0, 0.3) as f64) { @@ -1092,9 +1133,7 @@ fn write_column( biome.icy, ); Block::new( - if rand.chance(wpos, biome.mushroom * 0.01) { - BlockKind::GlowingWeakRock - } else if rand.chance(wpos, biome.icy) { + if rand.chance(wpos, (biome.mushroom * 0.01).max(biome.icy)) { BlockKind::GlowingWeakRock } else if rand.chance(wpos, biome.sandy) { BlockKind::Sand @@ -1382,10 +1421,10 @@ fn write_column( .flatten() { Block::air(sprite) - } else if let Some(vine) = + } else if let Some(mold) = ceiling_mold(wposf).or_else(|| ceiling_mold(wposf.xy().yx().with_z(wposf.z))) { - vine + mold } else if let Some(structure_block) = get_structure(wpos, rng) { structure_block } else { From 3dbbf80bb2089c2896b6eb238337dc52688158c8 Mon Sep 17 00:00:00 2001 From: Syniis Date: Mon, 19 Feb 2024 19:14:46 +0100 Subject: [PATCH 13/24] Various tweaks to sprites and colors. Made giant trees influence roots in caves --- assets/voxygen/voxel/sprite_manifest.ron | 45 +++++- assets/world/features.ron | 2 +- voxygen/src/scene/terrain/watcher.rs | 1 - world/src/layer/cave.rs | 176 ++++++++++++----------- 4 files changed, 135 insertions(+), 89 deletions(-) diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index 69de6ff461..1c8e64bb12 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -3939,9 +3939,44 @@ CrystalHigh: Some(( model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.green-2", offset: (-11.5, -12.5, -9.0), lod_axes: (1.0, 1.0, 1.0), - ) -], -wind_sway: 0.0, + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.blue-0", + offset: (-8.5, -9.0, -7.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.blue-1", + offset: (-8.0, -8.0, -10.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.blue-2", + offset: (-11.5, -12.5, -9.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.purple-0", + offset: (-8.5, -9.0, -7.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.purple-1", + offset: (-8.0, -8.0, -10.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.purple-2", + offset: (-11.5, -12.5, -9.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.mineral.deposit.crystal.ceiling.purple-3", + offset: (-11.0, -12.5, -49.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, )), CrystalLow: Some(( variations: [ @@ -3990,8 +4025,8 @@ CrystalLow: Some(( offset: (-11.5, -12.5, 0.0), lod_axes: (1.0, 1.0, 1.0), ) -], -wind_sway: 0.0, + ], + wind_sway: 0.0, )), Cotton: Some(( variations: [ diff --git a/assets/world/features.ron b/assets/world/features.ron index dae9a4ee75..b60a5f2014 100644 --- a/assets/world/features.ron +++ b/assets/world/features.ron @@ -11,7 +11,7 @@ paths: false, spots: false, site2_towns: false, - site2_giant_trees: false, + site2_giant_trees: true, wildlife_density: 0.0, peak_naming: false, biome_naming: false, diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 9c0ba54f01..8a4080274f 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -163,7 +163,6 @@ impl BlocksOfInterest { SpriteKind::StreetLampTall => fire_bowls.push(pos + Vec3::unit_z() * 4), SpriteKind::WallSconce => fire_bowls.push(pos + Vec3::unit_z()), SpriteKind::Beehive => beehives.push(pos), - SpriteKind::CrystalHigh => fireflies.push(pos), SpriteKind::Reed => { reeds.push(pos); fireflies.push(pos); diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 0b29727cdc..c4475d377c 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1,6 +1,7 @@ use super::scatter::close; use crate::{ + site::SiteKind, util::{ sampler::Sampler, FastNoise2d, RandomField, RandomPerm, StructureGen2d, LOCALITY, SQUARE_4, }, @@ -186,7 +187,7 @@ impl Tunnel { // Below the ground let below = ((col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * 2.0)).clamped(0.0, 1.0); let depth = (col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32); - let underground = ((col.alt - wpos.z as f32) / 100.0 - 1.0).clamped(0.0, 1.0); + let underground = ((col.alt - wpos.z as f32) / 80.0 - 1.0).clamped(0.0, 1.0); // TODO think about making rate of change of humidity and temp noise higher to // effectively increase biome size @@ -213,7 +214,7 @@ impl Tunnel { ); let mineral = FastNoise2d::new(43) - .get(wpos.xy().map(|e| e as f64 / 320.0)) + .get(wpos.xy().map(|e| e as f64 / 256.0)) .mul(1.15) .mul(0.5) .add( @@ -248,7 +249,7 @@ impl Tunnel { // Overgrown with plants that need a moderate climate to survive let leafy = underground * close(humidity, 0.8, 0.8) - * close(temp, 1.0, 0.8) + * close(temp, 0.85, 0.9) * close(depth, 0.0, 0.6); // Cool temperature, dry and devoid of value let dusty = close(humidity, 0.0, 0.5) * close(temp, -0.1, 0.6); @@ -438,6 +439,20 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { }) .collect::>(); if !tunnels.is_empty() { + let giant_tree_dist = info + .chunk + .sites + .iter() + .filter_map(|site| { + if let SiteKind::GiantTree(t) = &info.index.sites.get(*site).kind { + Some(t.origin.distance_squared(info.wpos) as f32 / t.radius().powi(2)) + } else { + None + } + }) + .max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)) + .unwrap_or(0.0) + .clamp(0.0, 1.0); let mut structure_cache = HashMap::new(); canvas.foreach_col(|canvas, wpos2d, col| { let tunnel_bounds = @@ -460,6 +475,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { z_range.clone(), tunnel, (horizontal, vertical, dist), + giant_tree_dist, &mut structure_cache, rng, ); @@ -468,6 +484,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { } } +#[allow(dead_code)] #[derive(Default)] struct Biome { humidity: f32, @@ -531,6 +548,7 @@ fn write_column( z_range: Range, tunnel: Tunnel, dimensions: (f32, f32, f32), + giant_tree_factor: f32, structure_cache: &mut HashMap<(Vec3, Vec2), Option>, rng: &mut R, ) { @@ -548,19 +566,20 @@ fn write_column( let stalactite = { FastNoise2d::new(35) .get(wpos2d.map(|e| e as f64 / 8.0)) - .mul(1.0) - .sub(0.5 + (biome.leafy - 1.0).max(0.0)) + .sub(0.5) .max(0.0) .mul(2.0) - .add((biome.leafy - 1.0).max(0.0)) + .powi(if biome.icy > 0.5 {3} else {1}) // No stalactites near entrances .mul(((col.alt - z_range.end as f32) / 32.0).clamped(0.0, 1.0)) - .mul(4.0 + cavern_height * (0.4 + (biome.sandy - 0.5).max(0.0))) + // Prevent stalactites from blocking cave + .mul(((cave_width + max_height) / 40.0).clamped(0.0, 1.0)) + .mul(8.0 + cavern_height * (0.4 + (biome.sandy - 0.5).max((biome.icy - 0.7) * 2.0).max(0.0))) }; let ceiling_cover = if (biome.leafy - 0.3) .max(biome.mushroom - 0.5) - .max(biome.icy - 0.6) + .max(biome.icy - 0.7) .max(biome.sandy - 0.5) .max(biome.fire - 0.5) > 0.0 @@ -618,7 +637,6 @@ fn write_column( let width_factor = (cave_width / 32.0).clamped(0.0, 1.0).powf(2.0); let ridge = FastNoise2d::new(38) .get(wpos2d.map(|e| e as f64 / 512.0)) - .mul(1.0) .sub(0.25) .max(0.0) .mul(1.3) @@ -631,10 +649,10 @@ fn write_column( .mul(((col.alt - z_range.end as f32) / 64.0).clamped(0.0, 1.0)); let bump = FastNoise2d::new(39) - .get(wpos2d.map(|e| e as f64 / 8.0)) - .mul(1.0) + .get(wpos2d.map(|e| e as f64 / 4.0)) + .mul(1.15) .add(1.0) - .mul(0.5) + .mul(0.25) .mul(((col.alt - z_range.end as f32) / 16.0).clamped(0.0, 1.0)) .mul({ let (val, total) = [ @@ -657,7 +675,7 @@ fn write_column( let dirt = 1 + (!is_ice) as i32 + is_snow as i32; let bedrock = z_range.start + lava as i32; let ridge_bedrock = bedrock + (ridge * 0.7) as i32; - let base = ridge_bedrock + (stalactite * 0.4) as i32; + let base = ridge_bedrock + (stalactite * (0.4 - biome.icy).max(0.0)) as i32; let floor = base + dirt + (ridge * 0.3) as i32 + bump as i32; let ceiling = z_range.end - stalactite.max(ceiling_cover) as i32; @@ -700,12 +718,6 @@ fn write_column( } else if biome.crystal > 0.5 && rng.gen_bool(0.4 * close(biome.crystal, 1.0, 0.7) as f64) { - let colors = [ - Rgb::new(209, 106, 255), - Rgb::new(187, 86, 240), - Rgb::new(251, 238, 255), - Rgb::new(243, 204, 255), - ]; let on_ground = rng.gen_bool(0.6); let pos = wpos2d.with_z(if on_ground { z_range.start @@ -714,54 +726,49 @@ fn write_column( }); let mut crystals: Vec = Vec::new(); - let max_length = (48.0 * close(vertical, MAX_RADIUS, 42.0)).max(12.0); - let main_length = rng.gen_range(8.0..max_length); - let main_radius = Lerp::lerp_unclamped( + let length = rng.gen_range(8.0..max_length); + let radius = Lerp::lerp_unclamped( 2.0, 4.5, - main_length / max_length + rng.gen_range(-0.1..0.1), + length / max_length + rng.gen_range(-0.1..0.1), ); - - let main_dir = Vec3::new( + let dir = Vec3::new( rng.gen_range(-3.0..3.0), rng.gen_range(-3.0..3.0), rng.gen_range(0.5..10.0) * if on_ground { 1.0 } else { -1.0 }, ) .normalized(); - let main_crystal = Crystal { - dir: main_dir, - length: main_length, - radius: main_radius, - }; - crystals.push(main_crystal); + crystals.push(Crystal { + dir, + length, + radius, + }); (0..4).for_each(|_| { - let side_radius = (main_radius * rng.gen_range(0.5..0.8)).max(1.0); - let side_length = main_length * rng.gen_range(0.3..0.8); - let side_crystal = Crystal { + crystals.push(Crystal { dir: Vec3::new( rng.gen_range(-1.0..1.0), rng.gen_range(-1.0..1.0), - (main_dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), + (dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), ), - length: side_length, - radius: side_radius, - }; - crystals.push(side_crystal); + length: length * rng.gen_range(0.3..0.8), + radius: (radius * rng.gen_range(0.5..0.8)).max(1.0), + }); }); - let mut color: Rgb = *(colors.choose(&mut rng).unwrap()); - if tunnel.biome_at(pos, &info).icy > 0.5 { - color.r = color.r.saturating_sub(150u8); - color.g = color.g.saturating_sub(40u8); - color.b = color.b.saturating_add(0u8); - } + let purple = rng.gen_range(25..75); + let blue = (rng.gen_range(45.0..75.0) * biome.icy) as u8; + Some(CaveStructure::Crystal(CrystalCluster { pos, crystals, - color, + color: Rgb::new( + 255 - blue * 2, + 255 - blue - purple, + 200 + rng.gen_range(25..55), + ), })) } else if biome.leafy > 0.8 && rng.gen_bool( @@ -788,8 +795,12 @@ fn write_column( )) .transposed(), })) - } else if biome.leafy > 0.8 - && rng.gen_bool(0.4 * close(biome.leafy, 1.0, 0.4) as f64) + } else if (biome.leafy > 0.8 || giant_tree_factor > 0.0) + && rng.gen_bool( + (0.4 * close(biome.leafy, 1.0, 0.4).max(1.0 + giant_tree_factor) + as f64) + .clamped(0.0, 1.0), + ) { Some(CaveStructure::GiantRoot { pos, @@ -928,7 +939,11 @@ fn write_column( }; if dist_sq < crystal_radius.powi(2) { - return Some(Block::new(BlockKind::GlowingRock, cluster.color)); + if dist_sq / crystal_radius.powi(2) > 0.75 { + return Some(Block::new(BlockKind::GlowingRock, cluster.color)); + } else { + return Some(Block::new(BlockKind::Rock, cluster.color)); + } } } } @@ -1058,15 +1073,11 @@ fn write_column( let mold_pos = mold_posf.map(|e| e.floor() as i32); let mut rng = RandomPerm::new(((mold_pos.x << 16) | mold_pos.y) as u32); - if !void_above - && biome.mushroom > 0.7 - && ceiling_cover > 0.0 - && rng.gen_bool(0.025 * close(biome.mushroom, 1.0, 0.3) as f64) - { + if !void_above && biome.mushroom > 0.9 && ceiling_cover > 0.0 && rng.gen_bool(0.05) { let mold_length = ((mold_posf.y.fract() - 0.5).abs() * 2.0 * dims.y) .mul(0.05) .powf(2.0) - .min(8.0); + .min(16.0); let mold_z = z_range.end as f32 - mold_length; if Vec2::new(mold_posf.x.fract() * 2.0 - 1.0, (mold_z - wpos.z) / 4.0) @@ -1108,7 +1119,8 @@ fn write_column( Lerp::lerp( Lerp::lerp( Lerp::lerp( - Rgb::new(20, 21, 49), + // Rgb::new(20, 21, 49), + Rgb::new(80, 100, 150), Rgb::new(23, 44, 88), biome.mushroom, ), @@ -1200,13 +1212,13 @@ fn write_column( if is_ice { Block::new(BlockKind::Ice, Rgb::new(120, 160, 255)) } else if is_snow { - Block::new(BlockKind::Snow, Rgb::new(170, 195, 255)) + Block::new(BlockKind::ArtSnow, Rgb::new(170, 195, 255)) } else { Block::new( if biome.mushroom.max(biome.leafy) > 0.5 { BlockKind::Grass } else if biome.icy > 0.5 { - BlockKind::Snow + BlockKind::ArtSnow } else if biome.fire.max(biome.snowy) > 0.5 { BlockKind::Rock } else if biome.crystal > 0.5 { @@ -1223,13 +1235,10 @@ fn write_column( } } else if let Some(sprite) = (z == floor && !void_below && !sky_above) .then(|| { - if rand.chance( - wpos2d.with_z(1), - biome.mushroom - * 0.3 - * col.marble_mid - * (col.marble_mid > 0.55) as u32 as f32, - ) { + if col.marble_mid > 0.55 + && biome.mushroom > 0.5 + && rand.chance(wpos2d.with_z(1), biome.mushroom * 0.25 * col.marble_mid) + { [ (SpriteKind::GlowMushroom, 0.5), (SpriteKind::Mushroom, 0.25), @@ -1242,10 +1251,10 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance( - wpos2d.with_z(15), - biome.leafy * 0.45 * col.marble_mid * (col.marble_mid > 0.6) as u32 as f32, - ) { + } else if col.marble_mid > 0.6 + && biome.leafy > 0.4 + && rand.chance(wpos2d.with_z(15), biome.leafy * 0.3 * col.marble_mid) + { let mixed = col.marble.add(col.marble_small.sub(0.5).mul(0.25)); if (0.25..0.45).contains(&mixed) || (0.55..0.75).contains(&mixed) { return [ @@ -1265,9 +1274,15 @@ fn write_column( .ok() .map(|s| s.0); } else if (0.0..0.25).contains(&mixed) { - return Some(SpriteKind::LanternPlant); + return [(Some(SpriteKind::LanternPlant), 0.5), (None, 0.5)] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .and_then(|s| s.0); } else if (0.75..1.0).contains(&mixed) { - return Some(SpriteKind::LushFlower); + return [(Some(SpriteKind::LushFlower), 0.6), (None, 0.4)] + .choose_weighted(rng, |(_, w)| *w) + .ok() + .and_then(|s| s.0); } else { return [ (SpriteKind::LongGrass, 1.0), @@ -1315,10 +1330,7 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance( - wpos2d.with_z(3), - close(biome.humidity, 0.0, 0.5) * biome.mineral * 0.0025, - ) { + } else if rand.chance(wpos2d.with_z(3), biome.crystal * 0.005) { Some(SpriteKind::CrystalLow) } else if rand.chance(wpos2d.with_z(13), biome.fire * 0.001) { [ @@ -1329,6 +1341,10 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) + } else if rand.chance(wpos2d.with_z(23), biome.icy * 0.005) { + Some(SpriteKind::IceCrystal) + } else if rand.chance(wpos2d.with_z(31), biome.icy * biome.mineral * 0.005) { + Some(SpriteKind::GlowIceCrystal) } else if rand.chance(wpos2d.with_z(5), 0.0025) { [ (Some(SpriteKind::VeloriteFrag), 0.3), @@ -1402,18 +1418,14 @@ fn write_column( (SpriteKind::CeilingLanternPlant, 1.5), (SpriteKind::CeilingLanternFlower, 1.25), (SpriteKind::CeilingJungleLeafyPlant, 1.0), - (SpriteKind::CrystalHigh, 0.1), ] .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) } else if rand.chance(wpos2d.with_z(5), biome.barren * 0.015) { - [(SpriteKind::Root, 1.5)] - .choose_weighted(rng, |(_, w)| *w) - .ok() - .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(5), biome.mineral * 0.005) { - Some(*[SpriteKind::CrystalHigh].choose(rng).unwrap()) + Some(SpriteKind::Root) + } else if rand.chance(wpos2d.with_z(5), biome.crystal * 0.005) { + Some(SpriteKind::CrystalHigh) } else { None } From c7dcd97434f49e8aaf90970e9ecdb6e0f0188c6d Mon Sep 17 00:00:00 2001 From: Syniis Date: Mon, 19 Feb 2024 21:46:39 +0100 Subject: [PATCH 14/24] Use lerp unclamped where possible --- world/src/layer/cave.rs | 103 ++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index c4475d377c..b35e9bd655 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -127,7 +127,7 @@ impl Tunnel { let _start = self.a.wpos.map(|e| e as f64 + 0.5); let _end = self.b.wpos.map(|e| e as f64 + 0.5); if let Some((t, closest, dist)) = self.possibly_near(wposf, 1.0) { - let horizontal = Lerp::lerp( + let horizontal = Lerp::lerp_unclamped( Self::RADIUS_RANGE.start, Self::RADIUS_RANGE.end, (info.index().noise.cave_fbm_nz.get( @@ -137,7 +137,7 @@ impl Tunnel { .clamped(0.0, 1.0) .powf(3.0), ); - let vertical = Lerp::lerp( + let vertical = Lerp::lerp_unclamped( Self::RADIUS_RANGE.start, Self::RADIUS_RANGE.end, (info.index().noise.cave_fbm_nz.get( @@ -158,7 +158,7 @@ impl Tunnel { * 96.0 * ((1.0 - (t - 0.5).abs() * 2.0) * 8.0).min(1.0); let alt_here = info.land().get_alt_approx(closest.map(|e| e as i32)); - let base = (Lerp::lerp( + let base = (Lerp::lerp_unclamped( alt_here as f64 - self.a.depth as f64, alt_here as f64 - self.b.depth as f64, t, @@ -191,7 +191,7 @@ impl Tunnel { // TODO think about making rate of change of humidity and temp noise higher to // effectively increase biome size - let humidity = Lerp::lerp( + let humidity = Lerp::lerp_unclamped( col.humidity, FastNoise2d::new(41) .get(wpos.xy().map(|e| e as f64 / 768.0)) @@ -199,7 +199,7 @@ impl Tunnel { below, ); - let temp = Lerp::lerp( + let temp = Lerp::lerp_unclamped( col.temp, FastNoise2d::new(42) .get(wpos.xy().map(|e| e as f64 / 1536.0)) @@ -390,7 +390,7 @@ fn tunnel_bounds_at_from<'a>( tunnels.filter_map(move |(level, tunnel)| { let (z_range, horizontal, vertical, dist) = tunnel.z_range_at(wposf, *info)?; // Avoid cave entrances intersecting water - let z_range = Lerp::lerp( + let z_range = Lerp::lerp_unclamped( z_range.end, z_range.start, 1.0 - (1.0 @@ -728,11 +728,8 @@ fn write_column( let mut crystals: Vec = Vec::new(); let max_length = (48.0 * close(vertical, MAX_RADIUS, 42.0)).max(12.0); let length = rng.gen_range(8.0..max_length); - let radius = Lerp::lerp_unclamped( - 2.0, - 4.5, - length / max_length + rng.gen_range(-0.1..0.1), - ); + let radius = + Lerp::lerp(2.0, 4.5, length / max_length + rng.gen_range(-0.1..0.1)); let dir = Vec3::new( rng.gen_range(-3.0..3.0), rng.gen_range(-3.0..3.0), @@ -851,8 +848,8 @@ fn write_column( / Vec2::broadcast(head_radius).with_z(head_height)) .magnitude(); - let stalk = - mushroom.stalk + Lerp::lerp(head_height * 0.5, 0.0, dist / head_radius); + let stalk = mushroom.stalk + + Lerp::lerp_unclamped(head_height * 0.5, 0.0, dist / head_radius); // Head if rpos.z > stalk @@ -928,14 +925,18 @@ fn write_column( let crystal_radius = if taper > peak_cutoff { let taper = (taper - peak_cutoff) * 5.0; - Lerp::lerp( + Lerp::lerp_unclamped( crystal.radius * taper_factor, crystal.radius * peak_taper, taper, ) } else { let taper = taper * 1.25; - Lerp::lerp(crystal.radius, crystal.radius * taper_factor, taper) + Lerp::lerp_unclamped( + crystal.radius, + crystal.radius * taper_factor, + taper, + ) }; if dist_sq < crystal_radius.powi(2) { @@ -960,7 +961,9 @@ fn write_column( let dist_sq = rpos.xy().magnitude_squared(); if rpos.z < flower.stalk && dist_sq - < (stalk_radius * Lerp::lerp(1.0, 0.75, rpos.z / flower.stalk)).powi(2) + < (stalk_radius + * Lerp::lerp_unclamped(1.0, 0.75, rpos.z / flower.stalk)) + .powi(2) { return Some(Block::new(BlockKind::Wood, Rgb::new(0, 108, 0))); } @@ -1019,8 +1022,9 @@ fn write_column( if rpos.z > 0.0 && rpos.z < pollen_height && dist_sq - < (stalk_radius * Lerp::lerp(0.5, 1.25, rpos.z / pollen_height)) - .powi(2) + < (stalk_radius + * Lerp::lerp_unclamped(0.5, 1.25, rpos.z / pollen_height)) + .powi(2) { return Some(Block::new( BlockKind::GlowingMushroom, @@ -1114,34 +1118,41 @@ fn write_column( } else if z < ridge_bedrock && !void_below { Block::new(BlockKind::Rock, col.stone_col) } else if (z < base && !void_below) || (z >= ceiling && !void_above) { - let stalactite: Rgb = Lerp::lerp( - Lerp::lerp( - Lerp::lerp( - Lerp::lerp( - Lerp::lerp( - // Rgb::new(20, 21, 49), + let stalactite: Rgb = Lerp::lerp_unclamped( + Lerp::lerp_unclamped( + Lerp::lerp_unclamped( + Lerp::lerp_unclamped( + Lerp::lerp_unclamped( Rgb::new(80, 100, 150), Rgb::new(23, 44, 88), biome.mushroom, ), - Lerp::lerp( + Lerp::lerp_unclamped( Rgb::new(100, 40, 40), Rgb::new(100, 75, 100), col.marble_small, ), biome.fire, ), - Lerp::lerp( + Lerp::lerp_unclamped( Rgb::new(238, 198, 139), Rgb::new(111, 99, 64), col.marble_mid, ), biome.sandy, ), - Lerp::lerp(Rgb::new(0, 73, 12), Rgb::new(49, 63, 12), col.marble_small), + Lerp::lerp_unclamped( + Rgb::new(0, 73, 12), + Rgb::new(49, 63, 12), + col.marble_small, + ), biome.leafy, ), - Lerp::lerp(Rgb::new(100, 150, 255), Rgb::new(100, 120, 255), col.marble), + Lerp::lerp_unclamped( + Rgb::new(100, 150, 255), + Rgb::new(100, 120, 255), + col.marble, + ), biome.icy, ); Block::new( @@ -1157,23 +1168,39 @@ fn write_column( } else if z >= base && z < floor && !void_below && !sky_above { let (net_col, total) = [ ( - Lerp::lerp(Rgb::new(68, 62, 58), Rgb::new(97, 95, 85), col.marble_small), + Lerp::lerp_unclamped( + Rgb::new(68, 62, 58), + Rgb::new(97, 95, 85), + col.marble_small, + ), 0.05, ), ( - Lerp::lerp(Rgb::new(66, 37, 30), Rgb::new(88, 62, 45), col.marble_mid), + Lerp::lerp_unclamped( + Rgb::new(66, 37, 30), + Rgb::new(88, 62, 45), + col.marble_mid, + ), biome.dusty, ), ( - Lerp::lerp(Rgb::new(20, 65, 175), Rgb::new(20, 100, 80), col.marble_mid), + Lerp::lerp_unclamped( + Rgb::new(20, 65, 175), + Rgb::new(20, 100, 80), + col.marble_mid, + ), biome.mushroom, ), ( - Lerp::lerp(Rgb::new(120, 50, 20), Rgb::new(50, 5, 40), col.marble_small), + Lerp::lerp_unclamped( + Rgb::new(120, 50, 20), + Rgb::new(50, 5, 40), + col.marble_small, + ), biome.fire, ), ( - Lerp::lerp( + Lerp::lerp_unclamped( Rgb::new(0, 100, 50), Rgb::new(80, 100, 20), col.marble_small, @@ -1182,7 +1209,7 @@ fn write_column( ), (Rgb::new(170, 195, 255), biome.icy), ( - Lerp::lerp( + Lerp::lerp_unclamped( Rgb::new(105, 25, 131), Rgb::new(251, 238, 255), col.marble_mid, @@ -1190,7 +1217,7 @@ fn write_column( biome.crystal, ), ( - Lerp::lerp( + Lerp::lerp_unclamped( Rgb::new(201, 174, 116), Rgb::new(244, 239, 227), col.marble_small, @@ -1199,7 +1226,11 @@ fn write_column( ), ( // Same as barren - Lerp::lerp(Rgb::new(68, 62, 58), Rgb::new(97, 95, 85), col.marble_small), + Lerp::lerp_unclamped( + Rgb::new(68, 62, 58), + Rgb::new(97, 95, 85), + col.marble_small, + ), biome.snowy, ), ] From 71a882a6b78beee63d114e7e29432e2dc4e5c183 Mon Sep 17 00:00:00 2001 From: Syniis Date: Mon, 19 Feb 2024 22:24:19 +0100 Subject: [PATCH 15/24] Small cache and cave noise changes from zesterer --- world/src/block/mod.rs | 2 +- world/src/index.rs | 4 ++-- world/src/layer/cave.rs | 13 ++++++------- world/src/util/small_cache.rs | 25 ++++++++++++------------- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index d7705dd6de..233f83d8a6 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -34,7 +34,7 @@ impl<'a> BlockGen<'a> { pub fn sample_column<'b>( column_gen: &ColumnGen<'a>, - cache: &'b mut SmallCache>>, + cache: &'b mut SmallCache, Option>>, wpos: Vec2, index: IndexRef<'a>, calendar: Option<&'a Calendar>, diff --git a/world/src/index.rs b/world/src/index.rs index 5fdaa6bff9..fc8fcd9497 100644 --- a/world/src/index.rs +++ b/world/src/index.rs @@ -9,7 +9,7 @@ use common::{ trade::{SiteId, SitePrices}, }; use core::ops::Deref; -use noise::{Fbm, Seedable, SuperSimplex}; +use noise::{Fbm, Seedable, SuperSimplex, MultiFractal}; use std::sync::Arc; const WORLD_COLORS_MANIFEST: &str = "world.style.colors"; @@ -144,7 +144,7 @@ impl Noise { Self { cave_nz: SuperSimplex::new().set_seed(seed + 0), scatter_nz: SuperSimplex::new().set_seed(seed + 1), - cave_fbm_nz: Fbm::new().set_seed(seed + 2), + cave_fbm_nz: Fbm::new().set_seed(seed + 2).set_octaves(5), } } } diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index b35e9bd655..e0350aef41 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -3,7 +3,8 @@ use super::scatter::close; use crate::{ site::SiteKind, util::{ - sampler::Sampler, FastNoise2d, RandomField, RandomPerm, StructureGen2d, LOCALITY, SQUARE_4, + sampler::Sampler, FastNoise2d, RandomField, RandomPerm, SmallCache, StructureGen2d, + LOCALITY, SQUARE_4, }, Canvas, CanvasInfo, ColumnSample, Land, }; @@ -20,7 +21,6 @@ use noise::NoiseFn; use rand::prelude::*; use std::{ cmp::Ordering, - collections::HashMap, f64::consts::PI, ops::{Add, Mul, Range, Sub}, }; @@ -453,7 +453,7 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { .max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)) .unwrap_or(0.0) .clamp(0.0, 1.0); - let mut structure_cache = HashMap::new(); + let mut structure_cache = SmallCache::default(); canvas.foreach_col(|canvas, wpos2d, col| { let tunnel_bounds = tunnel_bounds_at_from(wpos2d, &info, &land, tunnels.iter().copied()) @@ -549,7 +549,7 @@ fn write_column( tunnel: Tunnel, dimensions: (f32, f32, f32), giant_tree_factor: f32, - structure_cache: &mut HashMap<(Vec3, Vec2), Option>, + structure_cache: &mut SmallCache, Option>, rng: &mut R, ) { let info = canvas.info(); @@ -681,9 +681,8 @@ fn write_column( let mut get_structure = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { - let structure = if let Some(structure) = structure_cache - .entry((tunnel.a.wpos.with_z(tunnel.a.depth), wpos2d)) - .or_insert_with(|| { + let structure = if let Some(structure) = + structure_cache.get(wpos2d.with_z(tunnel.a.depth), |_| { let mut rng = RandomPerm::new(seed); let (z_range, horizontal, vertical, _) = tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; diff --git a/world/src/util/small_cache.rs b/world/src/util/small_cache.rs index 2246d5b932..4a850b952c 100644 --- a/world/src/util/small_cache.rs +++ b/world/src/util/small_cache.rs @@ -1,23 +1,22 @@ use arr_macro::arr; -use vek::*; -fn calc_idx(v: Vec2) -> usize { - let mut x = v.x as u32; - let mut y = v.y as u32; - x = x.wrapping_mul(0x6eed0e9d); - y = y.wrapping_mul(0x2f72b421); - (x ^ y) as usize +fn calc_idx(v: impl Iterator) -> usize { + let mut r = 0; + for (e, h) in v.zip([0x6eed0e9d, 0x2f72b421, 0x18132f72, 0x891e2fba].into_iter()) { + r ^= (e as u32).wrapping_mul(h); + } + r as usize } // NOTE: Use 128 if TerrainChunkSize::RECT_SIZE.x = 128. const CACHE_LEN: usize = 32; -pub struct SmallCache { - index: [Option>; CACHE_LEN + 9], +pub struct SmallCache { + index: [Option; CACHE_LEN + 9], data: [V; CACHE_LEN + 9], random: u32, } -impl Default for SmallCache { +impl Default for SmallCache { fn default() -> Self { Self { index: [None; CACHE_LEN + 9], @@ -26,9 +25,9 @@ impl Default for SmallCache { } } } -impl SmallCache { - pub fn get) -> V>(&mut self, key: Vec2, f: F) -> &V { - let idx = calc_idx(key) % CACHE_LEN; +impl, V: Default> SmallCache { + pub fn get V>(&mut self, key: K, f: F) -> &V { + let idx = calc_idx(key.into_iter()) % CACHE_LEN; // Search if self.index[idx].as_ref().map(|k| k == &key).unwrap_or(false) { From 17a88acd1c39b54156c870d75d1b8a0ea7a506bb Mon Sep 17 00:00:00 2001 From: Syniis Date: Wed, 21 Feb 2024 22:39:32 +0100 Subject: [PATCH 16/24] Various tweaks. New ArtLeaves BlockKind --- assets/world/features.ron | 20 +- common/net/src/msg/compression.rs | 5 + common/src/terrain/block.rs | 3 + voxygen/src/hud/minimap.rs | 6 +- world/src/layer/cave.rs | 546 ++++++++++++++++++------------ world/src/lib.rs | 4 +- 6 files changed, 346 insertions(+), 238 deletions(-) diff --git a/assets/world/features.ron b/assets/world/features.ron index b60a5f2014..53a2053d77 100644 --- a/assets/world/features.ron +++ b/assets/world/features.ron @@ -3,17 +3,17 @@ ( caverns: false, // TODO: Disabled by default until cave overhaul - caves: false, - rocks: false, - shrubs: false, - trees: false, + caves: true, + rocks: true, + shrubs: true, + trees: true, scatter: true, - paths: false, - spots: false, - site2_towns: false, + paths: true, + spots: true, + site2_towns: true, site2_giant_trees: true, - wildlife_density: 0.0, - peak_naming: false, - biome_naming: false, + wildlife_density: 1.0, + peak_naming: true, + biome_naming: true, train_tracks: false, // TODO: train stations, train entities ) diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs index 8428ca416c..beed5715a0 100644 --- a/common/net/src/msg/compression.rs +++ b/common/net/src/msg/compression.rs @@ -671,6 +671,11 @@ impl VoxelImageDecoding for TriPngEncoding Rgb { + r: 93, + g: 206, + b: 64, + }, GlowingMushroom => Rgb { r: 50, g: 250, diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 35a2d3f8f3..d89cad8c6b 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -55,6 +55,7 @@ make_case_elim!( Leaves = 0x41, GlowingMushroom = 0x42, Ice = 0x43, + ArtLeaves = 0x44, // 0x43 <= x < 0x50 is reserved for future tree parts // Covers all other cases (we sometimes have bizarrely coloured misc blocks, and also we // often want to experiment with new kinds of block without allocating them a @@ -451,6 +452,7 @@ impl Block { match self.kind() { BlockKind::Water => (0, 0.4), BlockKind::Leaves => (9, 255.0), + BlockKind::ArtLeaves => (9, 255.0), BlockKind::Wood => (6, 2.0), BlockKind::Snow => (6, 2.0), BlockKind::ArtSnow => (6, 2.0), @@ -488,6 +490,7 @@ impl Block { // so all is good for empty fluids. match self.kind() { BlockKind::Leaves => Some(0.25), + BlockKind::ArtLeaves => Some(0.25), BlockKind::Grass => Some(0.5), BlockKind::WeakRock => Some(0.75), BlockKind::Snow => Some(0.1), diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index 32b101145d..2b300b01c1 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -137,7 +137,11 @@ impl VoxelMinimap { // since otherwise trees would cause ceiling removal to trigger // when running under a branch. let is_filled = block.map_or(true, |b| { - b.is_filled() && !matches!(b.kind(), BlockKind::Leaves | BlockKind::Wood) + b.is_filled() + && !matches!( + b.kind(), + BlockKind::Leaves | BlockKind::ArtLeaves | BlockKind::Wood + ) }); let rgba = rgba.unwrap_or_else(|| Rgba::new(0, 0, 0, 255)); (rgba, is_filled) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index e0350aef41..858cf55399 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -26,6 +26,10 @@ use std::{ }; use vek::*; +fn close_fast(x: f32, tgt: f32, falloff: f32, falloff_strength: i32) -> f32 { + (1.0 - ((x - tgt) / falloff).powi(falloff_strength * 2)).max(0.0) +} + const CELL_SIZE: i32 = 1536; #[derive(Copy, Clone)] @@ -43,6 +47,7 @@ fn to_wpos(cell: Vec2, level: u32) -> Vec2 { const AVG_LEVEL_DEPTH: i32 = 120; const LAYERS: u32 = 4; +const MIN_RADIUS: f32 = 8.0; const MAX_RADIUS: f32 = 64.0; fn node_at(cell: Vec2, level: u32, land: &Land) -> Option { @@ -89,8 +94,6 @@ pub struct Tunnel { } impl Tunnel { - const RADIUS_RANGE: Range = 8.0..MAX_RADIUS as f64; - fn ctrl_offset(&self) -> Vec2 { let start = self.a.wpos.map(|e| e as f64 + 0.5); let end = self.b.wpos.map(|e| e as f64 + 0.5); @@ -108,7 +111,7 @@ impl Tunnel { Vec2::new(start, end), ) { let dist2 = closest.distance_squared(wposf); - if dist2 < (Self::RADIUS_RANGE.end + threshold).powi(2) { + if dist2 < (MAX_RADIUS as f64 + threshold).powi(2) { Some((t, closest, dist2.sqrt())) } else { None @@ -128,8 +131,8 @@ impl Tunnel { let _end = self.b.wpos.map(|e| e as f64 + 0.5); if let Some((t, closest, dist)) = self.possibly_near(wposf, 1.0) { let horizontal = Lerp::lerp_unclamped( - Self::RADIUS_RANGE.start, - Self::RADIUS_RANGE.end, + MIN_RADIUS as f64, + MAX_RADIUS as f64, (info.index().noise.cave_fbm_nz.get( (closest.with_z(info.land().get_alt_approx(self.a.wpos) as f64) / 256.0) .into_array(), @@ -138,8 +141,8 @@ impl Tunnel { .powf(3.0), ); let vertical = Lerp::lerp_unclamped( - Self::RADIUS_RANGE.start, - Self::RADIUS_RANGE.end, + MIN_RADIUS as f64, + MAX_RADIUS as f64, (info.index().noise.cave_fbm_nz.get( (closest.with_z(info.land().get_alt_approx(self.b.wpos) as f64) / 256.0) .into_array(), @@ -536,7 +539,7 @@ struct Flower { petals: usize, petal_height: f32, petal_radius: f32, - rotation: Mat3, + // rotation: Mat3, } #[inline_tweak::tweak_fn] @@ -569,23 +572,24 @@ fn write_column( .sub(0.5) .max(0.0) .mul(2.0) - .powi(if biome.icy > 0.5 {3} else {1}) + .powi(if biome.icy > 0.7 {2} else {1}) // No stalactites near entrances .mul(((col.alt - z_range.end as f32) / 32.0).clamped(0.0, 1.0)) // Prevent stalactites from blocking cave .mul(((cave_width + max_height) / 40.0).clamped(0.0, 1.0)) - .mul(8.0 + cavern_height * (0.4 + (biome.sandy - 0.5).max((biome.icy - 0.7) * 2.0).max(0.0))) + // Scale with cavern height, sandy and icy biomes have bigger stalactites + .mul(8.0 + cavern_height * (0.4 + (biome.sandy - 0.5).max(biome.icy - 0.6).max(0.0))) }; - let ceiling_cover = if (biome.leafy - 0.3) - .max(biome.mushroom - 0.5) - .max(biome.icy - 0.7) - .max(biome.sandy - 0.5) - .max(biome.fire - 0.5) - > 0.0 + let ceiling_cover = if biome.leafy > 0.3 + || biome.mushroom > 0.5 + || biome.icy > 0.7 + || biome.sandy > 0.5 + || biome.fire > 0.5 { + // 1.0 because at some point we maybe want to use some noise value here instead 1.0.mul(((col.alt - z_range.end as f32) / 32.0).clamped(0.0, 1.0)) - .mul(cavern_height * (dist_cave_center / cave_width).powf(3.33)) + .mul(max_height * (dist_cave_center / cave_width).powf(3.33)) .max(1.0) .sub( if col.marble_mid @@ -596,7 +600,7 @@ fn write_column( .max(biome.leafy - 0.4) .max(biome.mushroom - 0.4) { - cavern_height * col.marble_mid + max_height * col.marble_mid } else { 0.0 }, @@ -612,6 +616,7 @@ fn write_column( .mul(1.25) .sub(0.5) .max(0.0) + .mul(((cave_width + max_height) / 32.0).clamped(0.0, 1.0)) .mul(6.0 + cavern_height * 0.5) .mul(biome.fire) } else { @@ -633,8 +638,8 @@ fn write_column( 0.0 }; - let height_factor = (max_height / 32.0).clamped(0.0, 1.0).powf(2.0); - let width_factor = (cave_width / 32.0).clamped(0.0, 1.0).powf(2.0); + let height_factor = (max_height / MAX_RADIUS * 0.5).clamped(0.0, 1.0).powf(2.0); + let width_factor = (cave_width / MAX_RADIUS * 0.5).clamped(0.0, 1.0).powf(2.0); let ridge = FastNoise2d::new(38) .get(wpos2d.map(|e| e as f64 / 512.0)) .sub(0.25) @@ -652,32 +657,95 @@ fn write_column( .get(wpos2d.map(|e| e as f64 / 4.0)) .mul(1.15) .add(1.0) - .mul(0.25) + .mul(0.5) .mul(((col.alt - z_range.end as f32) / 16.0).clamped(0.0, 1.0)) .mul({ let (val, total) = [ - (biome.sandy - 0.3, 0.9), - (biome.dusty - 0.2, 0.5), - (biome.leafy - 0.5, 0.6), - (biome.barren - 0.1, 0.6), + (biome.sandy, 0.9), + (biome.dusty, 0.5), + (biome.leafy, 0.6), + (biome.barren, 0.6), ] .into_iter() .fold((0.0, 0.0), |a, x| (a.0 + x.0.max(0.0) * x.1, a.1 + x.1)); val / total }) - .mul(cavern_height * 0.4); + .mul(cavern_height * 0.2) + .clamped(0.0, 4.0); let rand = RandomField::new(37 + level); let is_ice = biome.icy + col.marble * 0.2 > 0.5 && col.marble > 0.6; let is_snow = biome.snowy + col.marble_mid * 0.2 > 0.5 && col.marble_mid > 0.6; - let dirt = 1 + (!is_ice) as i32 + is_snow as i32; + let (has_stalagmite, has_stalactite) = if biome.icy > 0.5 { + (col.marble_mid > 0.6, col.marble_mid < 0.5) + } else { + (true, true) + }; + + let stalagmite_only = if has_stalagmite && !has_stalactite { + 0.6f32 + } else { + 0.0f32 + }; + + // Don't cover stalgmites in ice biome with surface block + let dirt = if biome.icy > 0.5 && has_stalagmite && stalactite > 3.0 { + 0 + } else { + 1 + (!is_ice) as i32 + is_snow as i32 + }; let bedrock = z_range.start + lava as i32; let ridge_bedrock = bedrock + (ridge * 0.7) as i32; - let base = ridge_bedrock + (stalactite * (0.4 - biome.icy).max(0.0)) as i32; + let base = ridge_bedrock + (stalactite * (0.4 + stalagmite_only)) as i32; let floor = base + dirt + (ridge * 0.3) as i32 + bump as i32; - let ceiling = z_range.end - stalactite.max(ceiling_cover) as i32; + let ceiling = + z_range.end - (stalactite * has_stalactite as i32 as f32).max(ceiling_cover) as i32; + + let get_ceiling_drip = |wpos: Vec2, freq: f64, length: f32| { + let wposf = wpos.map(|e| e as f32); + let wposf = wposf + wposf.yx() * 1.1; + let dims = Vec2::new(11.0, 32.0); + let posf = wposf + Vec2::unit_y() * (wposf.x / dims.x).floor() * 89.0 / dims; + let pos = posf.map(|e| e.floor() as i32); + if rand.chance(pos.with_z(73), freq as f32) { + let drip_length = ((posf.y.fract() - 0.5).abs() * 2.0 * dims.y) + .mul(length * 0.01) + .powf(2.0) + .min(length); + + if (posf.x.fract() * 2.0 - 1.0).powi(2) < 1.0 { + drip_length + } else { + 0.0 + } + } else { + 0.0 + } + }; + + let ceiling_drip = ceiling + - if !void_above && !sky_above { + let c = if biome.mushroom > 0.9 && ceiling_cover > 0.0 { + Some((0.07, 7.0)) + } else if biome.icy > 0.9 { + Some((0.1 * col.marble_mid as f64, 9.0)) + } else { + None + }; + if let Some((freq, length)) = c { + get_ceiling_drip(wpos2d, freq, length).max(get_ceiling_drip( + wpos2d.yx(), + freq, + length, + )) as i32 + } else { + 0 + } + } else { + 0 + }; let mut get_structure = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { @@ -696,120 +764,125 @@ fn write_column( } if biome.mushroom > 0.7 - && rng.gen_bool( - 0.5 * close(vertical, MAX_RADIUS, 48.0) as f64 - * close(biome.mushroom, 1.0, 0.7) as f64, - ) - { - let purp = rng.gen_range(0..50); - Some(CaveStructure::Mushroom(Mushroom { - pos, - stalk: 8.0 - + rng.gen::().powf(2.0) - * (z_range.end - z_range.start - 8) as f32 - * 0.75, - head_color: Rgb::new( - 40 + purp, - rng.gen_range(60..120), - rng.gen_range(80..200) + purp, - ), - })) - } else if biome.crystal > 0.5 - && rng.gen_bool(0.4 * close(biome.crystal, 1.0, 0.7) as f64) - { - let on_ground = rng.gen_bool(0.6); - let pos = wpos2d.with_z(if on_ground { - z_range.start - } else { - z_range.end - }); - - let mut crystals: Vec = Vec::new(); - let max_length = (48.0 * close(vertical, MAX_RADIUS, 42.0)).max(12.0); - let length = rng.gen_range(8.0..max_length); - let radius = - Lerp::lerp(2.0, 4.5, length / max_length + rng.gen_range(-0.1..0.1)); - let dir = Vec3::new( - rng.gen_range(-3.0..3.0), - rng.gen_range(-3.0..3.0), - rng.gen_range(0.5..10.0) * if on_ground { 1.0 } else { -1.0 }, - ) - .normalized(); - - crystals.push(Crystal { - dir, - length, - radius, - }); - - (0..4).for_each(|_| { - crystals.push(Crystal { - dir: Vec3::new( - rng.gen_range(-1.0..1.0), - rng.gen_range(-1.0..1.0), - (dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), + && vertical > 16.0 + && rng.gen_bool( + 0.5 * close_fast(vertical, MAX_RADIUS, MAX_RADIUS - 16.0, 2) as f64 + * close_fast(biome.mushroom, 1.0, 0.7, 1) as f64, + ) + { + let purp = rng.gen_range(0..50); + Some(CaveStructure::Mushroom(Mushroom { + pos, + stalk: 8.0 + + rng.gen::().powf(2.0) + * (z_range.end - z_range.start - 8) as f32 + * 0.75, + head_color: Rgb::new( + 40 + purp, + rng.gen_range(60..120), + rng.gen_range(80..200) + purp, ), - length: length * rng.gen_range(0.3..0.8), - radius: (radius * rng.gen_range(0.5..0.8)).max(1.0), + })) + } else if biome.crystal > 0.5 + && rng.gen_bool(0.4 * close_fast(biome.crystal, 1.0, 0.7, 2) as f64) + { + let on_ground = rng.gen_bool(0.6); + let pos = wpos2d.with_z(if on_ground { + z_range.start + } else { + z_range.end }); - }); - let purple = rng.gen_range(25..75); - let blue = (rng.gen_range(45.0..75.0) * biome.icy) as u8; + let mut crystals: Vec = Vec::new(); + let max_length = + (48.0 * close_fast(vertical, MAX_RADIUS, MAX_RADIUS, 1)).max(12.0); + let length = rng.gen_range(8.0..max_length); + let radius = Lerp::lerp( + 2.0, + 4.5, + length / max_length + rng.gen_range(-0.1..0.1), + ); + let dir = Vec3::new( + rng.gen_range(-3.0..3.0), + rng.gen_range(-3.0..3.0), + rng.gen_range(0.5..10.0) * if on_ground { 1.0 } else { -1.0 }, + ) + .normalized(); - Some(CaveStructure::Crystal(CrystalCluster { - pos, - crystals, - color: Rgb::new( - 255 - blue * 2, - 255 - blue - purple, - 200 + rng.gen_range(25..55), - ), - })) - } else if biome.leafy > 0.8 - && rng.gen_bool( - 0.2 * (close(vertical, MAX_RADIUS, MAX_RADIUS - 16.0) - * close(horizontal, MAX_RADIUS, MAX_RADIUS - 12.0) - * close(biome.leafy, 1.0, 0.2)) - as f64, - ) - { - Some(CaveStructure::Flower(Flower { - pos, - stalk: 4.0 - + rng.gen::().powf(2.0) - * (z_range.end - z_range.start - 8) as f32 - * 0.75, - petals: rng.gen_range(1..5) * 2 + 1, - petal_height: rng.gen_range(4.0..16.0), - petal_radius: rng.gen_range(8.0..16.0), - rotation: (Mat3::rotation_x( - -(rng.gen_bool(1.0) as u32 as f32) * std::f32::consts::PI - / rng.gen_range(3.0..16.0), - ) * Mat3::rotation_y( - std::f32::consts::PI / rng.gen_range(3.0..16.0), - )) - .transposed(), - })) - } else if (biome.leafy > 0.8 || giant_tree_factor > 0.0) - && rng.gen_bool( - (0.4 * close(biome.leafy, 1.0, 0.4).max(1.0 + giant_tree_factor) - as f64) - .clamped(0.0, 1.0), - ) - { - Some(CaveStructure::GiantRoot { - pos, - radius: rng.gen_range( - 2.0..(6.0 - + close(vertical, MAX_RADIUS, MAX_RADIUS / 2.0) * 2.0 - + close(horizontal, MAX_RADIUS, MAX_RADIUS / 2.0) * 2.0), - ), - height: (z_range.end - z_range.start) as f32, - }) - } else { - None - } + crystals.push(Crystal { + dir, + length, + radius, + }); + + (0..4).for_each(|_| { + crystals.push(Crystal { + dir: Vec3::new( + rng.gen_range(-1.0..1.0), + rng.gen_range(-1.0..1.0), + (dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), + ), + length: length * rng.gen_range(0.3..0.8), + radius: (radius * rng.gen_range(0.5..0.8)).max(1.0), + }); + }); + + let purple = rng.gen_range(25..75); + let blue = (rng.gen_range(45.0..75.0) * biome.icy) as u8; + + Some(CaveStructure::Crystal(CrystalCluster { + pos, + crystals, + color: Rgb::new( + 255 - blue * 2, + 255 - blue - purple, + 200 + rng.gen_range(25..55), + ), + })) + } else if biome.leafy > 0.8 + && vertical > 16.0 + && horizontal > 8.0 + && rng.gen_bool( + 0.25 * (close_fast(vertical, MAX_RADIUS, MAX_RADIUS - 16.0, 2) + * close_fast(horizontal, MAX_RADIUS, MAX_RADIUS - 8.0, 2) + * biome.leafy) as f64, + ) + { + let petal_radius = rng.gen_range(8.0..16.0); + Some(CaveStructure::Flower(Flower { + pos, + stalk: 6.0 + + rng.gen::().powf(2.0) + * (z_range.end - z_range.start - 8) as f32 + * 0.75, + petals: rng.gen_range(1..5) * 2 + 1, + petal_height: 0.4 + * petal_radius + * (1.0 + rng.gen::().powf(2.0)), + petal_radius, + })) + } else if (biome.leafy > 0.7 || giant_tree_factor > 0.0) + && rng.gen_bool( + (0.5 * close_fast(biome.leafy, 1.0, 0.5, 1) + .max(1.0 + giant_tree_factor) + as f64) + .clamped(0.0, 1.0), + ) + { + Some(CaveStructure::GiantRoot { + pos, + radius: rng.gen_range( + 1.5..(3.5 + + close_fast(vertical, MAX_RADIUS, MAX_RADIUS / 2.0, 2) + * 3.0 + + close_fast(horizontal, MAX_RADIUS, MAX_RADIUS / 2.0, 2) + * 3.0), + ), + height: (z_range.end - z_range.start) as f32, + }) + } else { + None + } }) { structure } else { @@ -868,8 +941,8 @@ fn write_column( block_kind, Rgb::new( 30, - 120 + (radial * 30.0) as u8, - 180 - (radial * 30.0) as u8, + 120 + (radial * 40.0) as u8, + 180 - (radial * 40.0) as u8, ), )); } else if head_dist < 1.0 { @@ -949,14 +1022,28 @@ fn write_column( } }, CaveStructure::Flower(flower) => { - let wposf = wpos.map(|e| e as f32); - - let rpos = wposf - flower.pos.map(|e| e as f32); + let wposf = wpos.map(|e| e as f64); + let warp_freq = 1.0 / 16.0; + let warp_amp = Vec3::new(8.0, 8.0, 8.0); + let xy = wposf.xy(); + let xz = Vec2::new(wposf.x, wposf.z); + let yz = Vec2::new(wposf.y, wposf.z); + let wposf_warped = wposf.map(|e| e as f32) + + Vec3::new( + FastNoise2d::new(seed).get(yz * warp_freq), + FastNoise2d::new(seed).get(xz * warp_freq), + FastNoise2d::new(seed).get(xy * warp_freq), + ) * warp_amp + * (wposf.z as f32 - flower.pos.z as f32) + .mul(1.0 / flower.stalk) + .sub(1.0) + .min(0.0) + .abs() + .clamped(0.0, 1.0); + let rpos = wposf_warped - flower.pos.map(|e| e as f32); let stalk_radius = 2.5f32; - let petal_radius = flower.petal_radius; let petal_thickness = 2.5; - let dist_sq = rpos.xy().magnitude_squared(); if rpos.z < flower.stalk && dist_sq @@ -967,52 +1054,49 @@ fn write_column( return Some(Block::new(BlockKind::Wood, Rgb::new(0, 108, 0))); } - let rpos = wposf - flower.pos.map(|e| e as f32) - Vec3::unit_z() * flower.stalk; - let rpos = flower.rotation * (rpos - 0.5); + let rpos = rpos - Vec3::unit_z() * flower.stalk; let dist_sq = rpos.xy().magnitude_squared(); - let petal_radius_sq = petal_radius.powi(2); + let petal_radius_sq = flower.petal_radius.powi(2); if dist_sq < petal_radius_sq { let petal_height_at = - (dist_sq / petal_radius_sq).powf(1.5) * flower.petal_height; + (dist_sq / petal_radius_sq).powf(1.0) * flower.petal_height; if rpos.z > petal_height_at - 1.0 && rpos.z <= petal_height_at + petal_thickness { let dist_ratio = dist_sq / petal_radius_sq; let yellow = (60.0 * dist_ratio) as u8; - if dist_ratio < 0.175 && rpos.z > petal_height_at { - let near = (rpos.x.atan2(rpos.y)).rem_euclid( - std::f32::consts::TAU / (flower.petals as f32 * 1.5), - ); - let inset = close(near, 0.0, 0.475); - let inset2 = close(near, 0.0, 0.3); - if dist_ratio > inset { + let near = rpos + .x + .atan2(rpos.y) + .rem_euclid(std::f32::consts::TAU / flower.petals as f32); + if dist_ratio < 0.175 { + let red = close_fast(near, 0.0, 0.5, 1); + let purple = close_fast(near, 0.0, 0.35, 1); + if dist_ratio > red || rpos.z < petal_height_at { return Some(Block::new( - BlockKind::Wood, + BlockKind::ArtLeaves, Rgb::new(240, 80 - yellow, 80 - yellow), )); - } else if dist_ratio > inset2 { + } else if dist_ratio > purple { return Some(Block::new( - BlockKind::Wood, + BlockKind::ArtLeaves, Rgb::new(200, 14, 132), )); } else { return Some(Block::new( - BlockKind::Wood, + BlockKind::ArtLeaves, Rgb::new(249, 156, 218), )); } - } else if dist_ratio > 0.3 { - let near = (rpos.x.atan2(rpos.y)) - .rem_euclid(std::f32::consts::TAU / flower.petals as f32); - let inset = close(near, -1.0, 0.9).max(close(near, 1.0, 0.9)); + } else { + let inset = close_fast(near, -1.0, 1.0, 2) + .max(close_fast(near, 1.0, 1.0, 2)); if dist_ratio < inset { return Some(Block::new( - BlockKind::Wood, + BlockKind::ArtLeaves, Rgb::new(240, 80 - yellow, 80 - yellow), )); } - } else { - return Some(Block::new(BlockKind::Wood, Rgb::new(240, 50, 50))); } } @@ -1052,6 +1136,7 @@ fn write_column( let rpos = wposf_warped - pos.map(|e| e as f32); let dist_sq = rpos.xy().magnitude_squared(); if dist_sq < radius.powi(2) { + // Moss if col.marble_mid > (std::f32::consts::PI * rpos.z / *height) .sin() @@ -1069,36 +1154,8 @@ fn write_column( None }; - let ceiling_mold = |wpos: Vec3| { - let wpos = wpos + wpos.xy().yx().with_z(0.0) * 0.2; - let dims = Vec2::new(4.0, 32.0); - let mold_posf = wpos + Vec2::unit_y() * (wpos.x / dims.x).floor() * 89.0 / dims; - let mold_pos = mold_posf.map(|e| e.floor() as i32); - let mut rng = RandomPerm::new(((mold_pos.x << 16) | mold_pos.y) as u32); - - if !void_above && biome.mushroom > 0.9 && ceiling_cover > 0.0 && rng.gen_bool(0.05) { - let mold_length = ((mold_posf.y.fract() - 0.5).abs() * 2.0 * dims.y) - .mul(0.05) - .powf(2.0) - .min(16.0); - let mold_z = z_range.end as f32 - mold_length; - - if Vec2::new(mold_posf.x.fract() * 2.0 - 1.0, (mold_z - wpos.z) / 4.0) - .magnitude_squared() - < 1.0f32 - { - Some(Block::new(BlockKind::GlowingRock, Rgb::new(10, 70, 148))) - } else { - None - } - } else { - None - } - }; - for z in bedrock..z_range.end { let wpos = wpos2d.with_z(z); - let wposf = wpos.map(|e| e as f32); let mut try_spawn_entity = false; canvas.map_resource(wpos, |_block| { if z < z_range.start - 4 && !void_below { @@ -1155,15 +1212,26 @@ fn write_column( biome.icy, ); Block::new( - if rand.chance(wpos, (biome.mushroom * 0.01).max(biome.icy)) { + if rand.chance(wpos, (biome.mushroom * 0.01).max(biome.icy * 0.1)) { BlockKind::GlowingWeakRock } else if rand.chance(wpos, biome.sandy) { BlockKind::Sand + } else if rand.chance(wpos, biome.leafy) { + BlockKind::ArtLeaves } else { BlockKind::WeakRock }, stalactite.map(|e| e as u8), ) + } else if z < ceiling && z >= ceiling_drip { + let color = if biome.mushroom > 0.9 { + Rgb::new(10, 70, 148) + } else if biome.icy > 0.9 { + Rgb::new(120, 140, 255) + } else { + Rgb::new(80, 100, 150) + }; + Block::new(BlockKind::GlowingRock, color) } else if z >= base && z < floor && !void_below && !sky_above { let (net_col, total) = [ ( @@ -1266,8 +1334,11 @@ fn write_column( } else if let Some(sprite) = (z == floor && !void_below && !sky_above) .then(|| { if col.marble_mid > 0.55 - && biome.mushroom > 0.5 - && rand.chance(wpos2d.with_z(1), biome.mushroom * 0.25 * col.marble_mid) + && biome.mushroom > 0.6 + && rand.chance( + wpos2d.with_z(1), + biome.mushroom.powi(2) * 0.2 * col.marble_mid, + ) { [ (SpriteKind::GlowMushroom, 0.5), @@ -1283,7 +1354,10 @@ fn write_column( .map(|s| s.0) } else if col.marble_mid > 0.6 && biome.leafy > 0.4 - && rand.chance(wpos2d.with_z(15), biome.leafy * 0.3 * col.marble_mid) + && rand.chance( + wpos2d.with_z(15), + biome.leafy.powi(2) * 0.25 * col.marble_mid, + ) { let mixed = col.marble.add(col.marble_small.sub(0.5).mul(0.25)); if (0.25..0.45).contains(&mixed) || (0.55..0.75).contains(&mixed) { @@ -1371,9 +1445,11 @@ fn write_column( .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(23), biome.icy * 0.005) { + } else if biome.icy > 0.5 && rand.chance(wpos2d.with_z(23), biome.icy * 0.005) { Some(SpriteKind::IceCrystal) - } else if rand.chance(wpos2d.with_z(31), biome.icy * biome.mineral * 0.005) { + } else if biome.icy > 0.5 + && rand.chance(wpos2d.with_z(31), biome.icy * biome.mineral * 0.005) + { Some(SpriteKind::GlowIceCrystal) } else if rand.chance(wpos2d.with_z(5), 0.0025) { [ @@ -1437,17 +1513,20 @@ fn write_column( Block::air(sprite) } else if let Some(sprite) = (z == ceiling - 1 && !void_above) .then(|| { - if rand.chance(wpos2d.with_z(3), biome.mushroom * 0.01) { + if biome.mushroom > 0.5 && rand.chance(wpos2d.with_z(3), biome.mushroom * 0.01) + { [(SpriteKind::MycelBlue, 0.75), (SpriteKind::Mold, 1.0)] .choose_weighted(rng, |(_, w)| *w) .ok() .map(|s| s.0) - } else if rand.chance(wpos2d.with_z(4), biome.leafy * 0.015) { + } else if biome.leafy > 0.4 + && rand.chance(wpos2d.with_z(4), biome.leafy * 0.015) + { [ - (SpriteKind::Liana, 1.0), - (SpriteKind::CeilingLanternPlant, 1.5), - (SpriteKind::CeilingLanternFlower, 1.25), - (SpriteKind::CeilingJungleLeafyPlant, 1.0), + (SpriteKind::Liana, 1.5), + (SpriteKind::CeilingLanternPlant, 1.25), + (SpriteKind::CeilingLanternFlower, 1.0), + (SpriteKind::CeilingJungleLeafyPlant, 1.5), ] .choose_weighted(rng, |(_, w)| *w) .ok() @@ -1463,10 +1542,6 @@ fn write_column( .flatten() { Block::air(sprite) - } else if let Some(mold) = - ceiling_mold(wposf).or_else(|| ceiling_mold(wposf.xy().yx().with_z(wposf.z))) - { - mold } else if let Some(structure_block) = get_structure(wpos, rng) { structure_block } else { @@ -1519,11 +1594,13 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio ), ( Some("common.entity.wild.aggressive.batfox"), - (biome.leafy.max(biome.barren) + 0.15) * 0.35, - ), - ( - Some("common.entity.wild.aggressive.rocksnapper"), - (biome.leafy.max(biome.barren) + 0.1) * 0.08, + (biome + .leafy + .max(biome.barren) + .max(biome.sandy) + .max(biome.snowy) + + 0.3) + * 0.35, ), ( Some("common.entity.wild.aggressive.cave_salamander"), @@ -1544,7 +1621,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Dusty biome ( Some("common.entity.wild.aggressive.dodarock"), - (biome.dusty.max(biome.barren) + 0.05) * 0.05, + (biome.dusty.max(biome.barren).max(biome.snowy) + 0.05) * 0.05, ), ( Some("common.entity.wild.aggressive.cave_spider"), @@ -1554,17 +1631,13 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio Some("common.entity.wild.aggressive.cave_troll"), (biome.dusty + 0.1) * 0.05, ), - ( - Some("common.entity.wild.aggressive.antlion"), - (biome.dusty.min(biome.depth) + 0.0) * 0.01, - ), ( Some("common.entity.wild.peaceful.rat"), (biome.dusty.max(biome.barren) + 0.15) * 0.3, ), ( - Some("common.entity.wild.peaceful.bat"), - (biome.dusty.max(biome.barren) + 0.1) * 0.25, + Some("common.entity.wild.aggressive.bat"), + (biome.dusty.max(biome.sandy).max(biome.snowy) + 0.1) * 0.25, ), // Icy biome ( @@ -1582,7 +1655,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Lava biome ( Some("common.entity.wild.aggressive.lavadrake"), - (biome.fire + 0.0) * 0.15, + (biome.fire + 0.0) * 0.5, ), ( Some("common.entity.wild.peaceful.crawler_molten"), @@ -1592,6 +1665,29 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio Some("common.entity.wild.aggressive.red_oni"), (biome.fire + 0.0) * 0.05, ), + // Crystal biome + ( + Some("common.entity.wild.aggressive.basilisk"), + (biome.crystal + 0.1) * 0.1, + ), + // Sandy biome + ( + Some("common.entity.wild.aggressive.antlion"), + (biome.sandy.max(biome.dusty) + 0.1) * 0.025, + ), + ( + Some("common.entity.wild.aggressive.sandshark"), + (biome.sandy + 0.1) * 0.025, + ), + // Snowy biome + ( + Some("common.entity.wild.aggressive.akhlut"), + (biome.snowy.max(biome.icy) + 0.1) * 0.05, + ), + ( + Some("common.entity.wild.aggressive.rocksnapper"), + ((biome.barren).max(biome.snowy) + 0.1) * 0.1, + ), // With depth ( Some("common.entity.wild.aggressive.black_widow"), diff --git a/world/src/lib.rs b/world/src/lib.rs index 15836e8795..cebc3b1e2c 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -465,9 +465,9 @@ impl World { layer::apply_caverns_to(&mut canvas, &mut dynamic_rng); } if index.features.caves { - layer::apply_caves_to(&mut canvas, &mut dynamic_rng); + layer::apply_caves2_to(&mut canvas, &mut dynamic_rng); + // layer::apply_caves_to(&mut canvas, &mut dynamic_rng); } - layer::apply_caves2_to(&mut canvas, &mut dynamic_rng); if index.features.rocks { layer::apply_rocks_to(&mut canvas, &mut dynamic_rng); } From 059cdebb489201b99fefcae14e54d53b78ddaaff Mon Sep 17 00:00:00 2001 From: Gemu Peachems Date: Thu, 22 Feb 2024 15:04:31 +0100 Subject: [PATCH 17/24] change spawns --- world/src/layer/cave.rs | 74 ++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 858cf55399..bf8c8b4f8e 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1574,19 +1574,15 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Leafy biome ( Some("common.entity.wild.peaceful.holladon"), - (biome.leafy.max(biome.barren) + 0.1) * 0.5, + (biome.leafy.max(biome.dusty) + 0.05) * 0.3, ), ( - Some("common.entity.wild.peaceful.turtle"), - (biome.leafy + 0.05) * 0.5, + Some("common.entity.dungeon.gnarling.mandragora"), + (biome.leafy + 0.05) * 0.2, ), ( Some("common.entity.wild.aggressive.rootsnapper"), - (biome.leafy + 0.05) * 0.02, - ), - ( - Some("common.entity.wild.peaceful.axolotl"), - (biome.leafy + 0.05) * 0.5, + (biome.leafy + 0.05) * 0.1, ), ( Some("common.entity.wild.aggressive.maneater"), @@ -1603,25 +1599,31 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio * 0.35, ), ( - Some("common.entity.wild.aggressive.cave_salamander"), + Some("common.entity.wild.aggressive.asp"), (biome.leafy + 0.1) * 0.2, ), - ( - Some("common.entity.wild.aggressive.asp"), - (biome.leafy + 0.1) * 0.1, - ), ( Some("common.entity.wild.aggressive.swamp_troll"), - (biome.leafy + 0.0) * 0.1, + (biome.leafy + 0.0) * 0.05, ), ( Some("common.entity.wild.peaceful.bat"), (biome.leafy + 0.1) * 0.25, ), + ( + Some("common.entity.wild.peaceful.crawler_moss"), + (biome.leafy + 0.05) * 0.25, + ), // Dusty biome ( Some("common.entity.wild.aggressive.dodarock"), - (biome.dusty.max(biome.barren).max(biome.snowy) + 0.05) * 0.05, + (biome + .dusty + .max(biome.barren) + .max(biome.crystal) + .max(biome.snowy) + + 0.05) + * 0.05, ), ( Some("common.entity.wild.aggressive.cave_spider"), @@ -1640,53 +1642,73 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio (biome.dusty.max(biome.sandy).max(biome.snowy) + 0.1) * 0.25, ), // Icy biome - ( - Some("common.entity.wild.aggressive.blue_oni"), - (biome.icy + 0.0) * 0.03, - ), ( Some("common.entity.wild.aggressive.icedrake"), (biome.icy + 0.0) * 0.04, ), + ( + Some("common.entity.wild.aggressive.roshwalr"), + (biome.icy + 0.0) * 0.1, + ), ( Some("common.entity.wild.aggressive.wendigo"), (biome.icy.min(biome.depth) + 0.0) * 0.02, ), + ( + Some("common.entity.wild.aggressive.frostfang"), + (biome.icy + 0.0) * 0.2, + ), + ( + Some("common.entity.wild.aggressive.tursus"), + (biome.icy + 0.0) * 0.03, + ), // Lava biome ( Some("common.entity.wild.aggressive.lavadrake"), - (biome.fire + 0.0) * 0.5, + (biome.fire + 0.0) * 0.25, ), ( Some("common.entity.wild.peaceful.crawler_molten"), - (biome.fire + 0.0) * 0.35, + (biome.fire + 0.0) * 0.5, + ), + ( + Some("common.entity.wild.aggressive.cave_salamander"), + (biome.fire + 0.0) * 0.5, ), ( Some("common.entity.wild.aggressive.red_oni"), - (biome.fire + 0.0) * 0.05, + (biome.fire + 0.0) * 0.03, ), // Crystal biome ( Some("common.entity.wild.aggressive.basilisk"), (biome.crystal + 0.1) * 0.1, ), + ( + Some("common.entity.wild.aggressive.blue_oni"), + (biome.crystal + 0.0) * 0.03, + ), // Sandy biome ( Some("common.entity.wild.aggressive.antlion"), - (biome.sandy.max(biome.dusty) + 0.1) * 0.025, + (biome.sandy.max(biome.dusty) + 0.1) * 0.050, ), ( Some("common.entity.wild.aggressive.sandshark"), - (biome.sandy + 0.1) * 0.025, + (biome.sandy + 0.1) * 0.050, + ), + ( + Some("common.entity.wild.peaceful.crawler_sand"), + (biome.sandy + 0.1) * 0.2, ), // Snowy biome ( Some("common.entity.wild.aggressive.akhlut"), - (biome.snowy.max(biome.icy) + 0.1) * 0.05, + (biome.snowy.max(biome.icy) + 0.1) * 0.03, ), ( Some("common.entity.wild.aggressive.rocksnapper"), - ((biome.barren).max(biome.snowy) + 0.1) * 0.1, + (biome.barren.max(biome.crystal).max(biome.snowy) + 0.1) * 0.1, ), // With depth ( From 6979a1becab9f2cbbe1f254f2993735c559a6f47 Mon Sep 17 00:00:00 2001 From: Syniis Date: Thu, 22 Feb 2024 17:23:33 +0100 Subject: [PATCH 18/24] More granular entity spawning. Tweak biome distribution to not favour hot biomes --- world/src/layer/cave.rs | 265 ++++++++++++++++++++++++---------------- 1 file changed, 163 insertions(+), 102 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index bf8c8b4f8e..7460b9b3e2 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -17,6 +17,7 @@ use common::{ vol::RectVolSize, }; use inline_tweak::tweak_fn; +use itertools::Itertools; use noise::NoiseFn; use rand::prelude::*; use std::{ @@ -210,7 +211,7 @@ impl Tunnel { .mul(2.0) .sub(1.0) .add( - ((col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32 * 0.5)) + ((col.alt - wpos.z as f32) / (AVG_LEVEL_DEPTH as f32 * LAYERS as f32 * 0.75)) .clamped(0.0, 2.5), ), below, @@ -247,27 +248,27 @@ impl Tunnel { // Extremely hot and dry areas deep underground let fire = underground * close(humidity, 0.0, 0.6) - * close(temp, 2.5, 1.4) + * close(temp, 2.0, 1.3) * close(depth, 1.0, 0.5); // Overgrown with plants that need a moderate climate to survive let leafy = underground * close(humidity, 0.8, 0.8) - * close(temp, 0.85, 0.9) + * close(temp, 0.95, 0.85) * close(depth, 0.0, 0.6); // Cool temperature, dry and devoid of value let dusty = close(humidity, 0.0, 0.5) * close(temp, -0.1, 0.6); // Deep underground and freezing cold let icy = underground - * close(temp, -1.0, 0.6) - * close(depth, 1.0, 0.5) + * close(temp, -1.5, 1.3) + * close(depth, 1.0, 0.65) * close(humidity, 1.0, 0.7); // Rocky cold cave that appear near the surface let snowy = close(temp, -0.5, 0.3) * close(depth, 0.0, 0.4); // Crystals grow deep underground in areas rich with minerals. They are present // in areas with colder temperatures and low humidity let crystal = underground - * close(humidity, 0.0, 0.7) - * close(temp, -0.5, 0.8) + * close(humidity, 0.0, 0.5) + * close(temp, -0.6, 0.75) * close(depth, 1.0, 0.55) * close(mineral, 1.5, 1.0); // Hot, dry and shallow @@ -583,9 +584,10 @@ fn write_column( let ceiling_cover = if biome.leafy > 0.3 || biome.mushroom > 0.5 - || biome.icy > 0.7 - || biome.sandy > 0.5 - || biome.fire > 0.5 + || biome.icy > 0.6 + || biome.sandy > 0.4 + || biome.fire > 0.4 + || biome.crystal > 0.75 { // 1.0 because at some point we maybe want to use some noise value here instead 1.0.mul(((col.alt - z_range.end as f32) / 32.0).clamped(0.0, 1.0)) @@ -599,6 +601,7 @@ fn write_column( .max(biome.sandy - 0.3) .max(biome.leafy - 0.4) .max(biome.mushroom - 0.4) + .max(biome.crystal - 0.5) { max_height * col.marble_mid } else { @@ -1179,40 +1182,53 @@ fn write_column( Lerp::lerp_unclamped( Lerp::lerp_unclamped( Lerp::lerp_unclamped( - Rgb::new(80, 100, 150), - Rgb::new(23, 44, 88), - biome.mushroom, + Lerp::lerp_unclamped( + Rgb::new(80, 100, 150), + Rgb::new(23, 44, 88), + biome.mushroom, + ), + Lerp::lerp_unclamped( + Rgb::new(100, 40, 40), + Rgb::new(100, 75, 100), + col.marble_small, + ), + biome.fire, ), Lerp::lerp_unclamped( - Rgb::new(100, 40, 40), - Rgb::new(100, 75, 100), - col.marble_small, + Rgb::new(238, 198, 139), + Rgb::new(111, 99, 64), + col.marble_mid, ), - biome.fire, + biome.sandy, ), Lerp::lerp_unclamped( - Rgb::new(238, 198, 139), - Rgb::new(111, 99, 64), - col.marble_mid, + Rgb::new(0, 73, 12), + Rgb::new(49, 63, 12), + col.marble_small, ), - biome.sandy, + biome.leafy, ), Lerp::lerp_unclamped( - Rgb::new(0, 73, 12), - Rgb::new(49, 63, 12), - col.marble_small, + Rgb::new(100, 150, 255), + Rgb::new(100, 120, 255), + col.marble, ), - biome.leafy, + biome.icy, ), Lerp::lerp_unclamped( - Rgb::new(100, 150, 255), - Rgb::new(100, 120, 255), - col.marble, + Rgb::new(105, 25, 131), + Rgb::new(251, 238, 255), + col.marble_mid, ), - biome.icy, + biome.crystal, ); Block::new( - if rand.chance(wpos, (biome.mushroom * 0.01).max(biome.icy * 0.1)) { + if rand.chance( + wpos, + (biome.mushroom * 0.01) + .max(biome.icy * 0.1) + .max(biome.crystal * 0.005), + ) { BlockKind::GlowingWeakRock } else if rand.chance(wpos, biome.sandy) { BlockKind::Sand @@ -1556,175 +1572,220 @@ fn write_column( } fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Biome, rng: &mut R) { - if RandomField::new(canvas.info().index().seed).chance(wpos, 0.05) { + if RandomField::new(canvas.info().index().seed).chance(wpos, 0.025) { if let Some(entity_asset) = [ // Mushroom biome ( Some("common.entity.wild.peaceful.truffler"), - (biome.mushroom + 0.02) * 0.35, + biome.mushroom + 0.02, + 0.35, + 0.5, ), ( Some("common.entity.wild.peaceful.fungome"), - (biome.mushroom + 0.02) * 0.5, + biome.mushroom + 0.02, + 0.5, + 0.5, ), ( - Some("common.entity.wild.peaceful.bat"), - (biome.mushroom + 0.1) * 0.25, + Some("common.entity.wild.aggressive.bat"), + biome.mushroom + 0.1, + 0.25, + 0.5, ), // Leafy biome ( Some("common.entity.wild.peaceful.holladon"), - (biome.leafy.max(biome.dusty) + 0.05) * 0.3, + biome.leafy + 0.05, + 0.5, + 0.5, ), ( - Some("common.entity.dungeon.gnarling.mandragora"), - (biome.leafy + 0.05) * 0.2, + Some("common.entity.wild.peaceful.turtle"), + biome.leafy + 0.05, + 0.5, + 0.5, ), ( Some("common.entity.wild.aggressive.rootsnapper"), - (biome.leafy + 0.05) * 0.1, + biome.leafy + 0.05, + 0.05, + 0.5, + ), + ( + Some("common.entity.wild.peaceful.axolotl"), + biome.leafy + 0.05, + 0.5, + 0.5, ), ( Some("common.entity.wild.aggressive.maneater"), - (biome.leafy + 0.0) * 0.05, + biome.leafy + 0.05, + 0.1, + 0.5, ), ( Some("common.entity.wild.aggressive.batfox"), - (biome + biome .leafy .max(biome.barren) .max(biome.sandy) .max(biome.snowy) - + 0.3) - * 0.35, + + 0.3, + 0.35, + 0.5, + ), + ( + Some("common.entity.wild.aggressive.cave_salamander"), + biome.leafy + 0.0, + 0.3, + 0.5, ), ( Some("common.entity.wild.aggressive.asp"), - (biome.leafy + 0.1) * 0.2, + biome.leafy + 0.1, + 0.25, + 0.5, ), ( Some("common.entity.wild.aggressive.swamp_troll"), - (biome.leafy + 0.0) * 0.05, + biome.leafy + 0.0, + 0.1, + 0.5, ), ( - Some("common.entity.wild.peaceful.bat"), - (biome.leafy + 0.1) * 0.25, - ), - ( - Some("common.entity.wild.peaceful.crawler_moss"), - (biome.leafy + 0.05) * 0.25, + Some("common.entity.wild.aggressive.bat"), + biome.leafy + 0.1, + 0.25, + 0.5, ), // Dusty biome ( Some("common.entity.wild.aggressive.dodarock"), - (biome - .dusty - .max(biome.barren) - .max(biome.crystal) - .max(biome.snowy) - + 0.05) - * 0.05, + biome.dusty.max(biome.barren).max(biome.snowy) + 0.05, + 0.05, + 0.5, ), ( Some("common.entity.wild.aggressive.cave_spider"), - (biome.dusty + 0.0) * 0.05, + biome.dusty + 0.0, + 0.4, + 0.5, ), ( Some("common.entity.wild.aggressive.cave_troll"), - (biome.dusty + 0.1) * 0.05, + biome.dusty + 0.1, + 0.05, + 0.5, ), ( Some("common.entity.wild.peaceful.rat"), - (biome.dusty.max(biome.barren) + 0.15) * 0.3, + biome.dusty + 0.1, + 0.3, + 0.5, ), ( Some("common.entity.wild.aggressive.bat"), - (biome.dusty.max(biome.sandy).max(biome.snowy) + 0.1) * 0.25, + biome.dusty.max(biome.sandy).max(biome.snowy) + 0.1, + 0.25, + 0.5, ), // Icy biome ( - Some("common.entity.wild.aggressive.icedrake"), - (biome.icy + 0.0) * 0.04, + Some("common.entity.wild.aggressive.blue_oni"), + biome.icy + 0.0, + 0.03, + 0.5, ), ( - Some("common.entity.wild.aggressive.roshwalr"), - (biome.icy + 0.0) * 0.1, + Some("common.entity.wild.aggressive.icedrake"), + biome.icy + 0.0, + 0.1, + 0.5, ), ( Some("common.entity.wild.aggressive.wendigo"), - (biome.icy.min(biome.depth) + 0.0) * 0.02, - ), - ( - Some("common.entity.wild.aggressive.frostfang"), - (biome.icy + 0.0) * 0.2, - ), - ( - Some("common.entity.wild.aggressive.tursus"), - (biome.icy + 0.0) * 0.03, + biome.icy.min(biome.depth) + 0.0, + 0.02, + 0.5, ), // Lava biome ( Some("common.entity.wild.aggressive.lavadrake"), - (biome.fire + 0.0) * 0.25, + biome.fire + 0.0, + 0.5, + 0.5, ), ( Some("common.entity.wild.peaceful.crawler_molten"), - (biome.fire + 0.0) * 0.5, - ), - ( - Some("common.entity.wild.aggressive.cave_salamander"), - (biome.fire + 0.0) * 0.5, + biome.fire + 0.0, + 0.75, + 0.5, ), ( Some("common.entity.wild.aggressive.red_oni"), - (biome.fire + 0.0) * 0.03, + biome.fire + 0.0, + 0.05, + 0.5, ), // Crystal biome ( Some("common.entity.wild.aggressive.basilisk"), - (biome.crystal + 0.1) * 0.1, - ), - ( - Some("common.entity.wild.aggressive.blue_oni"), - (biome.crystal + 0.0) * 0.03, + biome.crystal + 0.1, + 0.1, + 0.5, ), // Sandy biome ( Some("common.entity.wild.aggressive.antlion"), - (biome.sandy.max(biome.dusty) + 0.1) * 0.050, + biome.sandy.max(biome.dusty) + 0.1, + 0.025, + 0.5, ), ( Some("common.entity.wild.aggressive.sandshark"), - (biome.sandy + 0.1) * 0.050, - ), - ( - Some("common.entity.wild.peaceful.crawler_sand"), - (biome.sandy + 0.1) * 0.2, + biome.sandy + 0.1, + 0.025, + 0.5, ), // Snowy biome ( Some("common.entity.wild.aggressive.akhlut"), - (biome.snowy.max(biome.icy) + 0.1) * 0.03, + biome.snowy.max(biome.icy) + 0.1, + 0.05, + 0.5, ), ( Some("common.entity.wild.aggressive.rocksnapper"), - (biome.barren.max(biome.crystal).max(biome.snowy) + 0.1) * 0.1, + biome.barren.max(biome.snowy) + 0.1, + 0.1, + 0.5, ), // With depth ( Some("common.entity.wild.aggressive.black_widow"), - (biome.depth + 0.0) * 0.01, + biome.depth + 0.0, + 0.02, + 0.5, ), ( Some("common.entity.wild.aggressive.ogre"), - (biome.depth + 0.0) * 0.02, + biome.depth + 0.0, + 0.02, + 0.5, ), - ( - Some("common.entity.wild.aggressive.basilisk"), - (biome.depth + 0.1) * 0.005, - ), - (None, 100.0), + (None, 100.0, 0.0, 0.0), ] + .iter() + .filter_map(|(entity, biome_modifier, chance, cutoff)| { + if let Some(entity) = entity { + let close = close_fast(1.0, *biome_modifier, *cutoff, 2); + (close > 0.0).then(|| (Some(entity), close * chance)) + } else { + Some((None, 100.0)) + } + }) + .collect_vec() .choose_weighted(rng, |(_, w)| *w) .ok() .and_then(|s| s.0) From 48837bf3f6886684c18048da4d22556b6910928d Mon Sep 17 00:00:00 2001 From: Gemu Peachems Date: Sat, 24 Feb 2024 20:28:29 +0100 Subject: [PATCH 19/24] Spawns --- common/src/comp/body.rs | 2 +- world/src/layer/cave.rs | 82 +++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index a026152fab..60746e7208 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -1118,7 +1118,7 @@ impl Body { | object::Body::Flamethrower | object::Body::TerracottaStatue ), - Body::QuadrupedLow(q) => matches!(q.species, quadruped_low::Species::Lavadrake), + Body::QuadrupedLow(q) => matches!(q.species, quadruped_low::Species::Lavadrake | quadruped_low::Species::Salamander), Body::BirdLarge(b) => matches!( b.species, bird_large::Species::Phoenix diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 7460b9b3e2..76cd40eb8c 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1570,9 +1570,9 @@ fn write_column( } } } - +#[tweak_fn] fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Biome, rng: &mut R) { - if RandomField::new(canvas.info().index().seed).chance(wpos, 0.025) { + if RandomField::new(canvas.info().index().seed).chance(wpos, 0.035) { if let Some(entity_asset) = [ // Mushroom biome ( @@ -1596,32 +1596,26 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Leafy biome ( Some("common.entity.wild.peaceful.holladon"), - biome.leafy + 0.05, - 0.5, + biome.leafy.max(biome.dusty) + 0.05, + 0.25, 0.5, ), ( - Some("common.entity.wild.peaceful.turtle"), + Some("common.entity.dungeon.gnarling.mandragora"), biome.leafy + 0.05, - 0.5, + 0.2, 0.5, ), ( Some("common.entity.wild.aggressive.rootsnapper"), biome.leafy + 0.05, - 0.05, - 0.5, - ), - ( - Some("common.entity.wild.peaceful.axolotl"), - biome.leafy + 0.05, - 0.5, + 0.075, 0.5, ), ( Some("common.entity.wild.aggressive.maneater"), biome.leafy + 0.05, - 0.1, + 0.075, 0.5, ), ( @@ -1632,25 +1626,25 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio .max(biome.sandy) .max(biome.snowy) + 0.3, - 0.35, + 0.25, 0.5, ), ( - Some("common.entity.wild.aggressive.cave_salamander"), - biome.leafy + 0.0, - 0.3, + Some("common.entity.wild.peaceful.crawler_moss"), + biome.leafy + 0.05, + 0.25, 0.5, ), ( Some("common.entity.wild.aggressive.asp"), - biome.leafy + 0.1, - 0.25, + biome.leafy.max(biome.sandy) + 0.1, + 0.2, 0.5, ), ( Some("common.entity.wild.aggressive.swamp_troll"), biome.leafy + 0.0, - 0.1, + 0.05, 0.5, ), ( @@ -1662,7 +1656,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Dusty biome ( Some("common.entity.wild.aggressive.dodarock"), - biome.dusty.max(biome.barren).max(biome.snowy) + 0.05, + biome.dusty.max(biome.barren).max(biome.crystal).max(biome.snowy) + 0.05, 0.05, 0.5, ), @@ -1691,12 +1685,6 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.5, ), // Icy biome - ( - Some("common.entity.wild.aggressive.blue_oni"), - biome.icy + 0.0, - 0.03, - 0.5, - ), ( Some("common.entity.wild.aggressive.icedrake"), biome.icy + 0.0, @@ -1709,6 +1697,18 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.02, 0.5, ), + ( + Some("common.entity.wild.aggressive.frostfang"), + biome.icy + 0.0, + 0.25, + 0.5, + ), + ( + Some("common.entity.wild.aggressive.tursus"), + biome.icy + 0.0, + 0.03, + 0.5, + ), // Lava biome ( Some("common.entity.wild.aggressive.lavadrake"), @@ -1719,13 +1719,19 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio ( Some("common.entity.wild.peaceful.crawler_molten"), biome.fire + 0.0, - 0.75, + 0.5, 0.5, ), + ( + Some("common.entity.wild.aggressive.cave_salamander"), + biome.fire + 0.0, + 0.5, + 0.5, + ), ( Some("common.entity.wild.aggressive.red_oni"), biome.fire + 0.0, - 0.05, + 0.03, 0.5, ), // Crystal biome @@ -1735,6 +1741,12 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.1, 0.5, ), + ( + Some("common.entity.wild.aggressive.blue_oni"), + biome.crystal + 0.0, + 0.03, + 0.5, + ), // Sandy biome ( Some("common.entity.wild.aggressive.antlion"), @@ -1748,16 +1760,22 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.025, 0.5, ), + ( + Some("common.entity.wild.peaceful.crawler_sand"), + biome.sandy + 0.1, + 0.25, + 0.5, + ), // Snowy biome ( Some("common.entity.wild.aggressive.akhlut"), - biome.snowy.max(biome.icy) + 0.1, + (biome.snowy.max(biome.icy) + 0.1) * 0.03, 0.05, 0.5, ), ( Some("common.entity.wild.aggressive.rocksnapper"), - biome.barren.max(biome.snowy) + 0.1, + biome.barren.max(biome.crystal).max(biome.snowy) + 0.1, 0.1, 0.5, ), From 2472a62e38cd1f92151ac0b5ac003584ada85a30 Mon Sep 17 00:00:00 2001 From: Syniis Date: Sat, 24 Feb 2024 23:08:06 +0100 Subject: [PATCH 20/24] Fmt, remove inline_tweak and move close functions --- Cargo.lock | 15 -- common/src/comp/body.rs | 5 +- world/Cargo.toml | 2 +- world/src/index.rs | 2 +- world/src/layer/cave.rs | 335 ++++++++++++++++----------------- world/src/layer/scatter.rs | 11 +- world/src/layer/wildlife.rs | 6 +- world/src/site2/plot/bridge.rs | 4 +- world/src/util/mod.rs | 8 + 9 files changed, 183 insertions(+), 205 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0a443b765..158b62b4f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3150,22 +3150,8 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6acddbefae08bfba73e27f55513f491f35c365d84bf3002bf85ba9b916c5e5f" dependencies = [ - "inline_tweak_derive", "lazy_static", - "proc-macro2 1.0.78", "rustc-hash", - "syn 2.0.48", -] - -[[package]] -name = "inline_tweak_derive" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46d62a0a3b6af04d4eee8e7251cd758ce74b0ed86253d3e4ac8a1b297a75f4a0" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.48", ] [[package]] @@ -7415,7 +7401,6 @@ dependencies = [ "fxhash", "hashbrown 0.13.2", "image", - "inline_tweak", "itertools 0.10.5", "kiddo", "lazy_static", diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 60746e7208..6fc0824ac0 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -1118,7 +1118,10 @@ impl Body { | object::Body::Flamethrower | object::Body::TerracottaStatue ), - Body::QuadrupedLow(q) => matches!(q.species, quadruped_low::Species::Lavadrake | quadruped_low::Species::Salamander), + Body::QuadrupedLow(q) => matches!( + q.species, + quadruped_low::Species::Lavadrake | quadruped_low::Species::Salamander + ), Body::BirdLarge(b) => matches!( b.species, bird_large::Species::Phoenix diff --git a/world/Cargo.toml b/world/Cargo.toml index 9f104d990d..fadad33856 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -39,7 +39,7 @@ packed_simd = { version = "0.3.9", optional = true } rayon = { workspace = true } serde = { workspace = true } ron = { workspace = true } -inline_tweak = { workspace = true, features = ["derive"] } +# inline_tweak = { workspace = true, features = ["derive"] } kiddo = "0.2" strum = { workspace = true } diff --git a/world/src/index.rs b/world/src/index.rs index fc8fcd9497..8f50d9b87c 100644 --- a/world/src/index.rs +++ b/world/src/index.rs @@ -9,7 +9,7 @@ use common::{ trade::{SiteId, SitePrices}, }; use core::ops::Deref; -use noise::{Fbm, Seedable, SuperSimplex, MultiFractal}; +use noise::{Fbm, MultiFractal, Seedable, SuperSimplex}; use std::sync::Arc; const WORLD_COLORS_MANIFEST: &str = "world.style.colors"; diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 76cd40eb8c..7a38467c43 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1,10 +1,8 @@ -use super::scatter::close; - use crate::{ site::SiteKind, util::{ - sampler::Sampler, FastNoise2d, RandomField, RandomPerm, SmallCache, StructureGen2d, - LOCALITY, SQUARE_4, + close_fast as close, sampler::Sampler, FastNoise2d, RandomField, RandomPerm, SmallCache, + StructureGen2d, LOCALITY, SQUARE_4, }, Canvas, CanvasInfo, ColumnSample, Land, }; @@ -16,7 +14,6 @@ use common::{ }, vol::RectVolSize, }; -use inline_tweak::tweak_fn; use itertools::Itertools; use noise::NoiseFn; use rand::prelude::*; @@ -27,10 +24,6 @@ use std::{ }; use vek::*; -fn close_fast(x: f32, tgt: f32, falloff: f32, falloff_strength: i32) -> f32 { - (1.0 - ((x - tgt) / falloff).powi(falloff_strength * 2)).max(0.0) -} - const CELL_SIZE: i32 = 1536; #[derive(Copy, Clone)] @@ -122,7 +115,6 @@ impl Tunnel { } } - #[tweak_fn] fn z_range_at( &self, wposf: Vec2, @@ -182,7 +174,6 @@ impl Tunnel { } } - #[inline_tweak::tweak_fn] fn biome_at(&self, wpos: Vec3, info: &CanvasInfo) -> Biome { let Some(col) = info.col_or_gen(wpos.xy()) else { return Biome::default(); @@ -242,37 +233,38 @@ impl Tunnel { // Mushrooms grow underground and thrive in a humid environment with moderate // temperatures let mushroom = underground - * close(humidity, 1.0, 0.7) - * close(temp, 1.5, 0.9) - * close(depth, 1.0, 0.6); + * close(humidity, 1.0, 0.7, 3) + * close(temp, 1.5, 0.9, 3) + * close(depth, 1.0, 0.6, 3); // Extremely hot and dry areas deep underground let fire = underground - * close(humidity, 0.0, 0.6) - * close(temp, 2.0, 1.3) - * close(depth, 1.0, 0.5); + * close(humidity, 0.0, 0.6, 3) + * close(temp, 2.0, 1.3, 3) + * close(depth, 1.0, 0.55, 3); // Overgrown with plants that need a moderate climate to survive let leafy = underground - * close(humidity, 0.8, 0.8) - * close(temp, 0.95, 0.85) - * close(depth, 0.0, 0.6); + * close(humidity, 0.8, 0.8, 3) + * close(temp, 0.95, 0.85, 3) + * close(depth, 0.0, 0.6, 3); // Cool temperature, dry and devoid of value - let dusty = close(humidity, 0.0, 0.5) * close(temp, -0.1, 0.6); + let dusty = close(humidity, 0.0, 0.5, 3) * close(temp, -0.1, 0.6, 3); // Deep underground and freezing cold let icy = underground - * close(temp, -1.5, 1.3) - * close(depth, 1.0, 0.65) - * close(humidity, 1.0, 0.7); + * close(temp, -1.5, 1.3, 3) + * close(depth, 1.0, 0.65, 3) + * close(humidity, 1.0, 0.7, 3); // Rocky cold cave that appear near the surface - let snowy = close(temp, -0.5, 0.3) * close(depth, 0.0, 0.4); + let snowy = close(temp, -0.6, 0.5, 3) * close(depth, 0.0, 0.45, 3); // Crystals grow deep underground in areas rich with minerals. They are present // in areas with colder temperatures and low humidity let crystal = underground - * close(humidity, 0.0, 0.5) - * close(temp, -0.6, 0.75) - * close(depth, 1.0, 0.55) - * close(mineral, 1.5, 1.0); + * close(humidity, 0.0, 0.5, 3) + * close(temp, -0.6, 0.75, 3) + * close(depth, 1.0, 0.55, 3) + * close(mineral, 2.0, 1.25, 3); // Hot, dry and shallow - let sandy = close(humidity, 0.0, 0.3) * close(temp, 0.7, 0.9) * close(depth, 0.0, 0.6); + let sandy = + close(humidity, 0.0, 0.3, 3) * close(temp, 0.7, 0.9, 3) * close(depth, 0.0, 0.6, 3); let biomes = [ barren, mushroom, fire, leafy, dusty, icy, snowy, crystal, sandy, @@ -543,7 +535,6 @@ struct Flower { // rotation: Mat3, } -#[inline_tweak::tweak_fn] fn write_column( canvas: &mut Canvas, col: &ColumnSample, @@ -652,7 +643,7 @@ fn write_column( .mul(width_factor) .mul( (0.75 * dist_cave_center) - + max_height * (close(dist_cave_center, cave_width, cave_width * 0.7)), + + max_height * (close(dist_cave_center, cave_width, cave_width * 0.7, 3)), ) .mul(((col.alt - z_range.end as f32) / 64.0).clamped(0.0, 1.0)); @@ -767,125 +758,117 @@ fn write_column( } if biome.mushroom > 0.7 - && vertical > 16.0 - && rng.gen_bool( - 0.5 * close_fast(vertical, MAX_RADIUS, MAX_RADIUS - 16.0, 2) as f64 - * close_fast(biome.mushroom, 1.0, 0.7, 1) as f64, - ) - { - let purp = rng.gen_range(0..50); - Some(CaveStructure::Mushroom(Mushroom { - pos, - stalk: 8.0 - + rng.gen::().powf(2.0) - * (z_range.end - z_range.start - 8) as f32 - * 0.75, - head_color: Rgb::new( - 40 + purp, - rng.gen_range(60..120), - rng.gen_range(80..200) + purp, - ), - })) - } else if biome.crystal > 0.5 - && rng.gen_bool(0.4 * close_fast(biome.crystal, 1.0, 0.7, 2) as f64) - { - let on_ground = rng.gen_bool(0.6); - let pos = wpos2d.with_z(if on_ground { - z_range.start - } else { - z_range.end - }); - - let mut crystals: Vec = Vec::new(); - let max_length = - (48.0 * close_fast(vertical, MAX_RADIUS, MAX_RADIUS, 1)).max(12.0); - let length = rng.gen_range(8.0..max_length); - let radius = Lerp::lerp( - 2.0, - 4.5, - length / max_length + rng.gen_range(-0.1..0.1), - ); - let dir = Vec3::new( - rng.gen_range(-3.0..3.0), - rng.gen_range(-3.0..3.0), - rng.gen_range(0.5..10.0) * if on_ground { 1.0 } else { -1.0 }, - ) - .normalized(); - - crystals.push(Crystal { - dir, - length, - radius, - }); - - (0..4).for_each(|_| { - crystals.push(Crystal { - dir: Vec3::new( - rng.gen_range(-1.0..1.0), - rng.gen_range(-1.0..1.0), - (dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), - ), - length: length * rng.gen_range(0.3..0.8), - radius: (radius * rng.gen_range(0.5..0.8)).max(1.0), - }); - }); - - let purple = rng.gen_range(25..75); - let blue = (rng.gen_range(45.0..75.0) * biome.icy) as u8; - - Some(CaveStructure::Crystal(CrystalCluster { - pos, - crystals, - color: Rgb::new( - 255 - blue * 2, - 255 - blue - purple, - 200 + rng.gen_range(25..55), - ), - })) - } else if biome.leafy > 0.8 - && vertical > 16.0 - && horizontal > 8.0 - && rng.gen_bool( - 0.25 * (close_fast(vertical, MAX_RADIUS, MAX_RADIUS - 16.0, 2) - * close_fast(horizontal, MAX_RADIUS, MAX_RADIUS - 8.0, 2) - * biome.leafy) as f64, - ) - { - let petal_radius = rng.gen_range(8.0..16.0); - Some(CaveStructure::Flower(Flower { - pos, - stalk: 6.0 - + rng.gen::().powf(2.0) - * (z_range.end - z_range.start - 8) as f32 - * 0.75, - petals: rng.gen_range(1..5) * 2 + 1, - petal_height: 0.4 - * petal_radius - * (1.0 + rng.gen::().powf(2.0)), - petal_radius, - })) - } else if (biome.leafy > 0.7 || giant_tree_factor > 0.0) - && rng.gen_bool( - (0.5 * close_fast(biome.leafy, 1.0, 0.5, 1) - .max(1.0 + giant_tree_factor) - as f64) - .clamped(0.0, 1.0), - ) - { - Some(CaveStructure::GiantRoot { - pos, - radius: rng.gen_range( - 1.5..(3.5 - + close_fast(vertical, MAX_RADIUS, MAX_RADIUS / 2.0, 2) - * 3.0 - + close_fast(horizontal, MAX_RADIUS, MAX_RADIUS / 2.0, 2) - * 3.0), - ), - height: (z_range.end - z_range.start) as f32, - }) + && vertical > 16.0 + && rng.gen_bool( + 0.5 * close(vertical, MAX_RADIUS, MAX_RADIUS - 16.0, 2) as f64 + * close(biome.mushroom, 1.0, 0.7, 1) as f64, + ) + { + let purp = rng.gen_range(0..50); + Some(CaveStructure::Mushroom(Mushroom { + pos, + stalk: 8.0 + + rng.gen::().powf(2.0) + * (z_range.end - z_range.start - 8) as f32 + * 0.75, + head_color: Rgb::new( + 40 + purp, + rng.gen_range(60..120), + rng.gen_range(80..200) + purp, + ), + })) + } else if biome.crystal > 0.5 + && rng.gen_bool(0.4 * close(biome.crystal, 1.0, 0.7, 2) as f64) + { + let on_ground = rng.gen_bool(0.6); + let pos = wpos2d.with_z(if on_ground { + z_range.start } else { - None - } + z_range.end + }); + + let mut crystals: Vec = Vec::new(); + let max_length = + (48.0 * close(vertical, MAX_RADIUS, MAX_RADIUS, 1)).max(12.0); + let length = rng.gen_range(8.0..max_length); + let radius = + Lerp::lerp(2.0, 4.5, length / max_length + rng.gen_range(-0.1..0.1)); + let dir = Vec3::new( + rng.gen_range(-3.0..3.0), + rng.gen_range(-3.0..3.0), + rng.gen_range(0.5..10.0) * if on_ground { 1.0 } else { -1.0 }, + ) + .normalized(); + + crystals.push(Crystal { + dir, + length, + radius, + }); + + (0..4).for_each(|_| { + crystals.push(Crystal { + dir: Vec3::new( + rng.gen_range(-1.0..1.0), + rng.gen_range(-1.0..1.0), + (dir.z + rng.gen_range(-0.2..0.2)).clamped(0.0, 1.0), + ), + length: length * rng.gen_range(0.3..0.8), + radius: (radius * rng.gen_range(0.5..0.8)).max(1.0), + }); + }); + + let purple = rng.gen_range(25..75); + let blue = (rng.gen_range(45.0..75.0) * biome.icy) as u8; + + Some(CaveStructure::Crystal(CrystalCluster { + pos, + crystals, + color: Rgb::new( + 255 - blue * 2, + 255 - blue - purple, + 200 + rng.gen_range(25..55), + ), + })) + } else if biome.leafy > 0.8 + && vertical > 16.0 + && horizontal > 8.0 + && rng.gen_bool( + 0.25 * (close(vertical, MAX_RADIUS, MAX_RADIUS - 16.0, 2) + * close(horizontal, MAX_RADIUS, MAX_RADIUS - 8.0, 2) + * biome.leafy) as f64, + ) + { + let petal_radius = rng.gen_range(8.0..16.0); + Some(CaveStructure::Flower(Flower { + pos, + stalk: 6.0 + + rng.gen::().powf(2.0) + * (z_range.end - z_range.start - 8) as f32 + * 0.75, + petals: rng.gen_range(1..5) * 2 + 1, + petal_height: 0.4 * petal_radius * (1.0 + rng.gen::().powf(2.0)), + petal_radius, + })) + } else if (biome.leafy > 0.7 || giant_tree_factor > 0.0) + && rng.gen_bool( + (0.5 * close(biome.leafy, 1.0, 0.5, 1).max(1.0 + giant_tree_factor) + as f64) + .clamped(0.0, 1.0), + ) + { + Some(CaveStructure::GiantRoot { + pos, + radius: rng.gen_range( + 1.5..(3.5 + + close(vertical, MAX_RADIUS, MAX_RADIUS / 2.0, 2) * 3.0 + + close(horizontal, MAX_RADIUS, MAX_RADIUS / 2.0, 2) * 3.0), + ), + height: (z_range.end - z_range.start) as f32, + }) + } else { + None + } }) { structure } else { @@ -1073,8 +1056,8 @@ fn write_column( .atan2(rpos.y) .rem_euclid(std::f32::consts::TAU / flower.petals as f32); if dist_ratio < 0.175 { - let red = close_fast(near, 0.0, 0.5, 1); - let purple = close_fast(near, 0.0, 0.35, 1); + let red = close(near, 0.0, 0.5, 1); + let purple = close(near, 0.0, 0.35, 1); if dist_ratio > red || rpos.z < petal_height_at { return Some(Block::new( BlockKind::ArtLeaves, @@ -1092,8 +1075,7 @@ fn write_column( )); } } else { - let inset = close_fast(near, -1.0, 1.0, 2) - .max(close_fast(near, 1.0, 1.0, 2)); + let inset = close(near, -1.0, 1.0, 2).max(close(near, 1.0, 1.0, 2)); if dist_ratio < inset { return Some(Block::new( BlockKind::ArtLeaves, @@ -1336,7 +1318,7 @@ fn write_column( } else if biome.fire.max(biome.snowy) > 0.5 { BlockKind::Rock } else if biome.crystal > 0.5 { - if rand.chance(wpos, biome.crystal * 0.05) { + if rand.chance(wpos, biome.crystal * 0.02) { BlockKind::GlowingRock } else { BlockKind::Rock @@ -1502,8 +1484,8 @@ fn write_column( .ok() .and_then(|s| s.0) } else if rand.chance(wpos2d.with_z(7), 0.01) { - let shallow = close(biome.depth, 0.0, 0.4); - let middle = close(biome.depth, 0.5, 0.4); + let shallow = close(biome.depth, 0.0, 0.4, 3); + let middle = close(biome.depth, 0.5, 0.4, 3); //let deep = close(biome.depth, 1.0, 0.4); // TODO: Use this for deep only // things [ @@ -1570,7 +1552,7 @@ fn write_column( } } } -#[tweak_fn] + fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Biome, rng: &mut R) { if RandomField::new(canvas.info().index().seed).chance(wpos, 0.035) { if let Some(entity_asset) = [ @@ -1632,7 +1614,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio ( Some("common.entity.wild.peaceful.crawler_moss"), biome.leafy + 0.05, - 0.25, + 0.25, 0.5, ), ( @@ -1656,7 +1638,12 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Dusty biome ( Some("common.entity.wild.aggressive.dodarock"), - biome.dusty.max(biome.barren).max(biome.crystal).max(biome.snowy) + 0.05, + biome + .dusty + .max(biome.barren) + .max(biome.crystal) + .max(biome.snowy) + + 0.05, 0.05, 0.5, ), @@ -1697,18 +1684,18 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.02, 0.5, ), - ( + ( Some("common.entity.wild.aggressive.frostfang"), biome.icy + 0.0, - 0.25, + 0.25, 0.5, - ), + ), ( Some("common.entity.wild.aggressive.tursus"), biome.icy + 0.0, - 0.03, + 0.03, 0.5, - ), + ), // Lava biome ( Some("common.entity.wild.aggressive.lavadrake"), @@ -1726,8 +1713,8 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio Some("common.entity.wild.aggressive.cave_salamander"), biome.fire + 0.0, 0.5, - 0.5, - ), + 0.5, + ), ( Some("common.entity.wild.aggressive.red_oni"), biome.fire + 0.0, @@ -1741,12 +1728,12 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.1, 0.5, ), - ( + ( Some("common.entity.wild.aggressive.blue_oni"), biome.crystal + 0.0, - 0.03, + 0.03, 0.5, - ), + ), // Sandy biome ( Some("common.entity.wild.aggressive.antlion"), @@ -1760,12 +1747,12 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.025, 0.5, ), - ( + ( Some("common.entity.wild.peaceful.crawler_sand"), biome.sandy + 0.1, - 0.25, + 0.25, 0.5, - ), + ), // Snowy biome ( Some("common.entity.wild.aggressive.akhlut"), @@ -1797,7 +1784,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio .iter() .filter_map(|(entity, biome_modifier, chance, cutoff)| { if let Some(entity) = entity { - let close = close_fast(1.0, *biome_modifier, *cutoff, 2); + let close = close(1.0, *biome_modifier, *cutoff, 2); (close > 0.0).then(|| (Some(entity), close * chance)) } else { Some((None, 100.0)) diff --git a/world/src/layer/scatter.rs b/world/src/layer/scatter.rs index 52c33d2a68..136b506b9d 100644 --- a/world/src/layer/scatter.rs +++ b/world/src/layer/scatter.rs @@ -1,4 +1,9 @@ -use crate::{column::ColumnSample, sim::SimChunk, util::RandomField, Canvas, CONFIG}; +use crate::{ + column::ColumnSample, + sim::SimChunk, + util::{close, RandomField}, + Canvas, CONFIG, +}; use common::{ calendar::{Calendar, CalendarEvent}, terrain::{Block, BlockKind, SpriteKind}, @@ -9,10 +14,6 @@ use rand::prelude::*; use std::f32; use vek::*; -pub fn close(x: f32, tgt: f32, falloff: f32) -> f32 { - (1.0 - (x - tgt).abs() / falloff).max(0.0).powf(0.125) -} - /// Returns a decimal value between 0 and 1. /// The density is maximum at the middle of the highest and the lowest allowed /// altitudes, and zero otherwise. Quadratic curve. diff --git a/world/src/layer/wildlife.rs b/world/src/layer/wildlife.rs index be8dd74c10..d4fced8b85 100644 --- a/world/src/layer/wildlife.rs +++ b/world/src/layer/wildlife.rs @@ -1,4 +1,4 @@ -use crate::{column::ColumnSample, sim::SimChunk, IndexRef, CONFIG}; +use crate::{column::ColumnSample, sim::SimChunk, util::close, IndexRef, CONFIG}; use common::{ assets::{self, AssetExt}, calendar::{Calendar, CalendarEvent}, @@ -17,10 +17,6 @@ type Weight = u32; type Min = u8; type Max = u8; -fn close(x: f32, tgt: f32, falloff: f32) -> f32 { - (1.0 - (x - tgt).abs() / falloff).max(0.0).powf(0.125) -} - #[derive(Clone, Debug, Deserialize)] pub struct SpawnEntry { /// User-facing info for wiki, statistical tools, etc. diff --git a/world/src/site2/plot/bridge.rs b/world/src/site2/plot/bridge.rs index 4687706df8..e6f281effb 100644 --- a/world/src/site2/plot/bridge.rs +++ b/world/src/site2/plot/bridge.rs @@ -8,8 +8,6 @@ use num::integer::Roots; use rand::prelude::*; use vek::*; -use inline_tweak::tweak; - enum RoofKind { Crenelated, Hipped, @@ -618,7 +616,7 @@ fn render_tower(bridge: &Bridge, painter: &Painter, roof_kind: &RoofKind) { .fill(rock.clone()); let offset = tower_size * 2 - 2; - let d = tweak!(2); + let d = 2; let n = (bridge.end.z - bridge.start.z - d) / offset; let p = (bridge.end.z - bridge.start.z - d) / n; diff --git a/world/src/util/mod.rs b/world/src/util/mod.rs index 66fe6f4571..bad938ec35 100644 --- a/world/src/util/mod.rs +++ b/world/src/util/mod.rs @@ -36,6 +36,14 @@ pub fn attempt(max_iters: usize, mut f: impl FnMut() -> Option) -> Option< (0..max_iters).find_map(|_| f()) } +pub fn close(x: f32, tgt: f32, falloff: f32) -> f32 { + (1.0 - (x - tgt).abs() / falloff).max(0.0).powf(0.125) +} + +pub fn close_fast(x: f32, tgt: f32, falloff: f32, falloff_strength: i32) -> f32 { + (1.0 - ((x - tgt) / falloff).powi(falloff_strength * 2)).max(0.0) +} + pub const CARDINALS: [Vec2; 4] = [ Vec2::new(0, 1), Vec2::new(1, 0), From 0836184bbc5e4787b419f6b3bb93de48cb628bb3 Mon Sep 17 00:00:00 2001 From: Syniis Date: Sat, 24 Feb 2024 23:30:05 +0100 Subject: [PATCH 21/24] Fix issue making akhlut unable to spawn --- world/src/layer/cave.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 7a38467c43..ef5c2c931c 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1756,7 +1756,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio // Snowy biome ( Some("common.entity.wild.aggressive.akhlut"), - (biome.snowy.max(biome.icy) + 0.1) * 0.03, + (biome.snowy.max(biome.icy) + 0.1), 0.05, 0.5, ), From 41ccb873edad38413fae29eb5f5f38958c7f016b Mon Sep 17 00:00:00 2001 From: Syniis Date: Sat, 24 Feb 2024 23:49:21 +0100 Subject: [PATCH 22/24] Changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68eea077e3..8e975696b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Autumn Forests, Cherry Blossom Forests, and Maple Trees. - Added reworked dungeon: Haniwa Catacombs - Added dungeon: Terracotta Ruins +- Sand and crystal cave biome ### Changed @@ -92,6 +93,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Sword Changes; Pommel Strike has been nerfed -> increased energy cost, increased _durations, and decreased poise damage. Heavy Sweep has been nerfed -> decreased poise damage and stun vulnerability damage. Pillar Thrust has been altered -> decreased maximum base damage with an increase in stun vulnerability damage. - Weapons block are based on poise - Wooden Shield recipe +- Overhauled the visuals of several cave biomes ### Removed - Medium and large potions from all loot tables From 2f051f9c6a0383ad7672b50b48af90abe6ad7ba2 Mon Sep 17 00:00:00 2001 From: Syniis Date: Sun, 25 Feb 2024 14:58:07 +0100 Subject: [PATCH 23/24] Fix bat entity path --- world/src/layer/cave.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index ef5c2c931c..578764bff6 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1570,7 +1570,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.5, ), ( - Some("common.entity.wild.aggressive.bat"), + Some("common.entity.wild.peaceful.bat"), biome.mushroom + 0.1, 0.25, 0.5, @@ -1630,7 +1630,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.5, ), ( - Some("common.entity.wild.aggressive.bat"), + Some("common.entity.wild.peaceful.bat"), biome.leafy + 0.1, 0.25, 0.5, @@ -1666,7 +1666,7 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio 0.5, ), ( - Some("common.entity.wild.aggressive.bat"), + Some("common.entity.wild.peaceful.bat"), biome.dusty.max(biome.sandy).max(biome.snowy) + 0.1, 0.25, 0.5, @@ -1784,8 +1784,12 @@ fn apply_entity_spawns(canvas: &mut Canvas, wpos: Vec3, biome: &Bio .iter() .filter_map(|(entity, biome_modifier, chance, cutoff)| { if let Some(entity) = entity { - let close = close(1.0, *biome_modifier, *cutoff, 2); - (close > 0.0).then(|| (Some(entity), close * chance)) + if *biome_modifier > *cutoff { + let close = close(1.0, *biome_modifier, *cutoff, 2); + (close > 0.0).then(|| (Some(entity), close * chance)) + } else { + None + } } else { Some((None, 100.0)) } From 50905aebfe748f6e0268efcf9229c6a3dd9bf2fd Mon Sep 17 00:00:00 2001 From: Syniis Date: Tue, 27 Feb 2024 18:12:36 +0100 Subject: [PATCH 24/24] Mushroom spore particles --- .cargo/config | 2 +- assets/voxygen/shaders/particle-vert.glsl | 13 +++++++++++++ voxygen/src/render/pipelines/particle.rs | 1 + voxygen/src/scene/particle.rs | 8 ++++++++ voxygen/src/scene/terrain/watcher.rs | 6 ++++++ world/src/layer/cave.rs | 18 ++++++++++++------ 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/.cargo/config b/.cargo/config index 87d684cbbf..e78c87c91f 100644 --- a/.cargo/config +++ b/.cargo/config @@ -25,7 +25,7 @@ tracy-server-debuginfo = "run --bin veloren-server-cli --features tracy,simd --p tracy-server-releasedebuginfo = "run --bin veloren-server-cli --features tracy,simd --profile releasedebuginfo" tracy-test-server = "run --bin veloren-server-cli --no-default-features --features tracy,simd --profile no_overflow" # voxygen -test-voxygen = "run --bin veloren-voxygen --no-default-features --features simd,egui-ui,shaderc-from-source" +test-voxygen = "run --bin veloren-voxygen --no-default-features --features simd,egui-ui,shaderc-from-source,hot-reloading" tracy-voxygen = "run --bin veloren-voxygen --no-default-features --features tracy,simd,egui-ui,shaderc-from-source --profile no_overflow" dbg-voxygen = "run --bin veloren-voxygen --profile debuginfo" # misc diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index 1eb5b25819..9cd475eae1 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -96,6 +96,7 @@ const int PHOENIX_BEAM = 56; const int PHOENIX_BUILD_UP_AIM = 57; const int CLAY_SHRAPNEL = 58; const int AIRFLOW = 59; +const int SPORE = 60; // meters per second squared (acceleration) const float earth_gravity = 9.807; @@ -1016,6 +1017,18 @@ void main() { spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0) ); break; + case SPORE: + f_reflect = 0.0; + attr = Attr( + linear_motion( + vec3(0), + vec3(0, 0, -1.1) + ) + vec3(sin((lifetime + rand9 * 0.1) * 0.5) * 3.0, sin((lifetime+ rand8 * 0.1) * 0.5) * 3.0, sin(lifetime * 0.5) * 1.5), + vec3(0.4 + 0.4 * abs(sin(lifetime))), + vec4(vec3(0.8, 6.0 + rand6 * 1.75, 7.5 + (1.75 + rand5 * 0.5)), 1), + spin_in_axis(vec3(rand1, rand2, rand3), rand4 * 1.5 + lifetime) + ); + break; default: attr = Attr( linear_motion( diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 9fd14f365f..cecd1fe823 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -111,6 +111,7 @@ pub enum ParticleMode { PhoenixBuildUpAim = 57, ClayShrapnel = 58, Airflow = 59, + Spore = 60, } impl ParticleMode { diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 498f9cc1bd..f24f7b76f9 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -2186,6 +2186,14 @@ impl ParticleMgr { mode: ParticleMode::PortalFizz, cond: |_| true, }, + BlockParticles { + blocks: |boi| BlockParticleSlice::Positions(&boi.spores), + range: 4, + rate: 0.055, + lifetime: 20.0, + mode: ParticleMode::Spore, + cond: |_| true, + }, ]; let ecs = scene_data.state.ecs(); diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 8a4080274f..1dcd37a369 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -49,6 +49,7 @@ pub struct BlocksOfInterest { pub flowers: Vec>, pub fire_bowls: Vec>, pub snow: Vec>, + pub spores: Vec>, //This is so crickets stay in place and don't randomly change sounds pub cricket1: Vec>, pub cricket2: Vec>, @@ -97,6 +98,7 @@ impl BlocksOfInterest { let mut cricket3 = Vec::new(); let mut frogs = Vec::new(); let mut one_way_walls = Vec::new(); + let mut spores = Vec::new(); let mut rng = ChaCha8Rng::from_seed(thread_rng().gen()); @@ -138,6 +140,7 @@ impl BlocksOfInterest { lavapool.push(pos) } }, + BlockKind::GlowingMushroom if rng.gen_range(0..8) == 0 => spores.push(pos), BlockKind::Snow | BlockKind::Ice if rng.gen_range(0..16) == 0 => snow.push(pos), _ => { if let Some(sprite) = block.get_sprite() { @@ -225,6 +228,8 @@ impl BlocksOfInterest { SpriteKind::Sign | SpriteKind::HangingSign => { interactables.push((pos, Interaction::Read)) }, + SpriteKind::MycelBlue => spores.push(pos), + SpriteKind::Mold => spores.push(pos), _ => {}, } } @@ -268,6 +273,7 @@ impl BlocksOfInterest { flowers, fire_bowls, snow, + spores, cricket1, cricket2, cricket3, diff --git a/world/src/layer/cave.rs b/world/src/layer/cave.rs index 578764bff6..a7ce750ff9 100644 --- a/world/src/layer/cave.rs +++ b/world/src/layer/cave.rs @@ -1216,20 +1216,26 @@ fn write_column( BlockKind::Sand } else if rand.chance(wpos, biome.leafy) { BlockKind::ArtLeaves + } else if ceiling_cover > 0.0 { + BlockKind::Rock } else { BlockKind::WeakRock }, stalactite.map(|e| e as u8), ) } else if z < ceiling && z >= ceiling_drip { - let color = if biome.mushroom > 0.9 { - Rgb::new(10, 70, 148) + if biome.mushroom > 0.9 { + let block = if rand.chance(wpos2d.with_z(89), 0.05) { + BlockKind::GlowingMushroom + } else { + BlockKind::GlowingWeakRock + }; + Block::new(block, Rgb::new(10, 70, 148)) } else if biome.icy > 0.9 { - Rgb::new(120, 140, 255) + Block::new(BlockKind::GlowingWeakRock, Rgb::new(120, 140, 255)) } else { - Rgb::new(80, 100, 150) - }; - Block::new(BlockKind::GlowingRock, color) + Block::new(BlockKind::WeakRock, Rgb::new(80, 100, 150)) + } } else if z >= base && z < floor && !void_below && !sky_above { let (net_col, total) = [ (