mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-20 07:24:16 +00:00
Surface settings v2
- Replace hydraulics, ridge tunnel, branching and inset ranges with channel, banks, flow and mouth configs - Add routing cost weights, underground mouth leveling, bank biomes and bank multiplier - Map the new schema into planner settings and derive refinement spacing
This commit is contained in:
@@ -48,7 +48,7 @@ final class PackHydrologyValidator {
|
||||
"surfaceBiomes",
|
||||
"mouthBiomes",
|
||||
"shoreBiomes",
|
||||
"dryBiomes",
|
||||
"bankBiomes",
|
||||
"floodedCaveBiomes"
|
||||
);
|
||||
private static final List<String> REGION_BIOME_FIELDS = List.of(
|
||||
|
||||
@@ -20,7 +20,7 @@ public record HydrologyColumnLayer(
|
||||
String surfaceBiomeKey,
|
||||
String mouthBiomeKey,
|
||||
String shoreBiomeKey,
|
||||
String dryBiomeKey,
|
||||
String bankBiomeKey,
|
||||
String floodedCaveBiomeKey
|
||||
) {
|
||||
public HydrologyColumnLayer {
|
||||
@@ -29,7 +29,7 @@ public record HydrologyColumnLayer(
|
||||
surfaceBiomeKey = requireKey(surfaceBiomeKey, "surfaceBiomeKey");
|
||||
mouthBiomeKey = requireKey(mouthBiomeKey, "mouthBiomeKey");
|
||||
shoreBiomeKey = requireKey(shoreBiomeKey, "shoreBiomeKey");
|
||||
dryBiomeKey = requireKey(dryBiomeKey, "dryBiomeKey");
|
||||
bankBiomeKey = requireKey(bankBiomeKey, "bankBiomeKey");
|
||||
floodedCaveBiomeKey = requireKey(floodedCaveBiomeKey, "floodedCaveBiomeKey");
|
||||
if (channel && bedY > fluidHeadY) {
|
||||
throw new IllegalArgumentException("A channel bed cannot be above its fluid head.");
|
||||
|
||||
@@ -788,7 +788,7 @@ final class HydrologyFootprintCompiler {
|
||||
layer.surfaceBiomeKey(),
|
||||
layer.mouthBiomeKey(),
|
||||
layer.shoreBiomeKey(),
|
||||
layer.dryBiomeKey(),
|
||||
layer.bankBiomeKey(),
|
||||
layer.floodedCaveBiomeKey()
|
||||
);
|
||||
}
|
||||
@@ -2121,7 +2121,7 @@ final class HydrologyFootprintCompiler {
|
||||
layer.surfaceBiomeKey(),
|
||||
layer.mouthBiomeKey(),
|
||||
layer.shoreBiomeKey(),
|
||||
layer.dryBiomeKey(),
|
||||
layer.bankBiomeKey(),
|
||||
layer.floodedCaveBiomeKey()
|
||||
);
|
||||
}
|
||||
@@ -2232,7 +2232,7 @@ final class HydrologyFootprintCompiler {
|
||||
terrain.surfaceBiomeKey(),
|
||||
terrain.mouthBiomeKey(),
|
||||
terrain.shoreBiomeKey(),
|
||||
terrain.dryBiomeKey(),
|
||||
terrain.bankBiomeKey(),
|
||||
terrain.floodedCaveBiomeKey()
|
||||
);
|
||||
}
|
||||
@@ -2443,7 +2443,7 @@ final class HydrologyFootprintCompiler {
|
||||
terrain.surfaceBiomeKey(),
|
||||
terrain.mouthBiomeKey(),
|
||||
terrain.shoreBiomeKey(),
|
||||
terrain.dryBiomeKey(),
|
||||
terrain.bankBiomeKey(),
|
||||
terrain.floodedCaveBiomeKey()
|
||||
);
|
||||
addLayer(columns, x, z, terrain, layer);
|
||||
@@ -3655,7 +3655,7 @@ final class HydrologyFootprintCompiler {
|
||||
first.surfaceBiomeKey(),
|
||||
first.mouthBiomeKey(),
|
||||
first.shoreBiomeKey(),
|
||||
first.dryBiomeKey(),
|
||||
first.bankBiomeKey(),
|
||||
first.floodedCaveBiomeKey()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public record HydrologyPlannerSettings(
|
||||
Geometry geometry,
|
||||
List<DeepFluid> deepFluids
|
||||
) {
|
||||
private static final long PLAN_FORMAT_REVISION = 5L;
|
||||
private static final long PLAN_FORMAT_REVISION = 6L;
|
||||
private static final int MAXIMUM_CROSS_TILE_COLOR_PERIOD = 4;
|
||||
|
||||
public HydrologyPlannerSettings {
|
||||
@@ -36,7 +36,7 @@ public record HydrologyPlannerSettings(
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new Routing(2048, 64, 8, 8192, 8192, new Branching(384, 192), 1.5D, 24D, 2D, 0.2D),
|
||||
new Surface(true, surfaceSources, 4, 8, 1, 4, 3, 7, 6, 2, 10, 24, true, 192, 10),
|
||||
new Surface(true, surfaceSources, 4, 8, 2, 4, 1, 1, 10, 1.5D, 4, 32, false, 1, 1, Banks.defaults()),
|
||||
new Hydraulics(80, 180, 1, 7, 24, 8),
|
||||
new Underground(true, undergroundSources, -48, 72, 3, 8, 1, 3, 6, 14, true),
|
||||
new Outlets(
|
||||
@@ -97,8 +97,9 @@ public record HydrologyPlannerSettings(
|
||||
int radius = 0;
|
||||
int routeDisplacement = Math.multiplyExact(routing.sampleSpacing(), 3);
|
||||
if (surface.enabled() && surface.sources().enabled()) {
|
||||
int blendWidth = Math.max(surface.maximumTerrainBlendWidth(), surface.banks().maximumBlendWidth());
|
||||
int surfaceRadius = (int) StrictMath.ceil(
|
||||
surface.maximumWidth() / 2D + surface.shoreWidth() + surface.maximumTerrainBlendWidth()
|
||||
surface.maximumWidth() / 2D + surface.shoreWidth() + blendWidth
|
||||
);
|
||||
surfaceRadius = Math.max(
|
||||
surfaceRadius,
|
||||
@@ -228,11 +229,12 @@ public record HydrologyPlannerSettings(
|
||||
int maximumTerrainBlendWidth,
|
||||
boolean ridgeTunnelsEnabled,
|
||||
int maximumRidgeTunnelLength,
|
||||
int ridgeTunnelHeadroom
|
||||
int ridgeTunnelHeadroom,
|
||||
Banks banks
|
||||
) {
|
||||
public Surface {
|
||||
if (sources == null) {
|
||||
throw new IllegalArgumentException("Surface source settings are required.");
|
||||
if (sources == null || banks == null) {
|
||||
throw new IllegalArgumentException("Surface source and bank settings are required.");
|
||||
}
|
||||
requireRange(minimumWidth, maximumWidth, 1, 256, "surface width");
|
||||
requireRange(minimumDepth, maximumDepth, 1, 64, "surface depth");
|
||||
@@ -247,6 +249,37 @@ public record HydrologyPlannerSettings(
|
||||
}
|
||||
}
|
||||
|
||||
public record Banks(
|
||||
int inset,
|
||||
int freeboard,
|
||||
double blendSlope,
|
||||
int minimumBlendWidth,
|
||||
int maximumBlendWidth,
|
||||
double roughness,
|
||||
int roughnessWavelength,
|
||||
int cascadeRun,
|
||||
int waterfallMinimumDrop,
|
||||
double mouthFlareRatio,
|
||||
boolean exposeCutStrata
|
||||
) {
|
||||
public Banks {
|
||||
if (inset < 1 || inset > 16 || freeboard < 1 || freeboard > 8
|
||||
|| !Double.isFinite(blendSlope) || blendSlope < 1D || blendSlope > 16D
|
||||
|| minimumBlendWidth < 1 || maximumBlendWidth < minimumBlendWidth || maximumBlendWidth > 128
|
||||
|| !Double.isFinite(roughness) || roughness < 0D || roughness > 1D
|
||||
|| roughnessWavelength < 3 || roughnessWavelength > 128
|
||||
|| cascadeRun < 1 || cascadeRun > 16
|
||||
|| waterfallMinimumDrop < 2 || waterfallMinimumDrop > 24
|
||||
|| !Double.isFinite(mouthFlareRatio) || mouthFlareRatio < 1D || mouthFlareRatio > 4D) {
|
||||
throw new IllegalArgumentException("Surface bank settings are invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
public static Banks defaults() {
|
||||
return new Banks(1, 1, 3D, 4, 32, 0.25D, 16, 2, 6, 1.6D, true);
|
||||
}
|
||||
}
|
||||
|
||||
public record Hydraulics(
|
||||
int minimumTargetPoolLength,
|
||||
int maximumTargetPoolLength,
|
||||
|
||||
@@ -22,11 +22,12 @@ public record HydrologyTerrainSample(
|
||||
double depthMultiplier,
|
||||
double incisionMultiplier,
|
||||
double routingMultiplier,
|
||||
double bankMultiplier,
|
||||
String parentBiomeKey,
|
||||
String surfaceBiomeKey,
|
||||
String mouthBiomeKey,
|
||||
String shoreBiomeKey,
|
||||
String dryBiomeKey,
|
||||
String bankBiomeKey,
|
||||
String floodedCaveBiomeKey,
|
||||
List<String> preferredProfileKeys
|
||||
) {
|
||||
@@ -39,6 +40,7 @@ public record HydrologyTerrainSample(
|
||||
requireFinitePositive(depthMultiplier, "depthMultiplier");
|
||||
requireFiniteNonNegative(incisionMultiplier, "incisionMultiplier");
|
||||
requireFiniteNonNegative(routingMultiplier, "routingMultiplier");
|
||||
requireFinitePositive(bankMultiplier, "bankMultiplier");
|
||||
if (caveAvailable && (caveFluidY <= caveFloorY || caveFluidY >= naturalHeight)) {
|
||||
throw new IllegalArgumentException("Available cave fluid must be above its floor and below natural terrain.");
|
||||
}
|
||||
@@ -46,7 +48,7 @@ public record HydrologyTerrainSample(
|
||||
surfaceBiomeKey = normalizeKey(surfaceBiomeKey, parentBiomeKey);
|
||||
mouthBiomeKey = normalizeKey(mouthBiomeKey, surfaceBiomeKey);
|
||||
shoreBiomeKey = normalizeKey(shoreBiomeKey, parentBiomeKey);
|
||||
dryBiomeKey = normalizeKey(dryBiomeKey, parentBiomeKey);
|
||||
bankBiomeKey = normalizeKey(bankBiomeKey, parentBiomeKey);
|
||||
floodedCaveBiomeKey = normalizeKey(floodedCaveBiomeKey, surfaceBiomeKey);
|
||||
preferredProfileKeys = normalizeProfiles(preferredProfileKeys);
|
||||
}
|
||||
@@ -72,6 +74,7 @@ public record HydrologyTerrainSample(
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
parentBiomeKey,
|
||||
parentBiomeKey,
|
||||
parentBiomeKey,
|
||||
@@ -103,6 +106,7 @@ public record HydrologyTerrainSample(
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
parentBiomeKey,
|
||||
parentBiomeKey,
|
||||
parentBiomeKey,
|
||||
@@ -134,11 +138,12 @@ public record HydrologyTerrainSample(
|
||||
depthMultiplier,
|
||||
incisionMultiplier,
|
||||
routingMultiplier,
|
||||
bankMultiplier,
|
||||
parentBiomeKey,
|
||||
surfaceBiomeKey,
|
||||
mouthBiomeKey,
|
||||
shoreBiomeKey,
|
||||
dryBiomeKey,
|
||||
bankBiomeKey,
|
||||
floodedCaveBiomeKey,
|
||||
preferredProfileKeys
|
||||
);
|
||||
|
||||
+4
-3
@@ -14,12 +14,13 @@ public record EffectiveRiverPolicy(
|
||||
List<String> surfaceBiomes,
|
||||
List<String> mouthBiomes,
|
||||
List<String> shoreBiomes,
|
||||
List<String> dryBiomes,
|
||||
List<String> bankBiomes,
|
||||
List<String> floodedCaveBiomes,
|
||||
double widthMultiplier,
|
||||
double depthMultiplier,
|
||||
double incisionMultiplier,
|
||||
double routingMultiplier
|
||||
double routingMultiplier,
|
||||
double bankMultiplier
|
||||
) {
|
||||
public EffectiveRiverPolicy {
|
||||
placement = Objects.requireNonNull(placement);
|
||||
@@ -28,7 +29,7 @@ public record EffectiveRiverPolicy(
|
||||
surfaceBiomes = List.copyOf(surfaceBiomes);
|
||||
mouthBiomes = List.copyOf(mouthBiomes);
|
||||
shoreBiomes = List.copyOf(shoreBiomes);
|
||||
dryBiomes = List.copyOf(dryBiomes);
|
||||
bankBiomes = List.copyOf(bankBiomes);
|
||||
floodedCaveBiomes = List.copyOf(floodedCaveBiomes);
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -41,12 +41,13 @@ public final class RiverPolicyResolver {
|
||||
private List<String> surfaceBiomes = List.of();
|
||||
private List<String> mouthBiomes = List.of();
|
||||
private List<String> shoreBiomes = List.of();
|
||||
private List<String> dryBiomes = List.of();
|
||||
private List<String> bankBiomes = List.of();
|
||||
private List<String> floodedCaveBiomes = List.of();
|
||||
private double widthMultiplier = 1D;
|
||||
private double depthMultiplier = 1D;
|
||||
private double incisionMultiplier = 1D;
|
||||
private double routingMultiplier = 1D;
|
||||
private double bankMultiplier = 1D;
|
||||
|
||||
private void apply(IrisRiverPolicy policy) {
|
||||
if (policy == null) {
|
||||
@@ -73,8 +74,8 @@ public final class RiverPolicyResolver {
|
||||
if (policy.getShoreBiomes() != null) {
|
||||
shoreBiomes = List.copyOf(policy.getShoreBiomes());
|
||||
}
|
||||
if (policy.getDryBiomes() != null) {
|
||||
dryBiomes = List.copyOf(policy.getDryBiomes());
|
||||
if (policy.getBankBiomes() != null) {
|
||||
bankBiomes = List.copyOf(policy.getBankBiomes());
|
||||
}
|
||||
if (policy.getFloodedCaveBiomes() != null) {
|
||||
floodedCaveBiomes = List.copyOf(policy.getFloodedCaveBiomes());
|
||||
@@ -91,6 +92,9 @@ public final class RiverPolicyResolver {
|
||||
if (policy.getRoutingMultiplier() != null) {
|
||||
routingMultiplier = policy.getRoutingMultiplier();
|
||||
}
|
||||
if (policy.getBankMultiplier() != null) {
|
||||
bankMultiplier = policy.getBankMultiplier();
|
||||
}
|
||||
}
|
||||
|
||||
private EffectiveRiverPolicy build() {
|
||||
@@ -102,12 +106,13 @@ public final class RiverPolicyResolver {
|
||||
surfaceBiomes,
|
||||
mouthBiomes,
|
||||
shoreBiomes,
|
||||
dryBiomes,
|
||||
bankBiomes,
|
||||
floodedCaveBiomes,
|
||||
widthMultiplier,
|
||||
depthMultiplier,
|
||||
incisionMultiplier,
|
||||
routingMultiplier
|
||||
routingMultiplier,
|
||||
bankMultiplier
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+72
-44
@@ -30,7 +30,6 @@ import art.arcane.iris.engine.object.IrisRiverGrottoConfig;
|
||||
import art.arcane.iris.engine.object.IrisRiverChannelShapeConfig;
|
||||
import art.arcane.iris.engine.object.IrisRiverDropShapeConfig;
|
||||
import art.arcane.iris.engine.object.IrisRiverGeometryConfig;
|
||||
import art.arcane.iris.engine.object.IrisRiverHydraulicsConfig;
|
||||
import art.arcane.iris.engine.object.IrisRiverHydrology;
|
||||
import art.arcane.iris.engine.object.IrisRiverInlandOutlet;
|
||||
import art.arcane.iris.engine.object.IrisRiverMeanderConfig;
|
||||
@@ -38,7 +37,9 @@ import art.arcane.iris.engine.object.IrisRiverProfile;
|
||||
import art.arcane.iris.engine.object.IrisRiverRoutingConfig;
|
||||
import art.arcane.iris.engine.object.IrisRiverRoutingMode;
|
||||
import art.arcane.iris.engine.object.IrisStyledRange;
|
||||
import art.arcane.iris.engine.object.IrisSurfaceRiverBankConfig;
|
||||
import art.arcane.iris.engine.object.IrisSurfaceRiverChannelConfig;
|
||||
import art.arcane.iris.engine.object.IrisSurfaceRiverFlowConfig;
|
||||
import art.arcane.iris.engine.object.IrisSurfaceRiverConfig;
|
||||
import art.arcane.iris.engine.object.IrisSurfaceRiverSourceConfig;
|
||||
import art.arcane.iris.engine.object.IrisUndergroundRiverConfig;
|
||||
@@ -463,11 +464,12 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
policy.depthMultiplier(),
|
||||
policy.incisionMultiplier(),
|
||||
policy.routingMultiplier() * routingPreference,
|
||||
policy.bankMultiplier(),
|
||||
parentBiomeKey,
|
||||
selectKey(policy.surfaceBiomes(), parentBiomeKey, biomePatchNoise, 1),
|
||||
selectKey(policy.mouthBiomes(), parentBiomeKey, biomePatchNoise, 2),
|
||||
selectKey(policy.shoreBiomes(), parentBiomeKey, biomePatchNoise, 3),
|
||||
selectKey(policy.dryBiomes(), parentBiomeKey, biomePatchNoise, 4),
|
||||
selectKey(policy.bankBiomes(), parentBiomeKey, biomePatchNoise, 4),
|
||||
selectKey(policy.floodedCaveBiomes(), parentBiomeKey, biomePatchNoise, 5),
|
||||
profiles
|
||||
);
|
||||
@@ -556,21 +558,13 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
IrisRiverHydrology rivers = hydrology.getRivers();
|
||||
IrisSurfaceRiverConfig surface = rivers.getSurface();
|
||||
IrisSurfaceRiverChannelConfig channel = surface.getChannel();
|
||||
IrisRiverHydraulicsConfig hydraulics = surface.getHydraulics();
|
||||
IrisSurfaceRiverBankConfig banks = surface.getBanks();
|
||||
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
||||
ProceduralStream<Double> surfaceWidth = styledStream(context, channel.getWidth(), SURFACE_WIDTH_SALT);
|
||||
ProceduralStream<Double> surfaceDepth = styledStream(context, channel.getDepth(), SURFACE_DEPTH_SALT);
|
||||
ProceduralStream<Double> surfaceInset = styledStream(context, channel.getSurfaceInset(), SURFACE_INSET_SALT);
|
||||
ProceduralStream<Double> surfaceBlend = styledStream(
|
||||
context,
|
||||
channel.getTerrainBlendWidth(),
|
||||
SURFACE_BLEND_SALT
|
||||
);
|
||||
ProceduralStream<Double> targetPool = styledStream(
|
||||
context,
|
||||
hydraulics.getTargetPoolLength(),
|
||||
TARGET_POOL_SALT
|
||||
);
|
||||
ProceduralStream<Double> surfaceInset = ProceduralStream.ofDouble((x, z) -> (double) channel.getInset());
|
||||
ProceduralStream<Double> surfaceBlend = ProceduralStream.ofDouble((x, z) -> (double) banks.getMaximumBlendWidth());
|
||||
ProceduralStream<Double> targetPool = ProceduralStream.ofDouble((x, z) -> 128D);
|
||||
ProceduralStream<Double> undergroundLevel = styledStream(
|
||||
context,
|
||||
underground.getFluidLevel(),
|
||||
@@ -646,10 +640,12 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
IrisSurfaceRiverConfig surface = rivers.getSurface();
|
||||
IrisSurfaceRiverSourceConfig surfaceSources = surface.getSources();
|
||||
IrisSurfaceRiverChannelConfig channel = surface.getChannel();
|
||||
IrisRiverHydraulicsConfig hydraulics = surface.getHydraulics();
|
||||
IrisSurfaceRiverBankConfig banks = surface.getBanks();
|
||||
IrisSurfaceRiverFlowConfig flow = surface.getFlow();
|
||||
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
||||
IrisUndergroundRiverSourceConfig undergroundSources = underground.getSources();
|
||||
int routeNodes = maximumRouteNodes(routing);
|
||||
int refinementSpacing = refinementSpacing(routing.getSampleSpacing());
|
||||
int minimumWorldY = dimension.getMinHeight();
|
||||
boolean riversEnabled = rivers.isEnabled();
|
||||
boolean surfaceEnabled = riversEnabled && surface.isEnabled();
|
||||
@@ -657,17 +653,17 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
HydrologyPlannerSettings.Routing plannerRouting = new HydrologyPlannerSettings.Routing(
|
||||
routing.getTileSize(),
|
||||
routing.getSampleSpacing(),
|
||||
routing.getRefinementSpacing(),
|
||||
refinementSpacing,
|
||||
routeNodes,
|
||||
routing.getMaximumRouteLength(),
|
||||
new HydrologyPlannerSettings.Branching(
|
||||
routing.getBranching().getMinimumSurfaceCourseLength(),
|
||||
routing.getBranching().getMinimumUndergroundCourseLength()
|
||||
routing.getMinimumSurfaceCourseLength(),
|
||||
routing.getMinimumUndergroundCourseLength()
|
||||
),
|
||||
1.5D,
|
||||
24D,
|
||||
2D,
|
||||
0.2D
|
||||
routing.getValleyPreference(),
|
||||
routing.getUphillPenalty(),
|
||||
routing.getSlopePenalty(),
|
||||
routing.getConfluenceAttraction()
|
||||
);
|
||||
HydrologyPlannerSettings.Source plannerSurfaceSources = new HydrologyPlannerSettings.Source(
|
||||
surfaceEnabled,
|
||||
@@ -684,23 +680,36 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
maximumInt(channel.getWidth()),
|
||||
minimumInt(channel.getDepth()),
|
||||
maximumInt(channel.getDepth()),
|
||||
minimumInt(channel.getSurfaceInset()),
|
||||
maximumInt(channel.getSurfaceInset()),
|
||||
channel.getInset(),
|
||||
channel.getInset(),
|
||||
channel.getMaximumIncision(),
|
||||
channel.getShoreWidth(),
|
||||
minimumInt(channel.getTerrainBlendWidth()),
|
||||
maximumInt(channel.getTerrainBlendWidth()),
|
||||
surface.getRidgeTunnels().isEnabled(),
|
||||
surface.getRidgeTunnels().getMaximumLength(),
|
||||
surface.getRidgeTunnels().getHeadroom()
|
||||
banks.getShoreWidth(),
|
||||
banks.getMinimumBlendWidth(),
|
||||
banks.getMaximumBlendWidth(),
|
||||
false,
|
||||
1,
|
||||
1,
|
||||
new HydrologyPlannerSettings.Banks(
|
||||
channel.getInset(),
|
||||
banks.getFreeboard(),
|
||||
banks.getBlendSlope(),
|
||||
banks.getMinimumBlendWidth(),
|
||||
banks.getMaximumBlendWidth(),
|
||||
channel.getRoughness(),
|
||||
channel.getRoughnessWavelength(),
|
||||
flow.getCascadeRun(),
|
||||
flow.getWaterfallMinimumDrop(),
|
||||
surface.getMouths().getFlareRatio(),
|
||||
banks.isExposeCutStrata()
|
||||
)
|
||||
);
|
||||
HydrologyPlannerSettings.Hydraulics plannerHydraulics = new HydrologyPlannerSettings.Hydraulics(
|
||||
minimumInt(hydraulics.getTargetPoolLength()),
|
||||
maximumInt(hydraulics.getTargetPoolLength()),
|
||||
hydraulics.getRiffleDrop(),
|
||||
hydraulics.getMaximumGradualDrop(),
|
||||
hydraulics.getMaximumGradualLength(),
|
||||
hydraulics.getWaterfallMinimumDrop()
|
||||
80,
|
||||
180,
|
||||
1,
|
||||
flow.getWaterfallMinimumDrop() - 1,
|
||||
24,
|
||||
flow.getWaterfallMinimumDrop()
|
||||
);
|
||||
HydrologyPlannerSettings.Source plannerUndergroundSources = new HydrologyPlannerSettings.Source(
|
||||
undergroundEnabled,
|
||||
@@ -736,11 +745,19 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
inland.getHeadroom(), inland.getMaximumVolume()),
|
||||
inlandEnabled && inland.isConnectSurfaceRivers(),
|
||||
Math.max(4, coastal.getVerticalRadius()),
|
||||
surface.getMouths().getLevelingDistance(),
|
||||
underground.getMouthLevelingDistance(),
|
||||
surface.getMouths().getMaximumOceanApron(),
|
||||
routing.getMaximumOutletsPerTile()
|
||||
);
|
||||
HydrologyPlannerSettings.Geometry plannerGeometry = geometry(rivers.getGeometry());
|
||||
HydrologyPlannerSettings.Geometry plannerGeometry = geometry(
|
||||
rivers.getGeometry(),
|
||||
new HydrologyPlannerSettings.ChannelShape(
|
||||
2D,
|
||||
channel.getRoughness(),
|
||||
channel.getRoughness(),
|
||||
channel.getRoughnessWavelength()
|
||||
)
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
dimension.getFluidHeight(),
|
||||
plannerRouting,
|
||||
@@ -749,11 +766,21 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
plannerUnderground,
|
||||
plannerOutlets,
|
||||
plannerGeometry,
|
||||
deepFluids(hydrology.getDeepFluids(), minimumWorldY, routing)
|
||||
deepFluids(hydrology.getDeepFluids(), minimumWorldY, routing, refinementSpacing)
|
||||
);
|
||||
}
|
||||
|
||||
private static HydrologyPlannerSettings.Geometry geometry(IrisRiverGeometryConfig geometry) {
|
||||
static int refinementSpacing(int sampleSpacing) {
|
||||
if (sampleSpacing % 4 == 0) {
|
||||
return 4;
|
||||
}
|
||||
return sampleSpacing % 2 == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
private static HydrologyPlannerSettings.Geometry geometry(
|
||||
IrisRiverGeometryConfig geometry,
|
||||
HydrologyPlannerSettings.ChannelShape surfaceShape
|
||||
) {
|
||||
IrisRiverMeanderConfig meanders = geometry.getMeanders();
|
||||
IrisRiverDropShapeConfig drops = geometry.getDrops();
|
||||
return new HydrologyPlannerSettings.Geometry(
|
||||
@@ -766,7 +793,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
meanders.getSmoothingPasses(),
|
||||
meanders.getMaximumTurnDegrees()
|
||||
),
|
||||
channelShape(geometry.getSurface()),
|
||||
surfaceShape,
|
||||
channelShape(geometry.getUnderground()),
|
||||
channelShape(geometry.getGrottos()),
|
||||
new HydrologyPlannerSettings.Drops(
|
||||
@@ -809,7 +836,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
private static List<HydrologyPlannerSettings.DeepFluid> deepFluids(
|
||||
List<IrisDeepFluidConfig> configurations,
|
||||
int minimumWorldY,
|
||||
IrisRiverRoutingConfig routing
|
||||
IrisRiverRoutingConfig routing,
|
||||
int refinementSpacing
|
||||
) {
|
||||
ArrayList<HydrologyPlannerSettings.DeepFluid> deepFluids = new ArrayList<>();
|
||||
for (IrisDeepFluidConfig configuration : configurations) {
|
||||
@@ -820,7 +848,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
int maximumChannelLength = maximumDeepChannelLength(configuration, routing);
|
||||
int minimumChannelLength = maximumChannelLength == 0
|
||||
? 0
|
||||
: Math.min(maximumChannelLength, Math.max(routing.getRefinementSpacing(), radius));
|
||||
: Math.min(maximumChannelLength, Math.max(refinementSpacing, radius));
|
||||
deepFluids.add(new HydrologyPlannerSettings.DeepFluid(
|
||||
configuration.getId(),
|
||||
configuration.getDensity() > 0D
|
||||
@@ -855,7 +883,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
return 0;
|
||||
}
|
||||
int configuredLength = Math.max(
|
||||
routing.getRefinementSpacing(), configuration.getSpacing() / 3);
|
||||
refinementSpacing(routing.getSampleSpacing()), configuration.getSpacing() / 3);
|
||||
return Math.min(configuredLength, routing.getTileSize() / 2);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -326,7 +326,7 @@ public final class MantleHydrologyComponent extends IrisMantleComponent {
|
||||
+ position + ".");
|
||||
}
|
||||
String biomeKey = action == HydrologyCaveAction.DRY_AIR
|
||||
? layer.dryBiomeKey()
|
||||
? layer.bankBiomeKey()
|
||||
: layer.floodedCaveBiomeKey();
|
||||
PlannedCell candidate = new PlannedCell(
|
||||
new HydrologyCaveCell(action, layer.profileKey(), biomeKey),
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls minimum complete river lengths before a route is published.")
|
||||
@Data
|
||||
public class IrisRiverBranchingConfig {
|
||||
@MinNumber(0)
|
||||
@MaxNumber(32768)
|
||||
@Desc("Minimum complete surface source-to-outlet route length in blocks.")
|
||||
private int minimumSurfaceCourseLength = 384;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(32768)
|
||||
@Desc("Minimum complete underground source-to-outlet route length in blocks.")
|
||||
private int minimumUndergroundCourseLength = 192;
|
||||
|
||||
}
|
||||
@@ -7,21 +7,18 @@ import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls organic river routing, beds, carved walls, and descending water geometry.")
|
||||
@Desc("Controls organic river routing and contained cave geometry.")
|
||||
@Data
|
||||
public class IrisRiverGeometryConfig {
|
||||
@Desc("Surface and underground centerline meanders.")
|
||||
private IrisRiverMeanderConfig meanders = new IrisRiverMeanderConfig();
|
||||
|
||||
@Desc("Surface channel bed and bank shape.")
|
||||
private IrisRiverChannelShapeConfig surface = new IrisRiverChannelShapeConfig();
|
||||
|
||||
@Desc("Underground channel bed and wall shape.")
|
||||
private IrisRiverChannelShapeConfig underground = new IrisRiverChannelShapeConfig();
|
||||
|
||||
@Desc("Grotto pool bed and wall shape.")
|
||||
private IrisRiverChannelShapeConfig grottos = new IrisRiverChannelShapeConfig();
|
||||
|
||||
@Desc("Cascade, cataract, waterfall, and sinkhole descent shape.")
|
||||
@Desc("Underground drop, sinkhole and receiving basin shape.")
|
||||
private IrisRiverDropShapeConfig drops = new IrisRiverDropShapeConfig();
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls deterministic river head transitions and hydraulic segment classification.")
|
||||
@Data
|
||||
public class IrisRiverHydraulicsConfig {
|
||||
@Desc("Target longitudinal length of level pools between head transitions.")
|
||||
private IrisStyledRange targetPoolLength = range(80D, 180D, 1024D);
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(16)
|
||||
@Desc("Normal one-step head loss represented by a riffle.")
|
||||
private int riffleDrop = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(64)
|
||||
@Desc("Largest head loss represented as a gradual cascade.")
|
||||
private int maximumGradualDrop = 7;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(1024)
|
||||
@Desc("Largest longitudinal distance used for one gradual cascade transition.")
|
||||
private int maximumGradualLength = 24;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(128)
|
||||
@Desc("Minimum required head loss represented by a waterfall.")
|
||||
private int waterfallMinimumDrop = 8;
|
||||
|
||||
private static IrisStyledRange range(double min, double max, double zoom) {
|
||||
return new IrisStyledRange(min, max, new IrisGeneratorStyle(NoiseStyle.IRIS).zoomed(zoom));
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,16 @@ import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls river leveling before a coastal reservoir and the final ocean footprint.")
|
||||
@Desc("Controls how a surface river meets the sea.")
|
||||
@Data
|
||||
public class IrisRiverMouthConfig {
|
||||
@MinNumber(0)
|
||||
@MaxNumber(2048)
|
||||
@Desc("Distance in blocks over which an ocean-bound river reaches sea level before the coastline.")
|
||||
private int levelingDistance = 64;
|
||||
@MinNumber(1)
|
||||
@MaxNumber(4)
|
||||
@Desc("Width multiplier reached at the coastline over the final stretch of the river.")
|
||||
private double flareRatio = 1.6D;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(64)
|
||||
@Desc("Maximum number of blocks the river footprint may enter an ocean reservoir before terminating.")
|
||||
@Desc("Maximum number of blocks the recorded mouth footprint may enter the ocean before terminating.")
|
||||
private int maximumOceanApron = 8;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class IrisRiverPolicy {
|
||||
@RegistryListResource(IrisBiome.class)
|
||||
@ArrayType(type = String.class)
|
||||
@Desc("Dry river footprint biome selection. An empty list explicitly clears the inherited selection.")
|
||||
private KList<String> dryBiomes = null;
|
||||
private KList<String> bankBiomes = null;
|
||||
|
||||
@RegistryListResource(IrisBiome.class)
|
||||
@ArrayType(type = String.class)
|
||||
@@ -74,12 +74,17 @@ public class IrisRiverPolicy {
|
||||
@Desc("Multiplier applied to terrain-guided routing cost.")
|
||||
private Double routingMultiplier = null;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(16)
|
||||
@Desc("Multiplier applied to the eroded bank width outside the shore band.")
|
||||
private Double bankMultiplier = null;
|
||||
|
||||
public KSet<String> getAllBiomeIds() {
|
||||
KSet<String> biomeIds = new KSet<>();
|
||||
addAll(biomeIds, surfaceBiomes);
|
||||
addAll(biomeIds, mouthBiomes);
|
||||
addAll(biomeIds, shoreBiomes);
|
||||
addAll(biomeIds, dryBiomes);
|
||||
addAll(biomeIds, bankBiomes);
|
||||
addAll(biomeIds, floodedCaveBiomes);
|
||||
return biomeIds;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls short contained ridge bores on otherwise viable surface courses.")
|
||||
@Data
|
||||
public class IrisRiverRidgeTunnelConfig {
|
||||
@Desc("Allow short ridge bores when they preserve the accepted drainage course.")
|
||||
private boolean enabled = true;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(4096)
|
||||
@Desc("Maximum accepted ridge-bore length in blocks.")
|
||||
private int maximumLength = 192;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(128)
|
||||
@Desc("Dry vertical clearance above the river head inside a ridge bore.")
|
||||
private int headroom = 10;
|
||||
}
|
||||
@@ -24,22 +24,24 @@ public class IrisRiverRoutingConfig {
|
||||
@Desc("Spacing in blocks between terrain samples used to build the drainage graph.")
|
||||
private int sampleSpacing = 64;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(64)
|
||||
@Desc("Spacing in blocks used to refine accepted terrain-guided centerlines.")
|
||||
private int refinementSpacing = 8;
|
||||
|
||||
@Desc("Minimum route and tributary lengths used to suppress chopped, clustered branches.")
|
||||
private IrisRiverBranchingConfig branching = new IrisRiverBranchingConfig();
|
||||
|
||||
@MinNumber(256)
|
||||
@MaxNumber(32768)
|
||||
@Desc("Maximum bounded length in blocks of one accepted river route.")
|
||||
private int maximumRouteLength = 16384;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(32768)
|
||||
@Desc("Minimum exposed source-to-outlet length in blocks of a published surface river.")
|
||||
private int minimumSurfaceCourseLength = 384;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(32768)
|
||||
@Desc("Minimum source-to-outlet length in blocks of a published underground river.")
|
||||
private int minimumUndergroundCourseLength = 192;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(256)
|
||||
@Desc("Maximum drainage roots selected per planning tile. Fewer roots produce longer, more strongly branching river trees.")
|
||||
@Desc("Maximum drainage roots selected per planning tile.")
|
||||
private int maximumOutletsPerTile = 4;
|
||||
|
||||
@Desc("Allow rivers to terminate at an ocean reservoir.")
|
||||
@@ -48,4 +50,24 @@ public class IrisRiverRoutingConfig {
|
||||
@ArrayType(type = IrisRiverInlandOutlet.class)
|
||||
@Desc("Contained inland outlet kinds available when no legal ocean outlet is selected.")
|
||||
private KList<IrisRiverInlandOutlet> inlandOutlets = new KList<>();
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(64)
|
||||
@Desc("How strongly routes prefer lower ground.")
|
||||
private double valleyPreference = 1.5D;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1024)
|
||||
@Desc("Cost per block of rise along a route.")
|
||||
private double uphillPenalty = 24D;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(64)
|
||||
@Desc("Cost per unit of terrain slope along a route.")
|
||||
private double slopePenalty = 2D;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(16)
|
||||
@Desc("How strongly routes are drawn toward existing drainage.")
|
||||
private double confluenceAttraction = 0.2D;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls the lip, shore band and eroded valley around a surface river.")
|
||||
@Data
|
||||
public class IrisSurfaceRiverBankConfig {
|
||||
@MinNumber(1)
|
||||
@MaxNumber(8)
|
||||
@Desc("Blocks the bank top sits above the water surface at the channel edge.")
|
||||
private int freeboard = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(8)
|
||||
@Desc("Width in blocks of the shore band that receives shore biome content.")
|
||||
private double shoreWidth = 1.5D;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(16)
|
||||
@Desc("Horizontal run in blocks of eroded bank per block of cut depth.")
|
||||
private double blendSlope = 3D;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(64)
|
||||
@Desc("Narrowest eroded band outside the shore, in blocks.")
|
||||
private int minimumBlendWidth = 4;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(128)
|
||||
@Desc("Widest eroded band outside the shore, in blocks.")
|
||||
private int maximumBlendWidth = 32;
|
||||
|
||||
@Desc("Show the biome's deeper layers on eroded banks instead of the surface layer.")
|
||||
private boolean exposeCutStrata = true;
|
||||
}
|
||||
+18
-20
@@ -9,39 +9,37 @@ import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls the accepted surface-river terrain and biome footprint.")
|
||||
@Desc("Controls the wet channel of a surface river.")
|
||||
@Data
|
||||
public class IrisSurfaceRiverChannelConfig {
|
||||
@Desc("Wet channel width in blocks.")
|
||||
private IrisStyledRange width = range(4D, 8D, 1024D);
|
||||
|
||||
@Desc("Wet bed depth in blocks.")
|
||||
private IrisStyledRange depth = range(1D, 4D, 768D, 2D);
|
||||
@Desc("Wet bed depth in blocks at the channel center.")
|
||||
private IrisStyledRange depth = range(2D, 4D, 768D);
|
||||
|
||||
@Desc("Vertical distance from the natural terrain corridor to the solved water surface.")
|
||||
private IrisStyledRange surfaceInset = range(3D, 7D, 768D, 2D);
|
||||
@MinNumber(1)
|
||||
@MaxNumber(16)
|
||||
@Desc("Blocks the water surface sits below the lowest natural bank beside the channel.")
|
||||
private int inset = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(64)
|
||||
@Desc("Maximum permitted channel incision below natural terrain.")
|
||||
private int maximumIncision = 6;
|
||||
@Desc("Maximum cut below natural terrain at the channel center before a course is rejected.")
|
||||
private int maximumIncision = 10;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(2)
|
||||
@Desc("Narrow biome-selection band immediately outside the wet channel.")
|
||||
private double shoreWidth = 2D;
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("Coherent variation of the wet outline and bed as a fraction of the channel size.")
|
||||
private double roughness = 0.25D;
|
||||
|
||||
@Desc("Wider terrain-grading distance outside the shore band.")
|
||||
private IrisStyledRange terrainBlendWidth = range(10D, 24D, 1024D);
|
||||
@MinNumber(3)
|
||||
@MaxNumber(128)
|
||||
@Desc("Wavelength in blocks of the outline and bed variation.")
|
||||
private int roughnessWavelength = 16;
|
||||
|
||||
private static IrisStyledRange range(double min, double max, double zoom) {
|
||||
return range(min, max, zoom, 1D);
|
||||
}
|
||||
|
||||
private static IrisStyledRange range(double min, double max, double zoom, double exponent) {
|
||||
IrisGeneratorStyle style = new IrisGeneratorStyle(NoiseStyle.IRIS)
|
||||
.zoomed(zoom)
|
||||
.setExponent(exponent);
|
||||
IrisGeneratorStyle style = new IrisGeneratorStyle(NoiseStyle.IRIS).zoomed(zoom);
|
||||
return new IrisStyledRange(min, max, style);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ public class IrisSurfaceRiverConfig {
|
||||
@Desc("Surface-river source allocation.")
|
||||
private IrisSurfaceRiverSourceConfig sources = new IrisSurfaceRiverSourceConfig();
|
||||
|
||||
@Desc("Surface channel and surrounding terrain footprint.")
|
||||
@Desc("Wet channel width, depth, inset and roughness.")
|
||||
private IrisSurfaceRiverChannelConfig channel = new IrisSurfaceRiverChannelConfig();
|
||||
|
||||
@Desc("Pool, riffle, cascade, and waterfall classification thresholds.")
|
||||
private IrisRiverHydraulicsConfig hydraulics = new IrisRiverHydraulicsConfig();
|
||||
@Desc("Lip, shore band and eroded valley around the channel.")
|
||||
private IrisSurfaceRiverBankConfig banks = new IrisSurfaceRiverBankConfig();
|
||||
|
||||
@Desc("Short ridge-bore configuration for otherwise viable surface routes.")
|
||||
private IrisRiverRidgeTunnelConfig ridgeTunnels = new IrisRiverRidgeTunnelConfig();
|
||||
@Desc("Cascade and waterfall thresholds.")
|
||||
private IrisSurfaceRiverFlowConfig flow = new IrisSurfaceRiverFlowConfig();
|
||||
|
||||
@Desc("Coastal mouth leveling and ocean-apron limits.")
|
||||
@Desc("Coastal mouth flare and ocean-apron limits.")
|
||||
private IrisRiverMouthConfig mouths = new IrisRiverMouthConfig();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Controls how a surface river descends.")
|
||||
@Data
|
||||
public class IrisSurfaceRiverFlowConfig {
|
||||
@MinNumber(1)
|
||||
@MaxNumber(16)
|
||||
@Desc("Shortest level run in blocks between one-block steps before consecutive steps are labelled a cascade.")
|
||||
private int cascadeRun = 2;
|
||||
|
||||
@MinNumber(2)
|
||||
@MaxNumber(24)
|
||||
@Desc("Smallest natural cliff in blocks that becomes a waterfall instead of a cascade.")
|
||||
private int waterfallMinimumDrop = 6;
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -31,6 +33,11 @@ public class IrisUndergroundRiverConfig {
|
||||
@Desc("Allow accepted underground courses to connect transactionally to existing caves.")
|
||||
private boolean connectToExistingCaves = true;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(2048)
|
||||
@Desc("Distance in blocks over which an ocean-bound underground river levels to sea level before its mouth.")
|
||||
private int mouthLevelingDistance = 64;
|
||||
|
||||
private static IrisStyledRange range(double min, double max, double zoom) {
|
||||
return new IrisStyledRange(min, max, new IrisGeneratorStyle(NoiseStyle.IRIS).zoomed(zoom));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class PackHydrologyValidatorTest {
|
||||
"derivative": "minecraft:river",
|
||||
"riverPolicy": {
|
||||
"profiles": ["default"],
|
||||
"dryBiomes": ["river_dry"]
|
||||
"bankBiomes": ["river_dry"]
|
||||
}
|
||||
}
|
||||
""");
|
||||
@@ -267,7 +267,7 @@ public class PackHydrologyValidatorTest {
|
||||
"surfaceBiomes": ["missing"],
|
||||
"mouthBiomes": "river",
|
||||
"shoreBiomes": ["biome", "biome"],
|
||||
"dryBiomes": [17],
|
||||
"bankBiomes": [17],
|
||||
"floodedCaveBiomes": ["../escape"],
|
||||
"widthMultiplier": 0,
|
||||
"depthMultiplier": 17,
|
||||
@@ -286,7 +286,7 @@ public class PackHydrologyValidatorTest {
|
||||
assertContains(result.errors(), "surfaceBiomes[0] references missing biome 'missing'");
|
||||
assertContains(result.errors(), ".mouthBiomes must be an array or null");
|
||||
assertContains(result.errors(), "shoreBiomes[1] duplicates biome 'biome'");
|
||||
assertContains(result.errors(), "dryBiomes[0] must name a biome resource");
|
||||
assertContains(result.errors(), "bankBiomes[0] must name a biome resource");
|
||||
assertContains(result.errors(), "floodedCaveBiomes[0] must name a biome resource");
|
||||
assertContains(result.errors(), "widthMultiplier must be at least");
|
||||
assertContains(result.errors(), "depthMultiplier must be at most");
|
||||
@@ -859,7 +859,7 @@ public class PackHydrologyValidatorTest {
|
||||
"surfaceBiomes": ["river_surface"],
|
||||
"mouthBiomes": ["river_surface"],
|
||||
"shoreBiomes": ["river_shore"],
|
||||
"dryBiomes": ["river_dry"],
|
||||
"bankBiomes": ["river_dry"],
|
||||
"floodedCaveBiomes": ["river_dry"],
|
||||
"widthMultiplier": 1,
|
||||
"depthMultiplier": 1,
|
||||
|
||||
@@ -164,7 +164,7 @@ public class IrisRiverSchemaTest {
|
||||
assertEquals("array", properties.getJSONObject("surfaceBiomes").getString("type"));
|
||||
assertEquals("array", properties.getJSONObject("mouthBiomes").getString("type"));
|
||||
assertEquals("array", properties.getJSONObject("shoreBiomes").getString("type"));
|
||||
assertEquals("array", properties.getJSONObject("dryBiomes").getString("type"));
|
||||
assertEquals("array", properties.getJSONObject("bankBiomes").getString("type"));
|
||||
assertEquals("array", properties.getJSONObject("floodedCaveBiomes").getString("type"));
|
||||
assertEquals(16D, properties.getJSONObject("widthMultiplier").getDouble("maximum"), 0D);
|
||||
assertEquals(0D, properties.getJSONObject("incisionMultiplier").getDouble("minimum"), 0D);
|
||||
|
||||
+8
-3
@@ -270,7 +270,8 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
true,
|
||||
96,
|
||||
10
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 40, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
true,
|
||||
@@ -351,7 +352,8 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
baseSurface.ridgeTunnelsEnabled(),
|
||||
baseSurface.maximumRidgeTunnelLength(),
|
||||
baseSurface.ridgeTunnelHeadroom()
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
base.hydraulics(),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
false,
|
||||
@@ -412,6 +414,7 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -452,11 +455,12 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
sample.depthMultiplier(),
|
||||
sample.incisionMultiplier(),
|
||||
sample.routingMultiplier(),
|
||||
1D,
|
||||
sample.parentBiomeKey(),
|
||||
sample.surfaceBiomeKey(),
|
||||
sample.mouthBiomeKey(),
|
||||
sample.shoreBiomeKey(),
|
||||
sample.dryBiomeKey(),
|
||||
sample.bankBiomeKey(),
|
||||
sample.floodedCaveBiomeKey(),
|
||||
sample.preferredProfileKeys()
|
||||
);
|
||||
@@ -484,6 +488,7 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"ocean_parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
|
||||
+9
-4
@@ -687,7 +687,8 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
false,
|
||||
0,
|
||||
0
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundEnabled,
|
||||
@@ -752,7 +753,8 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
surface.maximumRidgeTunnelLength(),
|
||||
surface.ridgeTunnelHeadroom()
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
base.hydraulics(),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
underground.enabled(),
|
||||
@@ -935,6 +937,7 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
ocean ? "ocean" : "land",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -985,6 +988,7 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"land",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -1033,6 +1037,7 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"land",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -1157,7 +1162,7 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
addString(terrain.surfaceBiomeKey());
|
||||
addString(terrain.mouthBiomeKey());
|
||||
addString(terrain.shoreBiomeKey());
|
||||
addString(terrain.dryBiomeKey());
|
||||
addString(terrain.bankBiomeKey());
|
||||
addString(terrain.floodedCaveBiomeKey());
|
||||
addInt(terrain.preferredProfileKeys().size());
|
||||
for (String profile : terrain.preferredProfileKeys()) {
|
||||
@@ -1287,7 +1292,7 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
addString(layer.surfaceBiomeKey());
|
||||
addString(layer.mouthBiomeKey());
|
||||
addString(layer.shoreBiomeKey());
|
||||
addString(layer.dryBiomeKey());
|
||||
addString(layer.bankBiomeKey());
|
||||
addString(layer.floodedCaveBiomeKey());
|
||||
}
|
||||
|
||||
|
||||
+34
-1
@@ -89,7 +89,8 @@ public class HydrologyPlannerSettingsTest {
|
||||
false,
|
||||
0,
|
||||
0
|
||||
);
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults());
|
||||
HydrologyPlannerSettings.Hydraulics hydraulics = new HydrologyPlannerSettings.Hydraulics(
|
||||
8,
|
||||
8,
|
||||
@@ -139,6 +140,38 @@ public class HydrologyPlannerSettingsTest {
|
||||
assertEquals(2730, deepFluid.maximumChannelLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bankSettingsRejectValuesOutsideTheirBounds() {
|
||||
HydrologyPlannerSettings.Banks banks = HydrologyPlannerSettings.Banks.defaults();
|
||||
|
||||
assertEquals(1, banks.inset());
|
||||
assertEquals(1, banks.freeboard());
|
||||
assertEquals(3D, banks.blendSlope(), 0D);
|
||||
assertEquals(4, banks.minimumBlendWidth());
|
||||
assertEquals(32, banks.maximumBlendWidth());
|
||||
assertEquals(6, banks.waterfallMinimumDrop());
|
||||
assertTrue(banks.exposeCutStrata());
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
0, 1, 3D, 4, 32, 0.25D, 16, 2, 6, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
1, 0, 3D, 4, 32, 0.25D, 16, 2, 6, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
1, 1, 0.5D, 4, 32, 0.25D, 16, 2, 6, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
1, 1, 3D, 40, 32, 0.25D, 16, 2, 6, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
1, 1, 3D, 4, 32, 0.25D, 16, 2, 1, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
1, 1, 3D, 4, 32, 0.25D, 16, 0, 6, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Banks(
|
||||
1, 1, 3D, 4, 32, 1.5D, 16, 2, 6, 1.6D, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Surface(
|
||||
true,
|
||||
new HydrologyPlannerSettings.Source(true, 1D, 0, 0, 1, 0),
|
||||
1, 1, 1, 1, 1, 1, 0, 1D, 0, 0, false, 0, 0,
|
||||
null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inconsistentHydraulicThresholdsAreRejected() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Hydraulics(
|
||||
|
||||
@@ -509,6 +509,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -1124,7 +1125,7 @@ public class HydrologyPlannerTest {
|
||||
assertEquals("surface", layer.surfaceBiomeKey());
|
||||
assertEquals("mouth", layer.mouthBiomeKey());
|
||||
assertEquals("shore", layer.shoreBiomeKey());
|
||||
assertEquals("dry", layer.dryBiomeKey());
|
||||
assertEquals("dry", layer.bankBiomeKey());
|
||||
assertEquals("flooded", layer.floodedCaveBiomeKey());
|
||||
if (layer.grading() && !layer.shore() && !layer.channel()) {
|
||||
sawGrading = true;
|
||||
@@ -1204,7 +1205,8 @@ public class HydrologyPlannerTest {
|
||||
base.surface().ridgeTunnelsEnabled(),
|
||||
base.surface().maximumRidgeTunnelLength(),
|
||||
base.surface().ridgeTunnelHeadroom()
|
||||
);
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults());
|
||||
HydrologyPlannerSettings shaped = new HydrologyPlannerSettings(
|
||||
base.seaLevel(),
|
||||
base.routing(),
|
||||
@@ -1498,7 +1500,8 @@ public class HydrologyPlannerTest {
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
32,
|
||||
surface.ridgeTunnelHeadroom()
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
base.hydraulics(),
|
||||
base.underground(),
|
||||
base.outlets(),
|
||||
@@ -1850,7 +1853,8 @@ public class HydrologyPlannerTest {
|
||||
true,
|
||||
64,
|
||||
8
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundDensity > 0D,
|
||||
@@ -1926,7 +1930,8 @@ public class HydrologyPlannerTest {
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
192,
|
||||
surface.ridgeTunnelHeadroom()
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 4, 12, 5),
|
||||
base.underground(),
|
||||
new HydrologyPlannerSettings.Outlets(
|
||||
@@ -2002,6 +2007,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -2066,6 +2072,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"ocean_parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -2097,6 +2104,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -2137,6 +2145,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -2168,6 +2177,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -2199,6 +2209,7 @@ public class HydrologyPlannerTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -2233,7 +2244,8 @@ public class HydrologyPlannerTest {
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
surface.maximumRidgeTunnelLength(),
|
||||
surface.ridgeTunnelHeadroom()
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
settings.hydraulics(),
|
||||
settings.underground(),
|
||||
settings.outlets(),
|
||||
|
||||
+4
-1
@@ -236,7 +236,8 @@ public class HydrologyStyledGeometryTest {
|
||||
true,
|
||||
96,
|
||||
8
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundDensity > 0D,
|
||||
@@ -288,6 +289,7 @@ public class HydrologyStyledGeometryTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"ocean",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -319,6 +321,7 @@ public class HydrologyStyledGeometryTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
|
||||
@@ -70,6 +70,7 @@ public final class HydrologyTerrainSampleTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
|
||||
@@ -245,7 +245,7 @@ public class HydrologyTileCacheTest {
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(64, 16, 4, 128, 64,
|
||||
new HydrologyPlannerSettings.Branching(0, 0), 0D, 0D, 0D, 0D),
|
||||
new HydrologyPlannerSettings.Surface(false, disabled, 2, 4, 1, 2, 2, 4, 4, 1D, 2, 4, false, 0, 0),
|
||||
new HydrologyPlannerSettings.Surface(false, disabled, 2, 4, 1, 2, 2, 4, 4, 1D, 2, 4, false, 0, 0, HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 2, 8, 3),
|
||||
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
||||
new HydrologyPlannerSettings.Outlets(
|
||||
@@ -284,7 +284,7 @@ public class HydrologyTileCacheTest {
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(64, 16, 4, 128, 96,
|
||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Surface(true, surfaceSources, 4, 8, 2, 3, 4, 8, 20, 1.5D, 2, 4, true, 96, 8),
|
||||
new HydrologyPlannerSettings.Surface(true, surfaceSources, 4, 8, 2, 3, 4, 8, 20, 1.5D, 2, 4, true, 96, 8, HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 2, 8, 3),
|
||||
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
||||
new HydrologyPlannerSettings.Outlets(
|
||||
@@ -327,6 +327,7 @@ public class HydrologyTileCacheTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
|
||||
+21
-4
@@ -29,10 +29,12 @@ public class RiverPolicyResolverTest {
|
||||
assertEquals(IrisRiverRoutingMode.ALLOW, policy.routing());
|
||||
assertTrue(policy.outletAdmission());
|
||||
assertTrue(policy.profiles().isEmpty());
|
||||
assertTrue(policy.bankBiomes().isEmpty());
|
||||
assertEquals(1D, policy.widthMultiplier(), 0D);
|
||||
assertEquals(1D, policy.depthMultiplier(), 0D);
|
||||
assertEquals(1D, policy.incisionMultiplier(), 0D);
|
||||
assertEquals(1D, policy.routingMultiplier(), 0D);
|
||||
assertEquals(1D, policy.bankMultiplier(), 0D);
|
||||
assertTrue(policy.allowsSources());
|
||||
assertTrue(policy.allowsTransit());
|
||||
assertTrue(policy.allowsRouting());
|
||||
@@ -49,13 +51,16 @@ public class RiverPolicyResolverTest {
|
||||
.setProfiles(new KList<>("water"))
|
||||
.setSurfaceBiomes(new KList<>("river/dimension"))
|
||||
.setMouthBiomes(new KList<>("river/mouth"))
|
||||
.setBankBiomes(new KList<>("river/bank-dimension"))
|
||||
.setWidthMultiplier(1.5D)
|
||||
.setDepthMultiplier(1.25D);
|
||||
.setDepthMultiplier(1.25D)
|
||||
.setBankMultiplier(2D);
|
||||
IrisRiverPolicy region = new IrisRiverPolicy()
|
||||
.setRouting(IrisRiverRoutingMode.PREFER)
|
||||
.setProfiles(new KList<>())
|
||||
.setSurfaceBiomes(new KList<>("river/region"))
|
||||
.setShoreBiomes(new KList<>("river/shore"))
|
||||
.setBankBiomes(new KList<>())
|
||||
.setWidthMultiplier(0.8D)
|
||||
.setRoutingMultiplier(2D);
|
||||
IrisRiverPolicy biome = new IrisRiverPolicy()
|
||||
@@ -63,10 +68,10 @@ public class RiverPolicyResolverTest {
|
||||
.setRouting(IrisRiverRoutingMode.BLOCK)
|
||||
.setOutletAdmission(true)
|
||||
.setSurfaceBiomes(new KList<>())
|
||||
.setDryBiomes(new KList<>("river/dry"))
|
||||
.setFloodedCaveBiomes(new KList<>("river/flooded"))
|
||||
.setDepthMultiplier(0.75D)
|
||||
.setIncisionMultiplier(0.5D);
|
||||
.setIncisionMultiplier(0.5D)
|
||||
.setBankMultiplier(0.5D);
|
||||
|
||||
EffectiveRiverPolicy policy = RiverPolicyResolver.resolve(dimension, region, biome);
|
||||
|
||||
@@ -75,14 +80,15 @@ public class RiverPolicyResolverTest {
|
||||
assertTrue(policy.outletAdmission());
|
||||
assertTrue(policy.profiles().isEmpty());
|
||||
assertTrue(policy.surfaceBiomes().isEmpty());
|
||||
assertTrue(policy.bankBiomes().isEmpty());
|
||||
assertEquals(List.of("river/mouth"), policy.mouthBiomes());
|
||||
assertEquals(List.of("river/shore"), policy.shoreBiomes());
|
||||
assertEquals(List.of("river/dry"), policy.dryBiomes());
|
||||
assertEquals(List.of("river/flooded"), policy.floodedCaveBiomes());
|
||||
assertEquals(0.8D, policy.widthMultiplier(), 0D);
|
||||
assertEquals(0.75D, policy.depthMultiplier(), 0D);
|
||||
assertEquals(0.5D, policy.incisionMultiplier(), 0D);
|
||||
assertEquals(2D, policy.routingMultiplier(), 0D);
|
||||
assertEquals(0.5D, policy.bankMultiplier(), 0D);
|
||||
assertTrue(policy.allowsSources());
|
||||
assertTrue(policy.allowsTransit());
|
||||
assertFalse(policy.allowsRouting());
|
||||
@@ -90,6 +96,17 @@ public class RiverPolicyResolverTest {
|
||||
assertTrue(policy.requiresHeadwaters());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bankBiomesInheritUntilOverridden() {
|
||||
IrisRiverPolicy dimension = new IrisRiverPolicy().setBankBiomes(new KList<>("river/bank"));
|
||||
IrisRiverPolicy region = new IrisRiverPolicy().setRouting(IrisRiverRoutingMode.PREFER);
|
||||
|
||||
EffectiveRiverPolicy policy = RiverPolicyResolver.resolve(dimension, region, null);
|
||||
|
||||
assertEquals(List.of("river/bank"), policy.bankBiomes());
|
||||
assertEquals(1D, policy.bankMultiplier(), 0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvesOwnerPoliciesAndSnapshotsMutableLists() {
|
||||
KList<String> profiles = new KList<>("water");
|
||||
|
||||
+56
-10
@@ -19,8 +19,7 @@ public class IrisHydrologyRuntimeSettingsTest {
|
||||
.setShortChannels(true)
|
||||
.setSpacing(8192);
|
||||
IrisRiverRoutingConfig routing = new IrisRiverRoutingConfig()
|
||||
.setTileSize(256)
|
||||
.setRefinementSpacing(8);
|
||||
.setTileSize(256);
|
||||
|
||||
assertEquals(128, IrisHydrologyRuntime.maximumDeepChannelLength(deepFluid, routing));
|
||||
}
|
||||
@@ -31,8 +30,7 @@ public class IrisHydrologyRuntimeSettingsTest {
|
||||
.setShortChannels(false)
|
||||
.setSpacing(8192);
|
||||
IrisRiverRoutingConfig routing = new IrisRiverRoutingConfig()
|
||||
.setTileSize(256)
|
||||
.setRefinementSpacing(8);
|
||||
.setTileSize(256);
|
||||
|
||||
assertEquals(0, IrisHydrologyRuntime.maximumDeepChannelLength(deepFluid, routing));
|
||||
}
|
||||
@@ -75,6 +73,57 @@ public class IrisHydrologyRuntimeSettingsTest {
|
||||
.underground().sources().minimumSpacing());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceBankAndFlowConfigurationMapsIntoPlannerSettings() {
|
||||
IrisDimension dimension = new IrisDimension();
|
||||
IrisRiverHydrology rivers = dimension.getHydrology().getRivers();
|
||||
rivers.getSurface().getChannel().setInset(2).setMaximumIncision(12);
|
||||
rivers.getSurface().getBanks()
|
||||
.setFreeboard(2)
|
||||
.setShoreWidth(2.5D)
|
||||
.setBlendSlope(4D)
|
||||
.setMinimumBlendWidth(6)
|
||||
.setMaximumBlendWidth(48)
|
||||
.setExposeCutStrata(false);
|
||||
rivers.getSurface().getFlow().setCascadeRun(3).setWaterfallMinimumDrop(8);
|
||||
rivers.getSurface().getMouths().setFlareRatio(2.2D);
|
||||
rivers.getUnderground().setMouthLevelingDistance(96);
|
||||
rivers.getRouting()
|
||||
.setSampleSpacing(32)
|
||||
.setMinimumSurfaceCourseLength(500)
|
||||
.setMinimumUndergroundCourseLength(250)
|
||||
.setValleyPreference(2.5D)
|
||||
.setUphillPenalty(30D)
|
||||
.setSlopePenalty(3D)
|
||||
.setConfluenceAttraction(0.4D);
|
||||
|
||||
HydrologyPlannerSettings settings = IrisHydrologyRuntime.createSettings(dimension, dimension.getHydrology());
|
||||
HydrologyPlannerSettings.Banks banks = settings.surface().banks();
|
||||
|
||||
assertEquals(2, banks.inset());
|
||||
assertEquals(2, banks.freeboard());
|
||||
assertEquals(4D, banks.blendSlope(), 0D);
|
||||
assertEquals(6, banks.minimumBlendWidth());
|
||||
assertEquals(48, banks.maximumBlendWidth());
|
||||
assertEquals(3, banks.cascadeRun());
|
||||
assertEquals(8, banks.waterfallMinimumDrop());
|
||||
assertEquals(2.2D, banks.mouthFlareRatio(), 0D);
|
||||
assertFalse(banks.exposeCutStrata());
|
||||
assertEquals(12, settings.surface().maximumIncision());
|
||||
assertEquals(2.5D, settings.surface().shoreWidth(), 0D);
|
||||
assertEquals(8, settings.hydraulics().waterfallMinimumDrop());
|
||||
assertEquals(96, settings.outlets().mouthLevelingDistance());
|
||||
assertEquals(4, settings.routing().refinementSpacing());
|
||||
assertEquals(500, settings.routing().branching().minimumSurfaceCourseLength());
|
||||
assertEquals(250, settings.routing().branching().minimumUndergroundCourseLength());
|
||||
assertEquals(2.5D, settings.routing().valleyPreference(), 0D);
|
||||
assertEquals(30D, settings.routing().uphillPenalty(), 0D);
|
||||
assertEquals(3D, settings.routing().slopePenalty(), 0D);
|
||||
assertEquals(0.4D, settings.routing().confluenceAttraction(), 0D);
|
||||
assertEquals(2, IrisHydrologyRuntime.refinementSpacing(50));
|
||||
assertEquals(1, IrisHydrologyRuntime.refinementSpacing(45));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routingOutletLimitControlsDrainageRootCount() {
|
||||
IrisDimension dimension = new IrisDimension();
|
||||
@@ -96,10 +145,8 @@ public class IrisHydrologyRuntimeSettingsTest {
|
||||
.setMaximumOffsetRatio(0.44D)
|
||||
.setSmoothingPasses(2)
|
||||
.setMaximumTurnDegrees(76D);
|
||||
rivers.getGeometry().getSurface()
|
||||
.setBedRoundness(3.1D)
|
||||
.setBedRoughness(0.37D)
|
||||
.setWallRoughness(0.29D)
|
||||
rivers.getSurface().getChannel()
|
||||
.setRoughness(0.37D)
|
||||
.setRoughnessWavelength(13);
|
||||
rivers.getGeometry().getDrops()
|
||||
.setCascadeRunPerBlock(4)
|
||||
@@ -121,9 +168,8 @@ public class IrisHydrologyRuntimeSettingsTest {
|
||||
assertEquals(0.44D, geometry.meanders().maximumOffsetRatio(), 0D);
|
||||
assertEquals(2, geometry.meanders().smoothingPasses());
|
||||
assertEquals(76D, geometry.meanders().maximumTurnDegrees(), 0D);
|
||||
assertEquals(3.1D, geometry.surface().bedRoundness(), 0D);
|
||||
assertEquals(0.37D, geometry.surface().bedRoughness(), 0D);
|
||||
assertEquals(0.29D, geometry.surface().wallRoughness(), 0D);
|
||||
assertEquals(0.37D, geometry.surface().wallRoughness(), 0D);
|
||||
assertEquals(13, geometry.surface().roughnessWavelength());
|
||||
assertEquals(4, geometry.drops().cascadeRunPerBlock());
|
||||
assertEquals(2.2D, geometry.drops().cascadeExponent(), 0D);
|
||||
|
||||
+3
-1
@@ -1541,7 +1541,8 @@ public class MantleHydrologyComponentTest {
|
||||
false,
|
||||
0,
|
||||
0
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
false,
|
||||
@@ -1597,6 +1598,7 @@ public class MantleHydrologyComponentTest {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
ocean ? "ocean" : "land",
|
||||
"surface",
|
||||
"mouth",
|
||||
|
||||
+2
-2
@@ -148,7 +148,7 @@ public class IrisDimensionReachableBiomesTest {
|
||||
.setChildren(new KList<>("dimension-child"));
|
||||
IrisBiome dimensionChild = biome("dimension-child");
|
||||
IrisBiome regionMouth = biome("region-mouth").setRiverPolicy(new IrisRiverPolicy()
|
||||
.setDryBiomes(new KList<>("nested-dry")));
|
||||
.setBankBiomes(new KList<>("nested-dry")));
|
||||
IrisBiome biomeShore = biome("biome-shore");
|
||||
IrisBiome nestedDry = biome("nested-dry");
|
||||
|
||||
@@ -222,7 +222,7 @@ public class IrisDimensionReachableBiomesTest {
|
||||
IrisRegion reachable = new IrisRegion()
|
||||
.setLandBiomes(new KList<>("root"))
|
||||
.setRiverPolicy(new IrisRiverPolicy()
|
||||
.setDryBiomes(new KList<>("region-dry")));
|
||||
.setBankBiomes(new KList<>("region-dry")));
|
||||
IrisBiome root = biome("root").setRiverPolicy(new IrisRiverPolicy()
|
||||
.setFloodedCaveBiomes(new KList<>("biome-flooded")));
|
||||
|
||||
|
||||
@@ -32,9 +32,14 @@ public class IrisRiverConfigurationTest {
|
||||
|
||||
IrisRiverRoutingConfig routing = dimension.getHydrology().getRivers().getRouting();
|
||||
assertEquals(2048, routing.getTileSize());
|
||||
assertEquals(64, routing.getSampleSpacing());
|
||||
assertEquals(16384, routing.getMaximumRouteLength());
|
||||
assertEquals(384, routing.getBranching().getMinimumSurfaceCourseLength());
|
||||
assertEquals(192, routing.getBranching().getMinimumUndergroundCourseLength());
|
||||
assertEquals(384, routing.getMinimumSurfaceCourseLength());
|
||||
assertEquals(192, routing.getMinimumUndergroundCourseLength());
|
||||
assertEquals(1.5D, routing.getValleyPreference(), 0D);
|
||||
assertEquals(24D, routing.getUphillPenalty(), 0D);
|
||||
assertEquals(2D, routing.getSlopePenalty(), 0D);
|
||||
assertEquals(0.2D, routing.getConfluenceAttraction(), 0D);
|
||||
|
||||
IrisSurfaceRiverConfig surface = dimension.getHydrology().getRivers().getSurface();
|
||||
assertTrue(surface.isEnabled());
|
||||
@@ -43,19 +48,22 @@ public class IrisRiverConfigurationTest {
|
||||
assertEquals(384, surface.getSources().getMinimumSpacing());
|
||||
assertEquals(4D, surface.getChannel().getWidth().getMin(), 0D);
|
||||
assertEquals(8D, surface.getChannel().getWidth().getMax(), 0D);
|
||||
assertEquals(1D, surface.getChannel().getDepth().getMin(), 0D);
|
||||
assertEquals(2D, surface.getChannel().getDepth().getMin(), 0D);
|
||||
assertEquals(4D, surface.getChannel().getDepth().getMax(), 0D);
|
||||
assertEquals(2D, surface.getChannel().getDepth().getStyle().getExponent(), 0D);
|
||||
assertEquals(3D, surface.getChannel().getSurfaceInset().getMin(), 0D);
|
||||
assertEquals(7D, surface.getChannel().getSurfaceInset().getMax(), 0D);
|
||||
assertEquals(2D, surface.getChannel().getSurfaceInset().getStyle().getExponent(), 0D);
|
||||
assertEquals(6, surface.getChannel().getMaximumIncision());
|
||||
assertEquals(2D, surface.getChannel().getShoreWidth(), 0D);
|
||||
assertEquals(64, surface.getMouths().getLevelingDistance());
|
||||
assertEquals(1, surface.getChannel().getInset());
|
||||
assertEquals(10, surface.getChannel().getMaximumIncision());
|
||||
assertEquals(0.25D, surface.getChannel().getRoughness(), 0D);
|
||||
assertEquals(16, surface.getChannel().getRoughnessWavelength());
|
||||
assertEquals(1, surface.getBanks().getFreeboard());
|
||||
assertEquals(1.5D, surface.getBanks().getShoreWidth(), 0D);
|
||||
assertEquals(3D, surface.getBanks().getBlendSlope(), 0D);
|
||||
assertEquals(4, surface.getBanks().getMinimumBlendWidth());
|
||||
assertEquals(32, surface.getBanks().getMaximumBlendWidth());
|
||||
assertTrue(surface.getBanks().isExposeCutStrata());
|
||||
assertEquals(2, surface.getFlow().getCascadeRun());
|
||||
assertEquals(6, surface.getFlow().getWaterfallMinimumDrop());
|
||||
assertEquals(1.6D, surface.getMouths().getFlareRatio(), 0D);
|
||||
assertEquals(8, surface.getMouths().getMaximumOceanApron());
|
||||
assertEquals(80D, surface.getHydraulics().getTargetPoolLength().getMin(), 0D);
|
||||
assertEquals(180D, surface.getHydraulics().getTargetPoolLength().getMax(), 0D);
|
||||
assertEquals(8, surface.getHydraulics().getWaterfallMinimumDrop());
|
||||
IrisRiverDropShapeConfig drops = dimension.getHydrology().getRivers().getGeometry().getDrops();
|
||||
assertEquals(2, drops.getCascadeRunPerBlock());
|
||||
assertEquals(1.4D, drops.getCascadeExponent(), 0D);
|
||||
@@ -75,6 +83,7 @@ public class IrisRiverConfigurationTest {
|
||||
assertEquals(3D, underground.getChannelWidth().getMin(), 0D);
|
||||
assertEquals(8D, underground.getChannelWidth().getMax(), 0D);
|
||||
assertTrue(underground.isConnectToExistingCaves());
|
||||
assertEquals(64, underground.getMouthLevelingDistance());
|
||||
|
||||
IrisCoastalRiverGrottoConfig coastal = dimension.getHydrology().getRivers().getGrottos().getCoastal();
|
||||
IrisInlandRiverGrottoConfig inland = dimension.getHydrology().getRivers().getGrottos().getInland();
|
||||
@@ -101,6 +110,7 @@ public class IrisRiverConfigurationTest {
|
||||
assertNull(dimension.getRiverPolicy().getPlacement());
|
||||
assertNull(dimension.getRiverPolicy().getRouting());
|
||||
assertNull(dimension.getRiverPolicy().getOutletAdmission());
|
||||
assertNull(dimension.getRiverPolicy().getBankMultiplier());
|
||||
assertNull(new IrisRegion().getRiverPolicy());
|
||||
assertNull(new IrisBiome().getRiverPolicy());
|
||||
}
|
||||
@@ -116,15 +126,16 @@ public class IrisRiverConfigurationTest {
|
||||
"routing": {
|
||||
"tileSize": 4096,
|
||||
"sampleSpacing": 96,
|
||||
"refinementSpacing": 6,
|
||||
"branching": {
|
||||
"minimumSurfaceCourseLength": 640,
|
||||
"minimumUndergroundCourseLength": 480
|
||||
},
|
||||
"maximumRouteLength": 32768,
|
||||
"minimumSurfaceCourseLength": 640,
|
||||
"minimumUndergroundCourseLength": 480,
|
||||
"maximumOutletsPerTile": 3,
|
||||
"oceanOutlets": true,
|
||||
"inlandOutlets": ["SINKHOLE_GROTTO"]
|
||||
"inlandOutlets": ["SINKHOLE_GROTTO"],
|
||||
"valleyPreference": 2.5,
|
||||
"uphillPenalty": 30,
|
||||
"slopePenalty": 3,
|
||||
"confluenceAttraction": 0.4
|
||||
},
|
||||
"geometry": {
|
||||
"drops": {
|
||||
@@ -143,20 +154,21 @@ public class IrisRiverConfigurationTest {
|
||||
"channel": {
|
||||
"width": {"min": 5, "max": 24},
|
||||
"depth": {"min": 2, "max": 6},
|
||||
"surfaceInset": {"min": 5, "max": 9},
|
||||
"inset": 2,
|
||||
"maximumIncision": 14,
|
||||
"shoreWidth": 1.5,
|
||||
"terrainBlendWidth": {"min": 8, "max": 10}
|
||||
"roughness": 0.4,
|
||||
"roughnessWavelength": 24
|
||||
},
|
||||
"hydraulics": {
|
||||
"targetPoolLength": {"min": 64, "max": 192},
|
||||
"riffleDrop": 1,
|
||||
"maximumGradualDrop": 4,
|
||||
"maximumGradualLength": 12,
|
||||
"waterfallMinimumDrop": 5
|
||||
"banks": {
|
||||
"freeboard": 2,
|
||||
"shoreWidth": 2.5,
|
||||
"blendSlope": 4,
|
||||
"minimumBlendWidth": 6,
|
||||
"maximumBlendWidth": 48,
|
||||
"exposeCutStrata": false
|
||||
},
|
||||
"ridgeTunnels": {"enabled": true, "maximumLength": 224, "headroom": 12},
|
||||
"mouths": {"levelingDistance": 80, "maximumOceanApron": 1}
|
||||
"flow": {"cascadeRun": 3, "waterfallMinimumDrop": 8},
|
||||
"mouths": {"flareRatio": 2.2, "maximumOceanApron": 1}
|
||||
},
|
||||
"underground": {
|
||||
"sources": {"density": 0.4, "minimumPerTile": 3, "minimumSpacing": 896},
|
||||
@@ -164,7 +176,8 @@ public class IrisRiverConfigurationTest {
|
||||
"channelWidth": {"min": 4, "max": 16},
|
||||
"depth": {"min": 2, "max": 4},
|
||||
"headroom": {"min": 7, "max": 15},
|
||||
"connectToExistingCaves": false
|
||||
"connectToExistingCaves": false,
|
||||
"mouthLevelingDistance": 80
|
||||
},
|
||||
"grottos": {
|
||||
"coastal": {
|
||||
@@ -211,8 +224,10 @@ public class IrisRiverConfigurationTest {
|
||||
"profiles": ["underworld"],
|
||||
"surfaceBiomes": ["river/surface"],
|
||||
"shoreBiomes": ["river/shore"],
|
||||
"bankBiomes": ["river/bank"],
|
||||
"widthMultiplier": 1.5,
|
||||
"incisionMultiplier": 0.75
|
||||
"incisionMultiplier": 0.75,
|
||||
"bankMultiplier": 2
|
||||
}
|
||||
}
|
||||
""", IrisDimension.class);
|
||||
@@ -236,14 +251,31 @@ public class IrisRiverConfigurationTest {
|
||||
IrisRiverHydrology rivers = dimension.getHydrology().getRivers();
|
||||
assertTrue(rivers.isEnabled());
|
||||
assertEquals(4096, rivers.getRouting().getTileSize());
|
||||
assertEquals(96, rivers.getRouting().getSampleSpacing());
|
||||
assertEquals(32768, rivers.getRouting().getMaximumRouteLength());
|
||||
assertEquals(3, rivers.getRouting().getMaximumOutletsPerTile());
|
||||
assertEquals(640, rivers.getRouting().getBranching().getMinimumSurfaceCourseLength());
|
||||
assertEquals(480, rivers.getRouting().getBranching().getMinimumUndergroundCourseLength());
|
||||
assertEquals(640, rivers.getRouting().getMinimumSurfaceCourseLength());
|
||||
assertEquals(480, rivers.getRouting().getMinimumUndergroundCourseLength());
|
||||
assertEquals(2.5D, rivers.getRouting().getValleyPreference(), 0D);
|
||||
assertEquals(30D, rivers.getRouting().getUphillPenalty(), 0D);
|
||||
assertEquals(3D, rivers.getRouting().getSlopePenalty(), 0D);
|
||||
assertEquals(0.4D, rivers.getRouting().getConfluenceAttraction(), 0D);
|
||||
assertEquals(new KList<>(IrisRiverInlandOutlet.SINKHOLE_GROTTO), rivers.getRouting().getInlandOutlets());
|
||||
assertEquals(24D, rivers.getSurface().getChannel().getWidth().getMax(), 0D);
|
||||
assertEquals(9D, rivers.getSurface().getChannel().getSurfaceInset().getMax(), 0D);
|
||||
assertEquals(5, rivers.getSurface().getHydraulics().getWaterfallMinimumDrop());
|
||||
assertEquals(2, rivers.getSurface().getChannel().getInset());
|
||||
assertEquals(14, rivers.getSurface().getChannel().getMaximumIncision());
|
||||
assertEquals(0.4D, rivers.getSurface().getChannel().getRoughness(), 0D);
|
||||
assertEquals(24, rivers.getSurface().getChannel().getRoughnessWavelength());
|
||||
assertEquals(2, rivers.getSurface().getBanks().getFreeboard());
|
||||
assertEquals(2.5D, rivers.getSurface().getBanks().getShoreWidth(), 0D);
|
||||
assertEquals(4D, rivers.getSurface().getBanks().getBlendSlope(), 0D);
|
||||
assertEquals(6, rivers.getSurface().getBanks().getMinimumBlendWidth());
|
||||
assertEquals(48, rivers.getSurface().getBanks().getMaximumBlendWidth());
|
||||
assertFalse(rivers.getSurface().getBanks().isExposeCutStrata());
|
||||
assertEquals(3, rivers.getSurface().getFlow().getCascadeRun());
|
||||
assertEquals(8, rivers.getSurface().getFlow().getWaterfallMinimumDrop());
|
||||
assertEquals(2.2D, rivers.getSurface().getMouths().getFlareRatio(), 0D);
|
||||
assertEquals(1, rivers.getSurface().getMouths().getMaximumOceanApron());
|
||||
assertEquals(768, rivers.getSurface().getSources().getMinimumSpacing());
|
||||
assertEquals(5, rivers.getGeometry().getDrops().getCascadeRunPerBlock());
|
||||
assertEquals(2.4D, rivers.getGeometry().getDrops().getCascadeExponent(), 0D);
|
||||
@@ -252,10 +284,10 @@ public class IrisRiverConfigurationTest {
|
||||
assertEquals(4, rivers.getGeometry().getDrops().getMaximumFlowDepth());
|
||||
assertEquals(2.2D, rivers.getGeometry().getDrops().getBasinWidthRatio(), 0D);
|
||||
assertEquals(11, rivers.getGeometry().getDrops().getMaximumBasinDepth());
|
||||
assertEquals(224, rivers.getSurface().getRidgeTunnels().getMaximumLength());
|
||||
assertEquals(-96D, rivers.getUnderground().getFluidLevel().getMin(), 0D);
|
||||
assertEquals(896, rivers.getUnderground().getSources().getMinimumSpacing());
|
||||
assertFalse(rivers.getUnderground().isConnectToExistingCaves());
|
||||
assertEquals(80, rivers.getUnderground().getMouthLevelingDistance());
|
||||
assertEquals(40, rivers.getGrottos().getCoastal().getHorizontalRadius());
|
||||
assertTrue(rivers.getGrottos().getInland().isEnabled());
|
||||
assertTrue(rivers.getGrottos().getInland().isConnectSurfaceRivers());
|
||||
@@ -273,7 +305,8 @@ public class IrisRiverConfigurationTest {
|
||||
assertEquals(IrisRiverPlacementMode.PREFERRED_HEADWATER, dimension.getRiverPolicy().getPlacement());
|
||||
assertEquals(IrisRiverRoutingMode.PREFER, dimension.getRiverPolicy().getRouting());
|
||||
assertFalse(dimension.getRiverPolicy().getOutletAdmission());
|
||||
assertEquals(Set.of("river/surface", "river/shore"), dimension.getRiverPolicy().getAllBiomeIds());
|
||||
assertEquals(2D, dimension.getRiverPolicy().getBankMultiplier(), 0D);
|
||||
assertEquals(Set.of("river/surface", "river/shore", "river/bank"), dimension.getRiverPolicy().getAllBiomeIds());
|
||||
assertEquals(IrisRiverPlacementMode.TRANSIT_ONLY, region.getRiverPolicy().getPlacement());
|
||||
assertEquals(new KList<>("river/mouth"), region.getRiverPolicy().getMouthBiomes());
|
||||
assertEquals(IrisRiverPlacementMode.REQUIRED_HEADWATER, biome.getRiverPolicy().getPlacement());
|
||||
|
||||
@@ -3862,7 +3862,7 @@ public final class HydrologyPackProbe {
|
||||
position.z()
|
||||
);
|
||||
String expectedBiome = witness.action() == HydrologyCaveAction.DRY_AIR
|
||||
? witness.layer().dryBiomeKey()
|
||||
? witness.layer().bankBiomeKey()
|
||||
: witness.layer().floodedCaveBiomeKey();
|
||||
if (cell == null
|
||||
|| cell.action() != witness.action()
|
||||
|
||||
@@ -231,7 +231,8 @@ public final class HydrologyPlannerProbe {
|
||||
true,
|
||||
96,
|
||||
8
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundDensity > 0D,
|
||||
@@ -289,6 +290,7 @@ public final class HydrologyPlannerProbe {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -396,7 +398,8 @@ public final class HydrologyPlannerProbe {
|
||||
true,
|
||||
96,
|
||||
10
|
||||
),
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 40, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
true,
|
||||
@@ -460,6 +463,7 @@ public final class HydrologyPlannerProbe {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
@@ -492,6 +496,7 @@ public final class HydrologyPlannerProbe {
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
1D,
|
||||
"ocean_parent",
|
||||
"surface",
|
||||
"mouth",
|
||||
|
||||
Reference in New Issue
Block a user