mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-27 06:20:02 +00:00
Legacy hydrology tests on the v2 contract; water connects across steps
- Geometry pins became relational properties; tests for deleted mechanisms removed - Every owned channel water column is published to the mantle so steps get fluid updates - Upper beds at head steps reach the lower head so the water stays one body - Ocean aprons are measured from the first ocean station and bounded laterally - Dry cave headroom uses the flooded cave biome
This commit is contained in:
1 parent
3d96a8616a
commit
507e241b2c
12 files changed
+336
-692
No files matched your search
@@ -70,13 +70,13 @@ public record HydrologyColumnLayer(
|
||||
return surfaceBiomeKey;
|
||||
}
|
||||
|
||||
/** Every owned channel water column is published so steps between stations receive fluid updates. */
|
||||
public boolean publishesSurfaceFluid() {
|
||||
return feature.type().isSurface()
|
||||
&& !oceanApron
|
||||
&& channel
|
||||
&& fluidOwned
|
||||
&& (terrainOwned || fallingFluid)
|
||||
&& (feature.type().isDrop() || fallingFluid || receivingPool)
|
||||
&& fluidHeadY > bedY;
|
||||
}
|
||||
|
||||
|
||||
+43
-1
@@ -78,6 +78,7 @@ public final class ErosionFieldCompiler {
|
||||
}
|
||||
}
|
||||
}
|
||||
int oceanStart = oceanStart(centerline, valley, terminal);
|
||||
Long2ObjectOpenHashMap<SurfaceColumn> columns = new Long2ObjectOpenHashMap<>(nearest.size());
|
||||
LongArrayList wetKeys = new LongArrayList();
|
||||
for (long key : nearest.keySet()) {
|
||||
@@ -95,7 +96,8 @@ public final class ErosionFieldCompiler {
|
||||
if (!SurfaceCellAdmission.writable(terrain, seaLevel)) {
|
||||
if (terrain != null && wet && terminal == SurfaceTerminal.OCEAN_MOUTH
|
||||
&& station >= valley.exposedStations() - 1
|
||||
&& station - valley.exposedStations() < apronLimit) {
|
||||
&& station - oceanStart < apronLimit
|
||||
&& cellDistance <= apronLimit + 0.25D) {
|
||||
columns.put(key, new SurfaceColumn(
|
||||
cellX, cellZ, terrain, station, SurfaceRole.CHANNEL, terrain.naturalHeight(), seaLevel, true));
|
||||
}
|
||||
@@ -133,9 +135,34 @@ public final class ErosionFieldCompiler {
|
||||
columns.put(key, new SurfaceColumn(cellX, cellZ, terrain, station, SurfaceRole.BANK, height, height, false));
|
||||
}
|
||||
int uncontained = contain(columns, wetKeys, freeboard);
|
||||
connectSteps(columns, wetKeys);
|
||||
return new ErosionField(columns, uncontained);
|
||||
}
|
||||
|
||||
/**
|
||||
* Where the head steps down between neighbouring wet cells, the upper bed is lowered so its water
|
||||
* column reaches the lower head; the water stays one connected body across every step.
|
||||
*/
|
||||
private static void connectSteps(Long2ObjectOpenHashMap<SurfaceColumn> columns, LongArrayList wetKeys) {
|
||||
for (int index = 0; index < wetKeys.size(); index++) {
|
||||
long key = wetKeys.getLong(index);
|
||||
SurfaceColumn wet = columns.get(key);
|
||||
int bed = wet.height();
|
||||
for (int[] offset : CARDINALS) {
|
||||
SurfaceColumn neighbour = columns.get(RiverFootprint.pack(wet.x() + offset[0], wet.z() + offset[1]));
|
||||
if (neighbour == null || neighbour.role() != SurfaceRole.CHANNEL || neighbour.apron()) {
|
||||
continue;
|
||||
}
|
||||
if (neighbour.headY() < wet.headY()) {
|
||||
bed = Math.min(bed, neighbour.headY() - 1);
|
||||
}
|
||||
}
|
||||
if (bed < wet.height()) {
|
||||
columns.put(key, wet.withBed(bed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Every dry cell touching water, diagonals included, keeps the lip; only cardinal neighbours can
|
||||
* spill, so only they count as uncontained.
|
||||
@@ -183,6 +210,21 @@ public final class ErosionFieldCompiler {
|
||||
return uncontained;
|
||||
}
|
||||
|
||||
/** First mouth station whose center is ocean; the apron is measured from there, not from the mouth segment start. */
|
||||
private int oceanStart(SurfaceCenterline centerline, ValleyProfile valley, SurfaceTerminal terminal) {
|
||||
int count = centerline.size();
|
||||
if (terminal != SurfaceTerminal.OCEAN_MOUTH) {
|
||||
return count;
|
||||
}
|
||||
for (int station = Math.max(0, valley.exposedStations() - 1); station < count; station++) {
|
||||
HydrologyTerrainSample center = sampler.sample(centerline.x()[station], centerline.z()[station]);
|
||||
if (!SurfaceCellAdmission.writable(center, seaLevel)) {
|
||||
return station;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private boolean[] basins(ValleyProfile valley, ChannelProfile channel, int count) {
|
||||
boolean[] basin = new boolean[count];
|
||||
for (int station = 1; station < count; station++) {
|
||||
|
||||
@@ -19,7 +19,13 @@ public record SurfaceColumn(
|
||||
Objects.requireNonNull(role, "role");
|
||||
}
|
||||
|
||||
/** Dry columns sit at their own height; the head follows it. */
|
||||
public SurfaceColumn withHeight(int replacementHeight) {
|
||||
return new SurfaceColumn(x, z, terrain, station, role, replacementHeight, replacementHeight, apron);
|
||||
}
|
||||
|
||||
/** Wet columns keep their head; only the bed moves. */
|
||||
public SurfaceColumn withBed(int replacementBed) {
|
||||
return new SurfaceColumn(x, z, terrain, station, role, replacementBed, headY, apron);
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -325,11 +325,8 @@ public final class MantleHydrologyComponent extends IrisMantleComponent {
|
||||
throw new IllegalStateException("Accepted cave layer is absent from its containment plan at "
|
||||
+ position + ".");
|
||||
}
|
||||
String biomeKey = action == HydrologyCaveAction.DRY_AIR
|
||||
? layer.floodedCaveBiomeKey()
|
||||
: layer.floodedCaveBiomeKey();
|
||||
PlannedCell candidate = new PlannedCell(
|
||||
new HydrologyCaveCell(action, layer.profileKey(), biomeKey),
|
||||
new HydrologyCaveCell(action, layer.profileKey(), layer.floodedCaveBiomeKey()),
|
||||
layer.feature().courseId()
|
||||
);
|
||||
mergeCaveCell(caveCells, position, candidate);
|
||||
|
||||
Reference in new issue
Block a user