feat(core): add water and lava fluid spread simulation

This commit is contained in:
dualfroz committed 2026-08-24 21:11:27 +02:00
1 parent 3293b96a64
commit 789ea3f934
2 files changed
+176

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include <cstdint>
#include <vector>
#include "World.h"
namespace vf {
constexpr uint8_t fluidMax = 8; // a full source cell; flow decays to 1 at the edge
// Cellular water automaton over a fixed world box. Levels run 0 (dry) to
// fluidMax. Source cells stay full every tick; flowing water spreads to lower
// horizontal neighbours losing one level per step, and pours straight down a
// gap filling the cell below fully. Updates are double buffered, so a tick is a
// pure function of the previous state (deterministic). Solid world voxels block
// and support the flow.
class FluidSim {
public:
FluidSim(World& world, const Vec3i& origin, const Vec3i& dims);
void addSource(int gx, int gy, int gz);
void removeSource(int gx, int gy, int gz);
void setLevel(int gx, int gy, int gz, uint8_t level);
uint8_t level(int gx, int gy, int gz) const;
bool isSource(int gx, int gy, int gz) const;
bool isWater(int gx, int gy, int gz) const { return level(gx, gy, gz) > 0; }
// Advances one tick. Returns true if any cell changed.
bool step();
// Steps until stable or maxSteps reached. Returns the number of steps taken.
int settle(int maxSteps);
// Writes Block::Water into the world for every wet, currently-air cell.
void applyToWorld() const;
const Vec3i& regionOrigin() const { return origin; }
const Vec3i& regionDims() const { return dims; }
const std::vector<uint8_t>& levels() const { return level_; }
const std::vector<uint8_t>& sourceFlags() const { return source_; }
void loadRaw(const std::vector<uint8_t>& levels, const std::vector<uint8_t>& sources);
private:
int index(int lx, int ly, int lz) const { return (ly * dims.z + lz) * dims.x + lx; }
bool inBox(int lx, int ly, int lz) const;
bool solidWorld(int gx, int gy, int gz) const;
uint8_t levelLocal(int lx, int ly, int lz) const;
bool sourceLocal(int lx, int ly, int lz) const;
bool spreader(int lx, int ly, int lz) const;
uint8_t computeNext(int lx, int ly, int lz) const;
World& world;
Vec3i origin;
Vec3i dims;
std::vector<uint8_t> level_;
std::vector<uint8_t> source_;
};
} // namespace vf