Feat/layered water beds underwater vegetation#1102
Conversation
Port two water-rendering features from the Teddy fork into the in-process carve path, isolated from the fork's dune/puddle/bridge/mossy-shore work. Layered beds: replace the SAND/GRAVEL depth-drift bed with a GRAVEL background carrying domain-warped, per-block noise patches of SAND/CLAY/DIRT/COARSE_DIRT plus rare deep MAGMA_BLOCK/SOUL_SAND, over a STONE base with a short STONE backfill so side faces never expose AIR. Underwater vegetation: seagrass meadows (SEAGRASS / TALL_SEAGRASS / SEA_PICKLE) gated by two decorrelated noise fields, with rarer KELP columns in deeper water; all painted into AIR only so the bed is never overwritten. Both are pure functions of (x, z), so output stays tile-independent. Adds 8 block definitions; the block id field widens u8 -> u16 (we had only 3 free u8 slots). Palette LUT and stair-cache key widen to match. Luanti/Mineclonia node arms added for the new blocks. Co-authored-by: Teddy563 <real@teddy.bar>
Port the fork's width-aware underwater dunes and the bridge-zone water fix, both wired to add no extra memory and little generation time. Dunes: rolling 1-4 block mounds of the bed material, domain-warped and multi-octave. Amplitude comes from the cell's own depth instead of the fork's 7x7 body-width sample; the depth cap makes that exact wherever it binds, so no neighbourhood scan and no extra field are needed. The placer returns its crest so vegetation plants on top without recomputing the dune noise (the fork sampled it twice). Bridge fix: cells in the 5x5 ring around a road get a plain bed with no blobs, dunes or veg, so nothing grows into the piers. The ring scan is skipped entirely when the road mask is empty and only runs for depth >= 2. Also samples the bed palette noise lazily so shallow cells skip the rare magma/soul tiers. Co-authored-by: Teddy563 <real@teddy.bar>
Add a 20s connect timeout to the fixed-tile HTTP client and drop the per-request total from 180s to 90s. A single tile is only a few MB, so a stalled connection now trips the retry quickly instead of hanging up to three minutes, which matters most on unstable links and large bboxes.
|
⏱️ Benchmark run finished in 0m 58s 📈 Compared against baseline: 18s time, 1005 MB memory 🟢 Generation time is unchanged. 📅 Last benchmark: 2026-06-15 21:33:02 UTC You can retrigger the benchmark by commenting |
There was a problem hiding this comment.
Pull request overview
This PR enhances underwater terrain generation by introducing layered seabeds, dunes, and underwater vegetation placement, and expands the block ID space to support additional underwater-related blocks.
Changes:
- Expand
BlockIDs fromu8tou16and add new underwater/vegetation block definitions. - Extend water carving to generate layered beds, dune bumps, and vegetation while respecting nearby bridges/roads.
- Update downstream integrations (Luanti mapping, tests, HTTP client timeouts) to align with new blocks and behaviors.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/world_editor/common.rs |
Updates palette construction logic for full sections to use block IDs directly. |
src/water_depth.rs |
Adds layered beds, dunes, vegetation, and bridge-adjacent suppression; updates call sites and adds tests. |
src/models_3d/wikidata/placement.rs |
Adjusts test helper for widened block ID type. |
src/luanti_block_map.rs |
Maps new underwater block IDs to Mineclonia/Luanti nodes. |
src/elevation/providers/fixed_tile.rs |
Tweaks HTTP client timeouts to fail faster on stalled connections. |
src/element_processing/water_areas.rs |
Passes road_mask into carve_water_column after signature change. |
src/block_definitions.rs |
Widens Block ID type and adds new underwater/vegetation block constants + NBT properties. |
Comments suppressed due to low confidence (2)
src/world_editor/common.rs:270
block_to_paletteis a fixed-size array indexed byBlock::id()(nowu16). This will panic if any block id >= 512 is ever introduced (which is more likely now that ids are no longer capped atu8). Consider switching to a dynamically-sized Vec (resizing on demand) to keep the fast O(1) lookup without a hard-coded upper bound.
// Build palette from unique blocks; array indexed by block id (u16, see block_definitions).
let mut block_to_palette = [u16::MAX; 512];
let mut palette_blocks: Vec<Block> = Vec::new();
for &block in blocks.iter() {
let id = block.id() as usize;
if block_to_palette[id] == u16::MAX {
block_to_palette[id] = palette_blocks.len() as u16;
src/block_definitions.rs:364
- This comment is now outdated: block IDs have already been widened to
u16and this file defines blocks above 255 (e.g. 256, 265). Please update the guidance so it doesn’t imply IDs must stay < 255.
265 => "soul_sand",
_ => panic!("Invalid id"),
}
// Note: If you want to add more blocks, please find unused ID
// slots below 255 so we don't need to update to u16 or higher.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Widening Block to u16 doubled every Full section's backing Vec, which the benchmark caught as a ~70% peak-memory jump on a dense city. Split section storage into Full(Vec<u8>) for the common case where every id fits in a byte and FullWide(Vec<Block>) only for sections that actually hold an id of 256 or more (the rare underwater blocks). Reads, writes, iteration, the content hash and serialization stay representation-independent. Also reword the bridge_adjacent doc/test to say 5x5 area, not ring, per review feedback.
Add a unit test for the Full -> FullWide upgrade and wide-id round-trip, and name the palette lookup bound (MAX_BLOCK_ID) with a debug assert so a future block id past it fails loudly instead of indexing out of bounds.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/block_definitions.rs:370
- The note below the
Block::name()match still says to keep new IDs below 255 to avoid switching away fromu8, butBlockis now backed byu16and this PR adds IDs >= 256. This comment is now misleading and should be updated to reflect the real constraint (keeping IDs < 256 avoids wide section storage / larger palette lookups).
// Note: If you want to add more blocks, please find unused ID
// slots below 255 so we don't need to update to u16 or higher.
No description provided.