Water overhaul: liquid simulation, flow physics, rendering, interaction#4
Conversation
- Liquid system: source/flowing water blocks, per-voxel level storage, bounded update queue (priority + normal lanes), Minetest-inspired flow rules (down-first, horizontal decay, renewable sources), cross-chunk updates, immediate priority burst on block edits for responsive flow. - Rendering: world-space UVs + animated surface texture, depth-write off (transparent best practice), no bottom/internal faces, partial-height flowing water with stepped shorelines. - Player: swim/buoyancy/drag, in-water + underwater detection. - Underwater: fog pull-in + DOM tint, lerped for stable surface crossings. - Interaction: raycast passes through water by default (Luanti-style), F4 liquid-targeting mode, break/place through water, liquid removal. - Debug: perf overlay liquid/target lines, console toggles for water sides/depth/animation/material plus liquid placement tools.
📋 SummaryNo linked issues (e.g., "Fixes #123") are mentioned in the PR description. This PR overhauls water from a static transparent block into a Minetest/Luanti-style liquid system: source/flowing block pair, per-voxel levels, a bounded priority+normal update queue, partial-height water meshing with world-space UVs, swim physics, an underwater fog/tint renderer, raycast-through-water targeting, and a suite of debug toggles/overlays. The implementation is large but well-organized, and both the game and website build and typecheck cleanly. 📌 Review Metadata
🔴 Critical Issues (Must Fix - Blocks Merge)None identified.
|
| Principle | Score | Notes |
|---|---|---|
| Single Responsibility | 8/10 | Liquid flow, rendering, and player physics are cleanly separated; World gains a few new responsibilities but keeps them well-scoped. |
| Open/Closed | 7/10 | New liquids require editing BLOCKS directly; meshing is reasonably open via liquidType/LiquidDef. |
| Liskov Substitution | 9/10 | getBlock(id) fallback to AIR keeps all consumers safe; new flowing block integrates without breaking existing lookups. |
| Interface Segregation | 8/10 | LiquidAccess is a narrow, testable surface; PerfSnapshot grows but remains a single snapshot object. |
| Dependency Inversion | 8/10 | Simulator depends on LiquidAccess, not World; Game still reaches into World internals for debug overlays. |
| Average | 8.0 |
🎯 Final Assessment
Overall Confidence Score: 75%
Confidence Breakdown:
- Code Quality: 80% (clean, well-commented, but some dead code/doc drift)
- Completeness: 70% (feature-complete, but claimed tests are missing and chunk-border edge cases need handling)
- Risk Level: 65% (large change touching meshing, physics, and simulation; border cases are the main risk)
- Test Coverage: 40% (no tests present despite PR claims)
Merge Readiness:
- All critical issues resolved
- SOLID average score >= 6.0
- Overall confidence >= 60%
- No security concerns
- Tests present and passing (if applicable)
Verdict:
MERGE WITH FIXES — The core implementation is solid, builds are clean, and the feature scope is impressive. Address the chunk-border liquid remesh/re-seed issues and either add the claimed tests or update the PR description before merging.
…/drag, tests - World: chunk unload now wakes the liquid simulator for neighbour border liquid cells (markDirty alone didn't recompute state; stale flow hung in air). - World: setLiquid marks neighbour chunks dirty on border edits (transparent water doesn't guarantee a lighting change to trigger remesh). - LiquidSimulator: tighten renewable support to solid/source below (was any non-floodable, which could create sources in flowing plumes). - Player: water horizontal drag is now dt-aware (pow(0.86, dt*60)) so swim feel is consistent across refresh rates. - LiquidSimulator: remove duplicate bestFeeder JSDoc; ChunkMesher: drop dead 'below' var; LiquidTypes: drop unused LiquidDebugMode type. - tests/: add liquid (8), raycast-through-water (5), responsiveness suites; wire 'bun run test'.
📋 SummaryNo linked issues are mentioned in the PR description. The previous review's feedback has been fully addressed in commit 📌 Review Metadata
🔴 Critical Issues (Must Fix - Blocks Merge)None identified. ✅ All previously reported critical issues have been resolved.
|
| Principle | Score | Notes |
|---|---|---|
| Single Responsibility | 8/10 | Liquid flow, rendering, and player physics remain cleanly separated; World coordinates them without absorbing simulator internals. |
| Open/Closed | 7/10 | New liquids still require editing BLOCKS, but the LiquidDef/liquidType hooks and LiquidAccess interface make extension straightforward. |
| Liskov Substitution | 9/10 | getBlock(id) fallback to AIR keeps all consumers safe; new flowing block integrates without breaking existing lookups. |
| Interface Segregation | 8/10 | LiquidAccess is a narrow, testable surface; PerfSnapshot grows but remains a single snapshot object. |
| Dependency Inversion | 8/10 | Simulator depends on LiquidAccess, not World; debug wiring in Game still reaches into World internals but is isolated to dev surface. |
| Average | 8.0 |
🎯 Final Assessment
Overall Confidence Score: 88%
Confidence Breakdown:
- Code Quality: 85% (clean, well-commented, one dead field remaining)
- Completeness: 90% (feature-complete, previous gaps addressed, tests present)
- Risk Level: 80% (large change, but simulation is bounded, convergent, and tested)
- Test Coverage: 85% (three focused suites covering flow rules, raycast behavior, and priority responsiveness)
Merge Readiness:
- All critical issues resolved
- SOLID average score >= 6.0
- Overall confidence >= 60%
- No security concerns
- Tests present and passing
Verdict:
MERGE — The previous review feedback has been comprehensively addressed, all builds and tests pass, and the water system is now well-tested and ready for integration.


Summary
A full voxel-water overhaul turning water from a visual surface into a real, Minetest/Luanti-inspired liquid system — plus a clean, responsive rendering and interaction pass.
Liquid system (
src/game/liquid/)liquidType+ sharedLiquidDef(range, viscosity, renewable, swimmable, fog).Chunk.levels), mirrors the lightingLightMap.Rendering (
ChunkMesher,WaterMaterial)Player & underwater (
Player,UnderwaterRenderer)Interaction (
BlockRaycaster,Player,Game)liquids=false) so you can mine/build underwater; F4 toggles liquid-targeting to select/remove water itself. Break/place through water wired into the liquid queue.Debug
liquid+targetlines (queue, priority queue, budget, ms-since-tick, writes, targeting mode).waterOpaque,waterDepth,waterSimple,waterSides,waterAnim,targetLiquids, plusplaceWater/removeWater/liquidBudget/liquid.Verification
tsc --noEmitclean;vite buildsucceeds.Notes
dist/couldn't be rebuilt here due to root-owned stale Docker artifacts (EACCES); code builds cleanly to a fresh outDir. Unrelated to this change.