Skip to content

Commit a7d4610

Browse files
committed
fix(water): consistent estimate ratio + memory-bounded size cap
- estimate_max_carve_depth uses the inclusive (world-1)/(grid-1) ratio, matching cover_class/grid_span_to_block_span, so it stays a safe upper bound instead of under-estimating the floor reserve. - Replace the u32-only guard with a cell cap that bounds the dt/depth/ visited allocations (and still keeps u32 indices valid); render flat water above it instead of risking OOM.
1 parent dd87442 commit a7d4610

1 file changed

Lines changed: 9 additions & 7 deletions

File tree

src/water_depth.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const DT_MAX: u8 = u8::MAX;
1616
/// Maximum water carve depth, in blocks (the deepest tier).
1717
const MAX_WATER_DEPTH: i32 = 6;
1818

19+
/// Cap on water sub-rect cells (bounds memory, keeps u32 indices valid); ~1000 km².
20+
const MAX_WATER_FIELD_CELLS: usize = 1_000_000_000;
21+
1922
#[inline]
2023
fn nibble_get(buf: &[u8], i: usize) -> u8 {
2124
let byte = buf[i >> 1];
@@ -126,9 +129,9 @@ pub fn compute_big_water_field(ground: &Ground, xzbbox: &XZBBox) -> BigWaterFiel
126129
let smax_z = (wmax_z + 1).min(max_z);
127130
let sw = (smax_x - smin_x + 1) as usize;
128131
let sh = (smax_z - smin_z + 1) as usize;
129-
// comp indexes cells as u32; on absurd sizes, render flat water instead of crashing.
132+
// Cap cells to bound memory; above it, render flat water instead of crashing.
130133
let total = match sw.checked_mul(sh) {
131-
Some(t) if t <= u32::MAX as usize => t,
134+
Some(t) if t <= MAX_WATER_FIELD_CELLS => t,
132135
_ => {
133136
eprintln!("Warning: water area too large for depth carving; rendering flat water");
134137
return BigWaterField::empty();
@@ -321,11 +324,10 @@ pub fn estimate_max_carve_depth(
321324
}
322325
chamfer_3_4_dt(&mut dt, gw, gh);
323326
let grid_max_dt = dt.iter().copied().max().unwrap_or(0);
324-
// Stretch grid DT to block units by the larger axis ratio (rounding up = safe).
325-
let ratio = (world_width as f64 / gw as f64)
326-
.max(world_height as f64 / gh as f64)
327-
.max(1.0);
328-
let block_max_dt = f64::from(grid_max_dt) * ratio;
327+
// Inclusive-span ratio, matching the grid<->block mapping elsewhere (safe upper bound).
328+
let wr = world_width.saturating_sub(1).max(1) as f64 / gw.saturating_sub(1).max(1) as f64;
329+
let hr = world_height.saturating_sub(1).max(1) as f64 / gh.saturating_sub(1).max(1) as f64;
330+
let block_max_dt = f64::from(grid_max_dt) * wr.max(hr).max(1.0);
329331
let comp_max = block_max_dt.min(f64::from(u16::MAX)) as u16;
330332
depth_from_dt(block_max_dt + 2.0, comp_max)
331333
}

0 commit comments

Comments
 (0)