From 465a283bffe6493552ad77d6c6237bf9bee0c0e7 Mon Sep 17 00:00:00 2001 From: clive Date: Tue, 4 Nov 2025 20:44:43 +0800 Subject: [PATCH 01/12] Fractal Variety --- .../FractalNoiseLastTerrainGenerator.java | 169 +++++++++++++++--- .../MultiLevelLastTerrainGenerator.java | 53 +++++- .../neroxis/mask/MapMaskMethods.java | 37 +++- 3 files changed, 232 insertions(+), 27 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index bfb63245..14741689 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -9,35 +9,107 @@ import com.faforever.neroxis.mask.MapMaskMethods; import com.faforever.neroxis.util.Pipeline; +import java.util.ArrayList; import java.util.Set; public class FractalNoiseLastTerrainGenerator extends MultiLevelLastTerrainGenerator { + private record FlattenParams( + float minHeight, + float maxHeight, + float destinationMinHeight, + float destinationMaxHeight, + float slope, + int blurAmount, + boolean hasRamps, + boolean spawnable, + float spawnMaskDeflate + ) {} + + private record FractalType( + float waterHeight, + boolean useRandomWaterMask, + int noiseMapBlurAmount, + float noiseOctaveMultiplier, + float noiseExpMultiplier, + float minSpawnable, + float maxSpawnable, + int teamSeparation, + FlattenParams[] flattenParams + ) {} + private BooleanMask symmetryLines; private FloatMask symmetryCliffs; - private FloatMask noise; + private FloatMask rampNoise; + + private FractalType fractalType; @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); + pipeline.setDebug(true); symmetryLines = new BooleanMask(1, random.nextLong(), symmetrySettings, "symmetryLines", pipeline); symmetryCliffs = new FloatMask(1, random.nextLong(), symmetrySettings, "symmetryCliffs", pipeline); - noise = new FloatMask(1, random.nextLong(), symmetrySettings, "rampNoise", pipeline); + rampNoise = new FloatMask(1, random.nextLong(), symmetrySettings, "rampNoise", pipeline); + + ArrayList FRACTAL_TYPES = new ArrayList(); + // Basic Land + FRACTAL_TYPES.add(new FractalType(0f, false, 1, 1.5f, 8, 0, 1, 2, new FlattenParams[]{ + new FlattenParams(1, 4, 1, 1, 0, 0, false, false, 4), + new FlattenParams(4, 6, 13, 13, 0, 2, false, false, 4), + new FlattenParams(6, 15, 11, 11, 0, 0, false, false, 4), + new FlattenParams(15, 22, 16, 16, 0, 1, false, false, 4), + })); + // Plateau's + FRACTAL_TYPES.add(new FractalType(3f, false, 4, 1.2f, 4, 0, 0, 2, new FlattenParams[]{ + new FlattenParams(0f, 0.1f, 0, 4, 0.5f, 0, false, false, 4), + new FlattenParams(0.1f, 1.0f, 4, 15, 2, 0, true, false, 4), + new FlattenParams(1.0f, 27, 15, 15, 0, 0, false, true, 4), + new FlattenParams(27, 50, 24, 24, 0, 2, false, false, 4), + })); + // Navy + FRACTAL_TYPES.add(new FractalType(16, true, 2, 1.5f, 6, 0, 0, 3, new FlattenParams[]{ + new FlattenParams(0f, 1.0f, 0, 8, 0.25f, 0, false, false, 4), + new FlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), + new FlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), + new FlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), + })); + // The Upside - Down + FRACTAL_TYPES.add(new FractalType(2, false, 2, 1.2f, 3, 0, 0, 3, new FlattenParams[]{ + new FlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), + new FlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), + new FlattenParams(15f, 50f, 13, 12.5f, 0.5f, 1, false, false, 4), + })); + + + + + fractalType = FRACTAL_TYPES.get(random.nextInt(FRACTAL_TYPES.size())); + //fractalType = FRACTAL_TYPES.get(2); + System.out.println("FractalType : " + fractalType); + if (fractalType.useRandomWaterMask) { + waterMask = WaterMasks.values()[random.nextInt(WaterMasks.values().length)]; + System.out.println("WaterMask: " + waterMask.name()); + } + System.out.println(fractalType); + for (FlattenParams fp : fractalType.flattenParams) { + System.out.println("FlattenParam: " + fp); + } noiseSmallestDetail = 2; - noiseOctaveMultiplier = 1.5f; + noiseOctaveMultiplier = fractalType.noiseOctaveMultiplier; - noiseMapBlurAmount = 1; + noiseMapBlurAmount = fractalType.noiseMapBlurAmount; noiseScaleMaxToValue = 50; mountainBrushSize = 24; mountainBrushDensity = 8f; mountainBrushIntensity = 3f; - waterHeight -= landHeight - 1; + waterHeight -= fractalType.waterHeight; symmetryLines.setSize(map.getSize() + 1); symmetryLines.drawSymmetryLines(); @@ -48,7 +120,7 @@ protected void landSetup() { super.landSetup(); landNoiseMap.scaleToNewMinAndMaxHeight(0, 1); - landNoiseMap.scaleExponentially(8); + landNoiseMap.scaleExponentially(fractalType.noiseExpMultiplier); landNoiseMap.scaleToNewMinAndMaxHeight(0, noiseScaleMaxToValue); } @@ -76,16 +148,37 @@ protected void setupMountainHeightmapPipeline() { @Override protected void initRamps() { - ramps = landNoiseMap.copyAsBooleanMask(4f, 6f); - noise.setSize(landNoiseMap.getSize() / 16); - noise.addWhiteNoise(0, 1); - noise.setSize(landNoiseMap.getSize()); - BooleanMask noiseMask = noise.copyAsBooleanMask(0f, 0.05f); - noiseMask.inflate(4); - ramps.subtract(noiseMask.invert()); - ramps.erode(3).inflate(3); + ramps.startVisualDebugger("Ramps: "); + rampNoise.startVisualDebugger("Ramp Noise: "); + ramps.setSize(landNoiseMap.getSize()); + + for (FlattenParams flattenParams : fractalType.flattenParams) { + if (flattenParams.hasRamps) { + BooleanMask layer = landNoiseMap.copyAsBooleanMask(0f, flattenParams.maxHeight); + layer.startVisualDebugger(); + layer.outline(); + + rampNoise.setSize(landNoiseMap.getSize() / 16); + rampNoise.addWhiteNoise(0, 1); + rampNoise.setSize(landNoiseMap.getSize()); + + layer.subtract(rampNoise.copyAsBooleanMask(0f, 0.8f)); + + ramps.add(layer); + } + } } + @Override + protected void blurRamps() { + BooleanMask inflatedRamps = ramps.copy(); + heightmap.blur(48, inflatedRamps) + .blur(32, inflatedRamps.inflate(2)) + .blur(4, inflatedRamps.inflate(4)) + .blur(4, inflatedRamps.inflate(8)) + .clampMin(0f) + .clampMax(255f); + } @Override protected void setupHeightmapPipeline() { @@ -93,22 +186,22 @@ protected void setupHeightmapPipeline() { initRamps(); + landNoiseMap.startVisualDebugger("LandNoiseMap: "); + heightmap.setSize(mapSize + 1); - heightmapLand.setSize(mapSize + 1); + heightmapLand.setSize(mapSize + 1).startVisualDebugger("Heightmap Land: "); heightMapNoise.setSize(mapSize / 128); // Start the land height as the noise map heightmapLand.add(landNoiseMap); - // Main land part of the map - MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, 1, 4, 1, 0); - - // Plateau - MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, 4, 6, 13, 2); - MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, 6, 15, 11, 0); + for (FlattenParams flattenParams : fractalType.flattenParams) { + MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, flattenParams.minHeight, + flattenParams.maxHeight, flattenParams.destinationMinHeight, + flattenParams.destinationMaxHeight, + flattenParams.slope, flattenParams.blurAmount); + } - // 2nd Plateau, surrounding the mountains - MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, 15, 22, 16, 1); // Blur and add mountains along the line of symmetry if (Set.of(Symmetry.QUAD, Symmetry.DIAG, Symmetry.POINT2, Symmetry.POINT3, Symmetry.POINT4, Symmetry.POINT5, @@ -139,4 +232,34 @@ protected void setupHeightmapPipeline() { blurRamps(); } + + @Override + protected void setupSpawnMaskPipeline() { + + spawnMask.startVisualDebugger("Spawn Mask: "); + + if (fractalType.maxSpawnable > fractalType.minSpawnable) { + spawnMask.add(landNoiseMap.copyAsBooleanMask(fractalType.minSpawnable, fractalType.maxSpawnable)); + } + for (FlattenParams flattenParams : fractalType.flattenParams) { + if (flattenParams.spawnable) { + spawnMask.add(landNoiseMap.copyAsBooleanMask(flattenParams.minHeight, flattenParams.maxHeight) + .deflate(flattenParams.spawnMaskDeflate)); + } + } + + spawnMask.subtract(unbuildable) + .deflate(4); + } + + @Override + protected int getTeamSeparation() { + if (generatorParameters.numTeams() < 2) { + return 0; + } else if (generatorParameters.numTeams() == 2) { + return map.getSize() / fractalType.teamSeparation; + } else { + return StrictMath.min(map.getSize() / generatorParameters.numTeams(), 256); + } + } } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java index cf6edd3e..d4e8c26c 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java @@ -4,12 +4,25 @@ import com.faforever.neroxis.generator.GeneratorParameters; import com.faforever.neroxis.map.SCMap; import com.faforever.neroxis.map.SymmetrySettings; +import com.faforever.neroxis.map.SymmetryType; import com.faforever.neroxis.mask.BooleanMask; import com.faforever.neroxis.mask.FloatMask; import com.faforever.neroxis.util.Pipeline; +import com.faforever.neroxis.util.vector.Vector2; + +import java.util.List; public class MultiLevelLastTerrainGenerator extends BasicLastTerrainGenerator { + protected enum WaterMasks { + NONE, + SYMMETRY_LINE, + HOUR_GLASS, + CENTER_LAKE + } + + protected WaterMasks waterMask; + protected BooleanMask secondLevelLand; protected BooleanMask thirdLevelLand; @@ -60,13 +73,14 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame plateauBrushIntensity = 16f; mountainDensity = random.nextFloat() / 3; + waterMask = WaterMasks.NONE; } @Override protected void landSetup() { int mapSize = map.getSize(); - int MAX_OCTAVES = 8; + int MAX_OCTAVES = 7; int numOctaves = 0; while (numOctaves < MAX_OCTAVES && noiseSmallestDetail << numOctaves <= mapSize) { @@ -75,6 +89,42 @@ protected void landSetup() { float amplitude = 1f; landNoiseMap.setSize(mapSize + 1); + + // For water only + if (waterMask == WaterMasks.SYMMETRY_LINE) { + BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, + "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); + waterArea.drawSymmetryLines(); + waterArea.inflate(mapSize / 3f / symmetrySettings.teamSymmetry().getNumSymPoints()); + FloatMask waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f).startVisualDebugger("WaterAreaBlur: "); + waterAreaBlur.blur(mapSize / 4); + landNoiseMap.add(1f); + landNoiseMap.subtract(waterAreaBlur); + } else if (waterMask == WaterMasks.HOUR_GLASS) { + BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, + "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); + waterArea.drawSymmetryLines(); + waterArea.inflate(mapSize / 12f); + List symmetryPoints = waterArea.getSymmetryPointsWithOutOfBounds(new Vector2(0, 0), SymmetryType.SPAWN) + .stream() + .map(Vector2::roundToNearestHalfPoint) + .toList(); + waterArea.fillCircle(new Vector2(0, 0), mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true); + symmetryPoints.forEach(s -> waterArea.fillCircle(s, mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true)); + FloatMask waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f).startVisualDebugger("WaterAreaBlur: "); + waterAreaBlur.blur(mapSize / 3 / symmetrySettings.teamSymmetry().getNumSymPoints()); + landNoiseMap.add(1f); + landNoiseMap.subtract(waterAreaBlur); + } else if (waterMask == WaterMasks.CENTER_LAKE) { + BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, + "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); + waterArea.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 3f, true); + FloatMask waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f).startVisualDebugger("WaterAreaBlur: "); + waterAreaBlur.blur(mapSize / 4); + landNoiseMap.add(1f); + landNoiseMap.subtract(waterAreaBlur); + } + for (int octave = 0; octave < numOctaves; octave++) { FloatMask octaveNoise = new FloatMask(mapSize + 1, getRandom().nextLong(), land.getSymmetrySettings(), "landNoiseOctave" + octave, pipeline); @@ -85,6 +135,7 @@ protected void landSetup() { } landNoiseMap.blur(noiseMapBlurAmount); + landNoiseMap.scaleToNewMinAndMaxHeight(0, noiseScaleMaxToValue); land = landNoiseMap diff --git a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java index 8985edf4..49cde8f7 100644 --- a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java +++ b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java @@ -134,20 +134,51 @@ public static BooleanMask pathAroundLocations(List locations, long seed }); } - public static FloatMask flattenHeightBand(FloatMask exec, FloatMask noiseMap, float minHeight, float maxHeight, float destinationHeight, int blurAmount) { + /** + * + * @param slope = 1 → linear interpolation. + * > 1 → slower start, faster rise. + * < 1 → faster start, slower rise. + * @return + */ + public static FloatMask flattenHeightBand(FloatMask exec, FloatMask noiseMap, float minHeight, float maxHeight, + float destinationMinHeight, float destinationMaxHeight, float slope, + int blurAmount) { return exec.enqueue(dependencies -> { FloatMask noise = (FloatMask) dependencies.getFirst(); BooleanMask flattenMask = noise.copyAsBooleanMask(minHeight, maxHeight); exec.setPrimitiveWithSymmetry(SymmetryType.SPAWN, (x, y) -> { + float value = noise.getPrimitive(x, y); if (flattenMask.getPrimitive(x, y)) { - return destinationHeight; + if (slope <= 0) { + return destinationMaxHeight; + } else { + return remapWithSlope(value, minHeight, maxHeight, destinationMinHeight, destinationMaxHeight, slope); + } } else { return exec.getPrimitive(x, y); } }); if (blurAmount > 0) { - exec.blur(blurAmount, flattenMask.outline().inflate(1)); + exec.blur(blurAmount, flattenMask.outline().inflate(blurAmount)); } }, noiseMap); } + + private static float remapWithSlope(float value, float minHeight, float maxHeight, + float destinationMinHeight, float destinationMaxHeight, + float slope) { + + // Normalize value to 0–1 range + float normalized = (value - minHeight) / (maxHeight - minHeight); + + // Clamp to stay within bounds + normalized = StrictMath.max(0f, StrictMath.min(1f, normalized)); + + // Apply slope for non-linear curve + float curved = (float) StrictMath.pow(normalized, slope); + + // Map to destination range + return destinationMinHeight + (destinationMaxHeight - destinationMinHeight) * curved; + } } From b9973da861273b5f3b485640258e9dbf0b8114e4 Mon Sep 17 00:00:00 2001 From: clive Date: Tue, 4 Nov 2025 22:16:32 +0800 Subject: [PATCH 02/12] Fix Odd Symmetry artifacts by limiting to a circle --- .../terrain/FractalNoiseLastTerrainGenerator.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index 14741689..bde57891 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -230,6 +230,14 @@ protected void setupHeightmapPipeline() { heightmap.add(heightMapNoise); } + if (symmetrySettings.spawnSymmetry().getNumSymPoints() == 3 || symmetrySettings.spawnSymmetry().getNumSymPoints() >= 5) { + BooleanMask outerCircle = new BooleanMask(mapSize + 1, random.nextLong(), symmetrySettings, "outerCircle", pipeline); + outerCircle.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 2f, true).startVisualDebugger(); + outerCircle.invert(); + heightmap.setToValue(outerCircle, waterHeight); + heightmap.blur(5, outerCircle.outline().inflate(5)); + } + blurRamps(); } From d2fdd78d62b03711330ece0e4f933edf3ea73d7e Mon Sep 17 00:00:00 2001 From: clive Date: Sun, 9 Nov 2025 00:49:59 +0800 Subject: [PATCH 03/12] bunch of code cleaning --- .../generator/FractalFlattenParams.java | 13 +++ .../neroxis/generator/FractalParams.java | 11 ++ .../neroxis/generator/TerrainStyle.java | 12 +- ...or.java => FractalLandStyleGenerator.java} | 8 +- .../style/FractalNavyStyleGenerator.java | 33 ++++++ .../style/FractalPlateauStyleGenerator.java | 35 ++++++ ...a => FractalUpsideDownStyleGenerator.java} | 19 +--- ...FloodedMultiLevelLastTerrainGenerator.java | 71 ------------ .../FractalLandLastTerrainGenerator.java | 24 ++++ .../FractalNavyLastTerrainGenerator.java | 23 ++++ .../FractalNoiseLastTerrainGenerator.java | 107 ++++-------------- .../FractalPlateauLastTerrainGenerator.java | 23 ++++ ...FractalUpsideDownLastTerrainGenerator.java | 22 ++++ .../MultiLevelLastTerrainGenerator.java | 5 +- 14 files changed, 229 insertions(+), 177 deletions(-) create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/FractalFlattenParams.java create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java rename generator/src/main/java/com/faforever/neroxis/generator/style/{FractalNoiseStyleGenerator.java => FractalLandStyleGenerator.java} (87%) create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/style/FractalPlateauStyleGenerator.java rename generator/src/main/java/com/faforever/neroxis/generator/style/{FloodedMultiLevelStyleGenerator.java => FractalUpsideDownStyleGenerator.java} (71%) delete mode 100644 generator/src/main/java/com/faforever/neroxis/generator/terrain/FloodedMultiLevelLastTerrainGenerator.java create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java create mode 100644 generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java diff --git a/generator/src/main/java/com/faforever/neroxis/generator/FractalFlattenParams.java b/generator/src/main/java/com/faforever/neroxis/generator/FractalFlattenParams.java new file mode 100644 index 00000000..531f3e93 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/FractalFlattenParams.java @@ -0,0 +1,13 @@ +package com.faforever.neroxis.generator; + +public record FractalFlattenParams( + float minHeight, + float maxHeight, + float destinationMinHeight, + float destinationMaxHeight, + float slope, + int blurAmount, + boolean hasRamps, + boolean spawnable, + float spawnMaskDeflate +) {} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java b/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java new file mode 100644 index 00000000..85364044 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java @@ -0,0 +1,11 @@ +package com.faforever.neroxis.generator; + +public record FractalParams( + float waterHeight, + boolean useRandomWaterMask, + int noiseMapBlurAmount, + float noiseOctaveMultiplier, + float noiseExpMultiplier, + int teamSeparation, + FractalFlattenParams[] fractalFlattenParams +) {} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/TerrainStyle.java b/generator/src/main/java/com/faforever/neroxis/generator/TerrainStyle.java index eb87b838..f344ba0b 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/TerrainStyle.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/TerrainStyle.java @@ -7,9 +7,11 @@ import com.faforever.neroxis.generator.terrain.CenterLakeTerrainGenerator; import com.faforever.neroxis.generator.terrain.DropPlateauLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.DropPlateauTerrainGenerator; -import com.faforever.neroxis.generator.terrain.FloodedMultiLevelLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.FloodedTerrainGenerator; -import com.faforever.neroxis.generator.terrain.FractalNoiseLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.FractalLandLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.FractalNavyLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.FractalPlateauLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.FractalUpsideDownLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.LandBridgeTerrainGenerator; import com.faforever.neroxis.generator.terrain.LittleMountainLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.LittleMountainTerrainGenerator; @@ -44,14 +46,16 @@ public enum TerrainStyle { MOUNTAIN_RANGE(MountainRangeTerrainGenerator::new), MOUNTAIN_RANGE_LAST(MountainRangeLastTerrainGenerator::new), MULTILEVEL_LAST(MultiLevelLastTerrainGenerator::new), - FLOODED_MULTILEVEL_LAST(FloodedMultiLevelLastTerrainGenerator::new), ONE_ISLAND(OneIslandTerrainGenerator::new), SMALL_ISLANDS(SmallIslandsTerrainGenerator::new), VALLEY(ValleyTerrainGenerator::new), VALLEY_LAST(ValleyLastTerrainGenerator::new), RIVERS(RiversTerrainGenerator::new), RIVERS_AND_OCEANS(RiversAndOceansTerrainGenerator::new), - FRACTAL_LAST(FractalNoiseLastTerrainGenerator::new); + FRACTAL_LAND(FractalLandLastTerrainGenerator::new), + FRACTAL_PLATEAU(FractalPlateauLastTerrainGenerator::new), + FRACTAL_NAVY(FractalNavyLastTerrainGenerator::new), + FRACTAL_UPSIDE_DOWN(FractalUpsideDownLastTerrainGenerator::new); private final Supplier generatorSupplier; } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNoiseStyleGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalLandStyleGenerator.java similarity index 87% rename from generator/src/main/java/com/faforever/neroxis/generator/style/FractalNoiseStyleGenerator.java rename to generator/src/main/java/com/faforever/neroxis/generator/style/FractalLandStyleGenerator.java index aa05205b..1c0213e0 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNoiseStyleGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalLandStyleGenerator.java @@ -11,20 +11,20 @@ import com.faforever.neroxis.generator.prop.PropGenerator; import com.faforever.neroxis.generator.prop.RockFieldPropGenerator; import com.faforever.neroxis.generator.prop.SmallBattlePropGenerator; -import com.faforever.neroxis.generator.terrain.FractalNoiseLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.FractalLandLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.TerrainGenerator; -public class FractalNoiseStyleGenerator extends StyleGenerator { +public class FractalLandStyleGenerator extends StyleGenerator { @Override protected WeightedOptionsWithFallback getTerrainGeneratorOptions() { - return WeightedOptionsWithFallback.of(new FractalNoiseLastTerrainGenerator()); + return WeightedOptionsWithFallback.of(new FractalLandLastTerrainGenerator()); } @Override protected WeightedOptionsWithFallback getPropGeneratorOptions() { return WeightedOptionsWithFallback.of(new BasicPropGenerator(), new WeightedOption<>(new BasicPropGenerator(), 1f), - new WeightedOption<>(new BoulderFieldPropGenerator(), .1f), + new WeightedOption<>(new BoulderFieldPropGenerator(), .5f), new WeightedOption<>(new EnemyCivPropGenerator(), .5f), new WeightedOption<>(new HighReclaimPropGenerator(), .25f), new WeightedOption<>(new LargeBattlePropGenerator(), .5f), diff --git a/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java new file mode 100644 index 00000000..861e4aa7 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java @@ -0,0 +1,33 @@ +package com.faforever.neroxis.generator.style; + +import com.faforever.neroxis.generator.WeightedOption; +import com.faforever.neroxis.generator.WeightedOptionsWithFallback; +import com.faforever.neroxis.generator.prop.BasicPropGenerator; +import com.faforever.neroxis.generator.prop.BoulderFieldPropGenerator; +import com.faforever.neroxis.generator.prop.HighReclaimPropGenerator; +import com.faforever.neroxis.generator.prop.LargeBattlePropGenerator; +import com.faforever.neroxis.generator.prop.NavyWrecksPropGenerator; +import com.faforever.neroxis.generator.prop.PropGenerator; +import com.faforever.neroxis.generator.prop.RockFieldPropGenerator; +import com.faforever.neroxis.generator.prop.SmallBattlePropGenerator; +import com.faforever.neroxis.generator.terrain.FractalNavyLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.TerrainGenerator; + +public class FractalNavyStyleGenerator extends StyleGenerator { + @Override + protected WeightedOptionsWithFallback getTerrainGeneratorOptions() { + return WeightedOptionsWithFallback.of(new FractalNavyLastTerrainGenerator()); + } + + @Override + protected WeightedOptionsWithFallback getPropGeneratorOptions() { + return WeightedOptionsWithFallback.of(new BasicPropGenerator(), + new WeightedOption<>(new BasicPropGenerator(), 1f), + new WeightedOption<>(new NavyWrecksPropGenerator(), 3f), + new WeightedOption<>(new BoulderFieldPropGenerator(), 2f), + new WeightedOption<>(new HighReclaimPropGenerator(), 1f), + new WeightedOption<>(new LargeBattlePropGenerator(), .5f), + new WeightedOption<>(new RockFieldPropGenerator(), 0.5f), + new WeightedOption<>(new SmallBattlePropGenerator(), 0.5f)); + } +} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/style/FractalPlateauStyleGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalPlateauStyleGenerator.java new file mode 100644 index 00000000..238b9699 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalPlateauStyleGenerator.java @@ -0,0 +1,35 @@ +package com.faforever.neroxis.generator.style; + +import com.faforever.neroxis.generator.WeightedOption; +import com.faforever.neroxis.generator.WeightedOptionsWithFallback; +import com.faforever.neroxis.generator.prop.BasicPropGenerator; +import com.faforever.neroxis.generator.prop.BoulderFieldPropGenerator; +import com.faforever.neroxis.generator.prop.EnemyCivPropGenerator; +import com.faforever.neroxis.generator.prop.HighReclaimPropGenerator; +import com.faforever.neroxis.generator.prop.LargeBattlePropGenerator; +import com.faforever.neroxis.generator.prop.NeutralCivPropGenerator; +import com.faforever.neroxis.generator.prop.PropGenerator; +import com.faforever.neroxis.generator.prop.RockFieldPropGenerator; +import com.faforever.neroxis.generator.prop.SmallBattlePropGenerator; +import com.faforever.neroxis.generator.terrain.FractalPlateauLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.TerrainGenerator; + +public class FractalPlateauStyleGenerator extends StyleGenerator { + @Override + protected WeightedOptionsWithFallback getTerrainGeneratorOptions() { + return WeightedOptionsWithFallback.of(new FractalPlateauLastTerrainGenerator()); + } + + @Override + protected WeightedOptionsWithFallback getPropGeneratorOptions() { + return WeightedOptionsWithFallback.of(new BasicPropGenerator(), + new WeightedOption<>(new BasicPropGenerator(), 1f), + new WeightedOption<>(new BoulderFieldPropGenerator(), .5f), + new WeightedOption<>(new EnemyCivPropGenerator(), .5f), + new WeightedOption<>(new HighReclaimPropGenerator(), .5f), + new WeightedOption<>(new LargeBattlePropGenerator(), .5f), + new WeightedOption<>(new NeutralCivPropGenerator(), 1f), + new WeightedOption<>(new RockFieldPropGenerator(), 1f), + new WeightedOption<>(new SmallBattlePropGenerator(), 1f)); + } +} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/style/FloodedMultiLevelStyleGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalUpsideDownStyleGenerator.java similarity index 71% rename from generator/src/main/java/com/faforever/neroxis/generator/style/FloodedMultiLevelStyleGenerator.java rename to generator/src/main/java/com/faforever/neroxis/generator/style/FractalUpsideDownStyleGenerator.java index bc2045aa..c414374a 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/style/FloodedMultiLevelStyleGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalUpsideDownStyleGenerator.java @@ -7,35 +7,28 @@ import com.faforever.neroxis.generator.prop.EnemyCivPropGenerator; import com.faforever.neroxis.generator.prop.HighReclaimPropGenerator; import com.faforever.neroxis.generator.prop.LargeBattlePropGenerator; -import com.faforever.neroxis.generator.prop.NavyWrecksPropGenerator; import com.faforever.neroxis.generator.prop.NeutralCivPropGenerator; import com.faforever.neroxis.generator.prop.PropGenerator; import com.faforever.neroxis.generator.prop.RockFieldPropGenerator; import com.faforever.neroxis.generator.prop.SmallBattlePropGenerator; -import com.faforever.neroxis.generator.resource.ResourceGenerator; -import com.faforever.neroxis.generator.resource.RiversAndOceansMexResourceGenerator; -import com.faforever.neroxis.generator.terrain.FloodedMultiLevelLastTerrainGenerator; +import com.faforever.neroxis.generator.terrain.FractalUpsideDownLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.TerrainGenerator; -public class FloodedMultiLevelStyleGenerator extends StyleGenerator { +public class FractalUpsideDownStyleGenerator extends StyleGenerator { @Override protected WeightedOptionsWithFallback getTerrainGeneratorOptions() { - return WeightedOptionsWithFallback.of(new FloodedMultiLevelLastTerrainGenerator()); - } - - @Override - protected WeightedOptionsWithFallback getResourceGeneratorOptions() { - return WeightedOptionsWithFallback.of(new RiversAndOceansMexResourceGenerator()); + return WeightedOptionsWithFallback.of(new FractalUpsideDownLastTerrainGenerator()); } @Override protected WeightedOptionsWithFallback getPropGeneratorOptions() { return WeightedOptionsWithFallback.of(new BasicPropGenerator(), new WeightedOption<>(new BasicPropGenerator(), 1f), - new WeightedOption<>(new BoulderFieldPropGenerator(), .1f), + new WeightedOption<>(new BoulderFieldPropGenerator(), .5f), + new WeightedOption<>(new EnemyCivPropGenerator(), .5f), new WeightedOption<>(new HighReclaimPropGenerator(), .25f), new WeightedOption<>(new LargeBattlePropGenerator(), .5f), - new WeightedOption<>(new NavyWrecksPropGenerator(), 4f), + new WeightedOption<>(new NeutralCivPropGenerator(), 1f), new WeightedOption<>(new RockFieldPropGenerator(), 1f), new WeightedOption<>(new SmallBattlePropGenerator(), 1f)); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FloodedMultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FloodedMultiLevelLastTerrainGenerator.java deleted file mode 100644 index dddc5b64..00000000 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FloodedMultiLevelLastTerrainGenerator.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.faforever.neroxis.generator.terrain; - -import com.faforever.neroxis.generator.GeneratorParameters; -import com.faforever.neroxis.map.SCMap; -import com.faforever.neroxis.map.SymmetrySettings; -import com.faforever.neroxis.mask.BooleanMask; -import com.faforever.neroxis.util.Pipeline; -import com.faforever.neroxis.util.vector.Vector2; -import com.faforever.neroxis.util.vector.Vector3; - -public class FloodedMultiLevelLastTerrainGenerator extends MultiLevelLastTerrainGenerator { - @Override - public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, - SymmetrySettings symmetrySettings, Pipeline pipeline) { - super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); - - oceanFloor = -26f; - - waterHeight -= landNoiseMapFirstLevel - 2f; - - noiseScaleMaxToValue = 40; - landNoiseMapFirstLevel = 10; - landNoiseMapSecondLevel = 22; - landNoiseMapThirdLevel = 38; - } - - @Override - protected void mountainSetup() { - mountains.setSize(map.getSize() + 1); - } - - @Override - protected void landSetup() { - super.landSetup(); - - int mapSize = map.getSize(); - if (mapSize < 512) { - BooleanMask connectionsMask = connections.copy().dilute(1, 18).setSize(land.getSize()); - land.add(connectionsMask); - secondLevelLand.add(connectionsMask); - } - - map.getSpawns().forEach(spawn -> { - if (spawn.getTeamID() == 0) { - Vector3 location = spawn.getPosition(); - String brush = SPAWN_MASK_BRUSHES[StrictMath.abs(random.nextInt()) % SPAWN_MASK_BRUSHES.length]; - land.addBrush(new Vector2(location.x(), location.z()), brush, 15f, 256f, 200); - secondLevelLand.addBrush(new Vector2(location.x(), location.z()), brush, 15f, 256f, 200); - } - }); - } - - @Override - protected void setupSpawnMaskPipeline() { - spawnMask.init(secondLevelLand); - spawnMask.subtract(unbuildable); - spawnMask.deflate(10); - } - - @Override - protected int getTeamSeparation() { - if (generatorParameters.numTeams() < 2) { - return 0; - } else if (generatorParameters.numTeams() == 2) { - return map.getSize() / 4; - } else { - return StrictMath.min(map.getSize() / generatorParameters.numTeams(), 256); - } - } - -} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java new file mode 100644 index 00000000..ea5879d1 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java @@ -0,0 +1,24 @@ +package com.faforever.neroxis.generator.terrain; + +import com.faforever.neroxis.generator.FractalFlattenParams; +import com.faforever.neroxis.generator.FractalParams; +import com.faforever.neroxis.generator.GeneratorParameters; +import com.faforever.neroxis.map.SCMap; +import com.faforever.neroxis.map.SymmetrySettings; +import com.faforever.neroxis.util.Pipeline; + +public class FractalLandLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { + @Override + public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, + SymmetrySettings symmetrySettings, Pipeline pipeline) { + fractalParams = new FractalParams(0f, false, 1, 1.5f, 8, 2, new FractalFlattenParams[]{ + new FractalFlattenParams(0, 1, 0, 1, 0.5f, 0, true, true, 4), + new FractalFlattenParams(1, 4, 1, 1, 0, 0, false, false, 4), + new FractalFlattenParams(4, 6, 13, 13, 0, 2, false, false, 4), + new FractalFlattenParams(6, 15, 11, 11, 0, 0, false, false, 4), + new FractalFlattenParams(15, 22, 16, 16, 0, 1, false, false, 4), + }); + + super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); + } +} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java new file mode 100644 index 00000000..e99de810 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java @@ -0,0 +1,23 @@ +package com.faforever.neroxis.generator.terrain; + +import com.faforever.neroxis.generator.FractalFlattenParams; +import com.faforever.neroxis.generator.FractalParams; +import com.faforever.neroxis.generator.GeneratorParameters; +import com.faforever.neroxis.map.SCMap; +import com.faforever.neroxis.map.SymmetrySettings; +import com.faforever.neroxis.util.Pipeline; + +public class FractalNavyLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { + @Override + public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, + SymmetrySettings symmetrySettings, Pipeline pipeline) { + fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 1.0f, 0, 8, 0.25f, 0, false, false, 4), + new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), + new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), + }); + + super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); + } +} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index bde57891..a92be6bc 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -1,5 +1,7 @@ package com.faforever.neroxis.generator.terrain; +import com.faforever.neroxis.generator.FractalFlattenParams; +import com.faforever.neroxis.generator.FractalParams; import com.faforever.neroxis.generator.GeneratorParameters; import com.faforever.neroxis.map.SCMap; import com.faforever.neroxis.map.Symmetry; @@ -8,41 +10,17 @@ import com.faforever.neroxis.mask.FloatMask; import com.faforever.neroxis.mask.MapMaskMethods; import com.faforever.neroxis.util.Pipeline; +import com.faforever.neroxis.util.vector.Vector2; -import java.util.ArrayList; import java.util.Set; public class FractalNoiseLastTerrainGenerator extends MultiLevelLastTerrainGenerator { - private record FlattenParams( - float minHeight, - float maxHeight, - float destinationMinHeight, - float destinationMaxHeight, - float slope, - int blurAmount, - boolean hasRamps, - boolean spawnable, - float spawnMaskDeflate - ) {} - - private record FractalType( - float waterHeight, - boolean useRandomWaterMask, - int noiseMapBlurAmount, - float noiseOctaveMultiplier, - float noiseExpMultiplier, - float minSpawnable, - float maxSpawnable, - int teamSeparation, - FlattenParams[] flattenParams - ) {} - private BooleanMask symmetryLines; private FloatMask symmetryCliffs; private FloatMask rampNoise; - private FractalType fractalType; + protected FractalParams fractalParams; @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, @@ -54,62 +32,26 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame symmetryCliffs = new FloatMask(1, random.nextLong(), symmetrySettings, "symmetryCliffs", pipeline); rampNoise = new FloatMask(1, random.nextLong(), symmetrySettings, "rampNoise", pipeline); - ArrayList FRACTAL_TYPES = new ArrayList(); - // Basic Land - FRACTAL_TYPES.add(new FractalType(0f, false, 1, 1.5f, 8, 0, 1, 2, new FlattenParams[]{ - new FlattenParams(1, 4, 1, 1, 0, 0, false, false, 4), - new FlattenParams(4, 6, 13, 13, 0, 2, false, false, 4), - new FlattenParams(6, 15, 11, 11, 0, 0, false, false, 4), - new FlattenParams(15, 22, 16, 16, 0, 1, false, false, 4), - })); - // Plateau's - FRACTAL_TYPES.add(new FractalType(3f, false, 4, 1.2f, 4, 0, 0, 2, new FlattenParams[]{ - new FlattenParams(0f, 0.1f, 0, 4, 0.5f, 0, false, false, 4), - new FlattenParams(0.1f, 1.0f, 4, 15, 2, 0, true, false, 4), - new FlattenParams(1.0f, 27, 15, 15, 0, 0, false, true, 4), - new FlattenParams(27, 50, 24, 24, 0, 2, false, false, 4), - })); - // Navy - FRACTAL_TYPES.add(new FractalType(16, true, 2, 1.5f, 6, 0, 0, 3, new FlattenParams[]{ - new FlattenParams(0f, 1.0f, 0, 8, 0.25f, 0, false, false, 4), - new FlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), - new FlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), - new FlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), - })); - // The Upside - Down - FRACTAL_TYPES.add(new FractalType(2, false, 2, 1.2f, 3, 0, 0, 3, new FlattenParams[]{ - new FlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), - new FlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), - new FlattenParams(15f, 50f, 13, 12.5f, 0.5f, 1, false, false, 4), - })); - - - - - fractalType = FRACTAL_TYPES.get(random.nextInt(FRACTAL_TYPES.size())); - //fractalType = FRACTAL_TYPES.get(2); - System.out.println("FractalType : " + fractalType); - if (fractalType.useRandomWaterMask) { + if (fractalParams.useRandomWaterMask()) { waterMask = WaterMasks.values()[random.nextInt(WaterMasks.values().length)]; System.out.println("WaterMask: " + waterMask.name()); } - System.out.println(fractalType); - for (FlattenParams fp : fractalType.flattenParams) { + for (FractalFlattenParams fp : fractalParams.fractalFlattenParams()) { System.out.println("FlattenParam: " + fp); } noiseSmallestDetail = 2; - noiseOctaveMultiplier = fractalType.noiseOctaveMultiplier; + noiseOctaveMultiplier = fractalParams.noiseOctaveMultiplier(); - noiseMapBlurAmount = fractalType.noiseMapBlurAmount; + noiseMapBlurAmount = fractalParams.noiseMapBlurAmount(); noiseScaleMaxToValue = 50; mountainBrushSize = 24; mountainBrushDensity = 8f; mountainBrushIntensity = 3f; - waterHeight -= fractalType.waterHeight; + waterHeight -= fractalParams.waterHeight(); symmetryLines.setSize(map.getSize() + 1); symmetryLines.drawSymmetryLines(); @@ -120,7 +62,7 @@ protected void landSetup() { super.landSetup(); landNoiseMap.scaleToNewMinAndMaxHeight(0, 1); - landNoiseMap.scaleExponentially(fractalType.noiseExpMultiplier); + landNoiseMap.scaleExponentially(fractalParams.noiseExpMultiplier()); landNoiseMap.scaleToNewMinAndMaxHeight(0, noiseScaleMaxToValue); } @@ -152,9 +94,9 @@ protected void initRamps() { rampNoise.startVisualDebugger("Ramp Noise: "); ramps.setSize(landNoiseMap.getSize()); - for (FlattenParams flattenParams : fractalType.flattenParams) { - if (flattenParams.hasRamps) { - BooleanMask layer = landNoiseMap.copyAsBooleanMask(0f, flattenParams.maxHeight); + for (FractalFlattenParams fractalFlattenParams : fractalParams.fractalFlattenParams()) { + if (fractalFlattenParams.hasRamps()) { + BooleanMask layer = landNoiseMap.copyAsBooleanMask(0f, fractalFlattenParams.maxHeight()); layer.startVisualDebugger(); layer.outline(); @@ -195,11 +137,11 @@ protected void setupHeightmapPipeline() { // Start the land height as the noise map heightmapLand.add(landNoiseMap); - for (FlattenParams flattenParams : fractalType.flattenParams) { - MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, flattenParams.minHeight, - flattenParams.maxHeight, flattenParams.destinationMinHeight, - flattenParams.destinationMaxHeight, - flattenParams.slope, flattenParams.blurAmount); + for (FractalFlattenParams fractalFlattenParams : fractalParams.fractalFlattenParams()) { + MapMaskMethods.flattenHeightBand(heightmapLand, landNoiseMap, fractalFlattenParams.minHeight(), + fractalFlattenParams.maxHeight(), fractalFlattenParams.destinationMinHeight(), + fractalFlattenParams.destinationMaxHeight(), + fractalFlattenParams.slope(), fractalFlattenParams.blurAmount()); } @@ -246,13 +188,10 @@ protected void setupSpawnMaskPipeline() { spawnMask.startVisualDebugger("Spawn Mask: "); - if (fractalType.maxSpawnable > fractalType.minSpawnable) { - spawnMask.add(landNoiseMap.copyAsBooleanMask(fractalType.minSpawnable, fractalType.maxSpawnable)); - } - for (FlattenParams flattenParams : fractalType.flattenParams) { - if (flattenParams.spawnable) { - spawnMask.add(landNoiseMap.copyAsBooleanMask(flattenParams.minHeight, flattenParams.maxHeight) - .deflate(flattenParams.spawnMaskDeflate)); + for (FractalFlattenParams fractalFlattenParams : fractalParams.fractalFlattenParams()) { + if (fractalFlattenParams.spawnable()) { + spawnMask.add(landNoiseMap.copyAsBooleanMask(fractalFlattenParams.minHeight(), fractalFlattenParams.maxHeight()) + .deflate(fractalFlattenParams.spawnMaskDeflate())); } } @@ -265,7 +204,7 @@ protected int getTeamSeparation() { if (generatorParameters.numTeams() < 2) { return 0; } else if (generatorParameters.numTeams() == 2) { - return map.getSize() / fractalType.teamSeparation; + return map.getSize() / fractalParams.teamSeparation(); } else { return StrictMath.min(map.getSize() / generatorParameters.numTeams(), 256); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java new file mode 100644 index 00000000..73893458 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java @@ -0,0 +1,23 @@ +package com.faforever.neroxis.generator.terrain; + +import com.faforever.neroxis.generator.FractalFlattenParams; +import com.faforever.neroxis.generator.FractalParams; +import com.faforever.neroxis.generator.GeneratorParameters; +import com.faforever.neroxis.map.SCMap; +import com.faforever.neroxis.map.SymmetrySettings; +import com.faforever.neroxis.util.Pipeline; + +public class FractalPlateauLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { + @Override + public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, + SymmetrySettings symmetrySettings, Pipeline pipeline) { + fractalParams = new FractalParams(3f, false, 4, 1.2f, 4, 2, new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 0.1f, 0, 4, 0.5f, 0, false, false, 4), + new FractalFlattenParams(0.1f, 1.0f, 4, 14, 2, 0, true, false, 4), + new FractalFlattenParams(1.0f, 27, 14, 15, 1f, 0, false, true, 4), + new FractalFlattenParams(27, 50, 24, 24, 0, 2, false, false, 4), + }); + + super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); + } +} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java new file mode 100644 index 00000000..78983303 --- /dev/null +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java @@ -0,0 +1,22 @@ +package com.faforever.neroxis.generator.terrain; + +import com.faforever.neroxis.generator.FractalFlattenParams; +import com.faforever.neroxis.generator.FractalParams; +import com.faforever.neroxis.generator.GeneratorParameters; +import com.faforever.neroxis.map.SCMap; +import com.faforever.neroxis.map.SymmetrySettings; +import com.faforever.neroxis.util.Pipeline; + +public class FractalUpsideDownLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { + @Override + public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, + SymmetrySettings symmetrySettings, Pipeline pipeline) { + fractalParams = new FractalParams(2, false, 2, 1.2f, 3, 3, new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), + new FractalFlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), + new FractalFlattenParams(15f, 50f, 13, 12.5f, 0.5f, 1, false, false, 4), + }); + + super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); + } +} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java index d4e8c26c..eb34f5a1 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java @@ -90,8 +90,9 @@ protected void landSetup() { float amplitude = 1f; landNoiseMap.setSize(mapSize + 1); - // For water only + // For water only, we can influence the likelihood of water to occur for different areas of the map if (waterMask == WaterMasks.SYMMETRY_LINE) { + // Water will be more likely along the symmetry line(s), kinda splitting the map in half, or pie slices for odd symmetries BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); waterArea.drawSymmetryLines(); @@ -101,6 +102,7 @@ protected void landSetup() { landNoiseMap.add(1f); landNoiseMap.subtract(waterAreaBlur); } else if (waterMask == WaterMasks.HOUR_GLASS) { + // An unusual shape, which increase the likelihood of water along the symmetry lines and the corners of the map BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); waterArea.drawSymmetryLines(); @@ -116,6 +118,7 @@ protected void landSetup() { landNoiseMap.add(1f); landNoiseMap.subtract(waterAreaBlur); } else if (waterMask == WaterMasks.CENTER_LAKE) { + // big ocean in the centre of the map BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); waterArea.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 3f, true); From b4df4f8f7862d6d9d19fac40fb7cb774ac0b2e5c Mon Sep 17 00:00:00 2001 From: clive Date: Sun, 9 Nov 2025 19:09:51 +0800 Subject: [PATCH 04/12] full cleanup --- .../faforever/neroxis/generator/MapStyle.java | 16 ++-- .../FractalNoiseLastTerrainGenerator.java | 20 +---- .../MultiLevelLastTerrainGenerator.java | 82 +++++++++---------- 3 files changed, 52 insertions(+), 66 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java b/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java index 1ab45881..0d1a4a9d 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java @@ -4,9 +4,11 @@ import com.faforever.neroxis.generator.style.BigIslandsStyleGenerator; import com.faforever.neroxis.generator.style.CenterLakeStyleGenerator; import com.faforever.neroxis.generator.style.DropPlateauStyleGenerator; -import com.faforever.neroxis.generator.style.FloodedMultiLevelStyleGenerator; import com.faforever.neroxis.generator.style.FloodedStyleGenerator; -import com.faforever.neroxis.generator.style.FractalNoiseStyleGenerator; +import com.faforever.neroxis.generator.style.FractalLandStyleGenerator; +import com.faforever.neroxis.generator.style.FractalNavyStyleGenerator; +import com.faforever.neroxis.generator.style.FractalPlateauStyleGenerator; +import com.faforever.neroxis.generator.style.FractalUpsideDownStyleGenerator; import com.faforever.neroxis.generator.style.HighReclaimStyleGenerator; import com.faforever.neroxis.generator.style.LandBridgeStyleGenerator; import com.faforever.neroxis.generator.style.LittleMountainStyleGenerator; @@ -27,24 +29,26 @@ @Getter @AllArgsConstructor public enum MapStyle { - BASIC(BasicStyleGenerator::new, 1), + BASIC(BasicStyleGenerator::new, 2f), BIG_ISLANDS(BigIslandsStyleGenerator::new, 1), CENTER_LAKE(CenterLakeStyleGenerator::new, 1), DROP_PLATEAU(DropPlateauStyleGenerator::new, .5f), - FLOODED(FloodedStyleGenerator::new, .01f), + FLOODED(FloodedStyleGenerator::new, 0.5f), HIGH_RECLAIM(HighReclaimStyleGenerator::new, .25f), LAND_BRIDGE(LandBridgeStyleGenerator::new, 2), LITTLE_MOUNTAIN(LittleMountainStyleGenerator::new, 1), LOW_MEX(LowMexStyleGenerator::new, .5f), MOUNTAIN_RANGE(MountainRangeStyleGenerator::new, 1), MULTILEVEL(MultiLevelStyleGenerator::new, 1f), - FLOODED_MULTILEVEL(FloodedMultiLevelStyleGenerator::new, 0.75f), ONE_ISLAND(OneIslandStyleGenerator::new, 1), SMALL_ISLANDS(SmallIslandsStyleGenerator::new, 1), VALLEY(ValleyStyleGenerator::new, 1), RIVERS(RiversStyleGenerator::new, 0.25f), RIVERS_AND_OCEANS(RiversAndOceansStyleGenerator::new, 0.75f), - FRACTAL(FractalNoiseStyleGenerator::new, 1f); + FRACTAL_LAND(FractalLandStyleGenerator::new, 0.25f), + FRACTAL_PLATEAU(FractalPlateauStyleGenerator::new, 0.25f), + FRACTAL_NAVY(FractalNavyStyleGenerator::new, 0.01f), + FRACTAL_UPSIDE_DOWN(FractalUpsideDownStyleGenerator::new, 0.25f); private final Supplier generatorSupplier; private final float weight; diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index a92be6bc..86ef5305 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -26,7 +26,6 @@ public class FractalNoiseLastTerrainGenerator extends MultiLevelLastTerrainGener public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); - pipeline.setDebug(true); symmetryLines = new BooleanMask(1, random.nextLong(), symmetrySettings, "symmetryLines", pipeline); symmetryCliffs = new FloatMask(1, random.nextLong(), symmetrySettings, "symmetryCliffs", pipeline); @@ -34,14 +33,9 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame if (fractalParams.useRandomWaterMask()) { waterMask = WaterMasks.values()[random.nextInt(WaterMasks.values().length)]; - System.out.println("WaterMask: " + waterMask.name()); - } - for (FractalFlattenParams fp : fractalParams.fractalFlattenParams()) { - System.out.println("FlattenParam: " + fp); } noiseSmallestDetail = 2; - noiseOctaveMultiplier = fractalParams.noiseOctaveMultiplier(); noiseMapBlurAmount = fractalParams.noiseMapBlurAmount(); @@ -69,7 +63,6 @@ protected void landSetup() { @Override protected void mountainSetup() { symmetryCliffs = landNoiseMap.copy(); - symmetryCliffs.setVisualName("Symmetry Cliffs: "); symmetryCliffs.supcomGradient(); symmetryCliffs.setToValue(symmetryLines.copy().inflate(3).invert(), 0f); @@ -90,14 +83,11 @@ protected void setupMountainHeightmapPipeline() { @Override protected void initRamps() { - ramps.startVisualDebugger("Ramps: "); - rampNoise.startVisualDebugger("Ramp Noise: "); ramps.setSize(landNoiseMap.getSize()); for (FractalFlattenParams fractalFlattenParams : fractalParams.fractalFlattenParams()) { if (fractalFlattenParams.hasRamps()) { BooleanMask layer = landNoiseMap.copyAsBooleanMask(0f, fractalFlattenParams.maxHeight()); - layer.startVisualDebugger(); layer.outline(); rampNoise.setSize(landNoiseMap.getSize() / 16); @@ -128,10 +118,8 @@ protected void setupHeightmapPipeline() { initRamps(); - landNoiseMap.startVisualDebugger("LandNoiseMap: "); - heightmap.setSize(mapSize + 1); - heightmapLand.setSize(mapSize + 1).startVisualDebugger("Heightmap Land: "); + heightmapLand.setSize(mapSize + 1); heightMapNoise.setSize(mapSize / 128); // Start the land height as the noise map @@ -173,8 +161,9 @@ protected void setupHeightmapPipeline() { } if (symmetrySettings.spawnSymmetry().getNumSymPoints() == 3 || symmetrySettings.spawnSymmetry().getNumSymPoints() >= 5) { + // For the odd symmetry, pie shaped maps, we need to limit the terrain to a circle with the full diameter of the map BooleanMask outerCircle = new BooleanMask(mapSize + 1, random.nextLong(), symmetrySettings, "outerCircle", pipeline); - outerCircle.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 2f, true).startVisualDebugger(); + outerCircle.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 2f, true); outerCircle.invert(); heightmap.setToValue(outerCircle, waterHeight); heightmap.blur(5, outerCircle.outline().inflate(5)); @@ -185,9 +174,6 @@ protected void setupHeightmapPipeline() { @Override protected void setupSpawnMaskPipeline() { - - spawnMask.startVisualDebugger("Spawn Mask: "); - for (FractalFlattenParams fractalFlattenParams : fractalParams.fractalFlattenParams()) { if (fractalFlattenParams.spawnable()) { spawnMask.add(landNoiseMap.copyAsBooleanMask(fractalFlattenParams.minHeight(), fractalFlattenParams.maxHeight()) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java index eb34f5a1..b97224b3 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java @@ -35,19 +35,12 @@ protected enum WaterMasks { protected float landNoiseMapFirstLevel; protected float landNoiseMapSecondLevel; protected float landNoiseMapThirdLevel; + protected FloatMask waterAreaBlur; protected FloatMask rampExclusion; protected Pipeline pipeline; - String[] SPAWN_MASK_BRUSHES = { - "mountain4.png", - "mountain6.png", - "mountain7.png", - "mountain8.png", - "mountain9.png", - }; - @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { @@ -57,6 +50,7 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame secondLevelLand = new BooleanMask(1, random.nextLong(), symmetrySettings, "secondLevelLand", pipeline); thirdLevelLand = new BooleanMask(1, random.nextLong(), symmetrySettings, "thirdLevelLand", pipeline); rampExclusion = new FloatMask(1, random.nextLong(), symmetrySettings,"rampExclusion", pipeline); + waterAreaBlur = new FloatMask(1, random.nextLong(), symmetrySettings,"waterAreaBlur", pipeline); noiseSmallestDetail = 5; noiseOctaveMultiplier = 1.0f; @@ -90,21 +84,48 @@ protected void landSetup() { float amplitude = 1f; landNoiseMap.setSize(mapSize + 1); + if (waterMask != WaterMasks.NONE) { + addWaterAreasToNoiseMap(mapSize); + } + + for (int octave = 0; octave < numOctaves; octave++) { + FloatMask octaveNoise = new FloatMask(mapSize + 1, getRandom().nextLong(), land.getSymmetrySettings(), + "landNoiseOctave" + octave, pipeline); + octaveNoise.addPerlinNoise(noiseSmallestDetail << octave, 1f / numOctaves); + octaveNoise.multiply(amplitude); + landNoiseMap.add(octaveNoise); + amplitude *= noiseOctaveMultiplier; + } + landNoiseMap.blur(noiseMapBlurAmount); + + + landNoiseMap.scaleToNewMinAndMaxHeight(0, noiseScaleMaxToValue); + + land = landNoiseMap + .copyAsBooleanMask(landNoiseMapFirstLevel) + .erode(0.3f, 10); + secondLevelLand = landNoiseMap + .copyAsBooleanMask(landNoiseMapSecondLevel) + .erode(0.3f, 10); + thirdLevelLand = landNoiseMap + .copyAsBooleanMask(landNoiseMapThirdLevel) + .erode(0.3f, 10); + } + + private void addWaterAreasToNoiseMap(int mapSize) { // For water only, we can influence the likelihood of water to occur for different areas of the map if (waterMask == WaterMasks.SYMMETRY_LINE) { // Water will be more likely along the symmetry line(s), kinda splitting the map in half, or pie slices for odd symmetries BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, - "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); + "symmetryLines", pipeline); waterArea.drawSymmetryLines(); waterArea.inflate(mapSize / 3f / symmetrySettings.teamSymmetry().getNumSymPoints()); - FloatMask waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f).startVisualDebugger("WaterAreaBlur: "); + waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); waterAreaBlur.blur(mapSize / 4); - landNoiseMap.add(1f); - landNoiseMap.subtract(waterAreaBlur); } else if (waterMask == WaterMasks.HOUR_GLASS) { // An unusual shape, which increase the likelihood of water along the symmetry lines and the corners of the map BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, - "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); + "symmetryLines", pipeline); waterArea.drawSymmetryLines(); waterArea.inflate(mapSize / 12f); List symmetryPoints = waterArea.getSymmetryPointsWithOutOfBounds(new Vector2(0, 0), SymmetryType.SPAWN) @@ -113,43 +134,18 @@ protected void landSetup() { .toList(); waterArea.fillCircle(new Vector2(0, 0), mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true); symmetryPoints.forEach(s -> waterArea.fillCircle(s, mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true)); - FloatMask waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f).startVisualDebugger("WaterAreaBlur: "); + waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); waterAreaBlur.blur(mapSize / 3 / symmetrySettings.teamSymmetry().getNumSymPoints()); - landNoiseMap.add(1f); - landNoiseMap.subtract(waterAreaBlur); } else if (waterMask == WaterMasks.CENTER_LAKE) { // big ocean in the centre of the map BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, - "symmetryLines", pipeline).startVisualDebugger("WaterArea: "); + "symmetryLines", pipeline); waterArea.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 3f, true); - FloatMask waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f).startVisualDebugger("WaterAreaBlur: "); + waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); waterAreaBlur.blur(mapSize / 4); - landNoiseMap.add(1f); - landNoiseMap.subtract(waterAreaBlur); } - - for (int octave = 0; octave < numOctaves; octave++) { - FloatMask octaveNoise = new FloatMask(mapSize + 1, getRandom().nextLong(), land.getSymmetrySettings(), - "landNoiseOctave" + octave, pipeline); - octaveNoise.addPerlinNoise(noiseSmallestDetail << octave, 1f / numOctaves); - octaveNoise.multiply(amplitude); - landNoiseMap.add(octaveNoise); - amplitude *= noiseOctaveMultiplier; - } - landNoiseMap.blur(noiseMapBlurAmount); - - - landNoiseMap.scaleToNewMinAndMaxHeight(0, noiseScaleMaxToValue); - - land = landNoiseMap - .copyAsBooleanMask(landNoiseMapFirstLevel) - .erode(0.3f, 10); - secondLevelLand = landNoiseMap - .copyAsBooleanMask(landNoiseMapSecondLevel) - .erode(0.3f, 10); - thirdLevelLand = landNoiseMap - .copyAsBooleanMask(landNoiseMapThirdLevel) - .erode(0.3f, 10); + landNoiseMap.add(1f); + landNoiseMap.subtract(waterAreaBlur); } @Override From abb27ce2e7a280223de6a7bcaae0cd38f87ba093 Mon Sep 17 00:00:00 2001 From: clive Date: Sun, 9 Nov 2025 21:27:59 +0800 Subject: [PATCH 05/12] Some work on Navy, it's much better for gameplay and balance with more mexes --- .../neroxis/generator/ResourceStyle.java | 4 +++- ...hMexLandLowMexWaterResourceGenerator.java} | 3 ++- .../style/FractalNavyStyleGenerator.java | 7 ++++++ .../style/RiversAndOceansStyleGenerator.java | 4 ++-- .../FractalNavyLastTerrainGenerator.java | 24 ++++++++++++++----- .../MultiLevelLastTerrainGenerator.java | 9 +++---- 6 files changed, 35 insertions(+), 16 deletions(-) rename generator/src/main/java/com/faforever/neroxis/generator/resource/{RiversAndOceansMexResourceGenerator.java => HighMexLandLowMexWaterResourceGenerator.java} (90%) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/ResourceStyle.java b/generator/src/main/java/com/faforever/neroxis/generator/ResourceStyle.java index 1bff5877..d0cb802f 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/ResourceStyle.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/ResourceStyle.java @@ -1,6 +1,7 @@ package com.faforever.neroxis.generator; import com.faforever.neroxis.generator.resource.BasicResourceGenerator; +import com.faforever.neroxis.generator.resource.HighMexLandLowMexWaterResourceGenerator; import com.faforever.neroxis.generator.resource.LowMexResourceGenerator; import com.faforever.neroxis.generator.resource.WaterMexResourceGenerator; import lombok.AllArgsConstructor; @@ -13,7 +14,8 @@ public enum ResourceStyle { BASIC(BasicResourceGenerator::new), LOW_MEX(LowMexResourceGenerator::new), - WATER_MEX(WaterMexResourceGenerator::new); + WATER_MEX(WaterMexResourceGenerator::new), + HI_MEX_LAND_LOW_MEX_WATER(HighMexLandLowMexWaterResourceGenerator::new); private final Supplier generatorSupplier; } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/resource/RiversAndOceansMexResourceGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java similarity index 90% rename from generator/src/main/java/com/faforever/neroxis/generator/resource/RiversAndOceansMexResourceGenerator.java rename to generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java index 7bd09468..9e986c2d 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/resource/RiversAndOceansMexResourceGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java @@ -7,7 +7,7 @@ import com.faforever.neroxis.mask.FloatMask; import com.faforever.neroxis.util.Pipeline; -public class RiversAndOceansMexResourceGenerator extends BasicResourceGenerator { +public class HighMexLandLowMexWaterResourceGenerator extends BasicResourceGenerator { private FloatMask waterResourceLimitNoiseMask; @@ -16,6 +16,7 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame super.initialize(map, seed, generatorParameters, symmetrySettings, terrainGenerator, pipeline); waterResourceLimitNoiseMask = new FloatMask(1, random.nextLong(), symmetrySettings, "waterResourceLimitNoiseMask", pipeline); + resourceDensity = random.nextFloat(1.5f, 2.0f); } @Override diff --git a/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java index 861e4aa7..2534b966 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/style/FractalNavyStyleGenerator.java @@ -10,10 +10,17 @@ import com.faforever.neroxis.generator.prop.PropGenerator; import com.faforever.neroxis.generator.prop.RockFieldPropGenerator; import com.faforever.neroxis.generator.prop.SmallBattlePropGenerator; +import com.faforever.neroxis.generator.resource.ResourceGenerator; +import com.faforever.neroxis.generator.resource.HighMexLandLowMexWaterResourceGenerator; import com.faforever.neroxis.generator.terrain.FractalNavyLastTerrainGenerator; import com.faforever.neroxis.generator.terrain.TerrainGenerator; public class FractalNavyStyleGenerator extends StyleGenerator { + @Override + protected WeightedOptionsWithFallback getResourceGeneratorOptions() { + return WeightedOptionsWithFallback.of(new HighMexLandLowMexWaterResourceGenerator()); + } + @Override protected WeightedOptionsWithFallback getTerrainGeneratorOptions() { return WeightedOptionsWithFallback.of(new FractalNavyLastTerrainGenerator()); diff --git a/generator/src/main/java/com/faforever/neroxis/generator/style/RiversAndOceansStyleGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/style/RiversAndOceansStyleGenerator.java index 5f63b1c7..22b8f937 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/style/RiversAndOceansStyleGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/style/RiversAndOceansStyleGenerator.java @@ -13,7 +13,7 @@ import com.faforever.neroxis.generator.prop.RockFieldPropGenerator; import com.faforever.neroxis.generator.prop.SmallBattlePropGenerator; import com.faforever.neroxis.generator.resource.ResourceGenerator; -import com.faforever.neroxis.generator.resource.RiversAndOceansMexResourceGenerator; +import com.faforever.neroxis.generator.resource.HighMexLandLowMexWaterResourceGenerator; import com.faforever.neroxis.generator.terrain.RiversAndOceansTerrainGenerator; import com.faforever.neroxis.generator.terrain.TerrainGenerator; @@ -21,7 +21,7 @@ public class RiversAndOceansStyleGenerator extends StyleGenerator { @Override protected WeightedOptionsWithFallback getResourceGeneratorOptions() { - return WeightedOptionsWithFallback.of(new RiversAndOceansMexResourceGenerator()); + return WeightedOptionsWithFallback.of(new HighMexLandLowMexWaterResourceGenerator()); } @Override diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java index e99de810..eaef6b6e 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java @@ -11,12 +11,24 @@ public class FractalNavyLastTerrainGenerator extends FractalNoiseLastTerrainGene @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { - fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ - new FractalFlattenParams(0f, 1.0f, 0, 8, 0.25f, 0, false, false, 4), - new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), - new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), - new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), - }); + if (map.getSize() < 512) { + // Small maps are very problematic, because of a lack of spawnable land area, and low mex count + // This increases the area of the map dedicated to spawnable land and mexes + fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 0.5f, 0, 8, 0.25f, 0, false, false, 4), + new FractalFlattenParams(0.5f, 1f, 8, 16, 1f, 0, true, false, 4), + new FractalFlattenParams(1f, 27, 18, 18, 0, 1, false, true, 8), + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), + }); + } else { + // This is a fractal navy map, works well for 10K - 20K maps, with a good amount of the map being ocean. + fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 1.0f, 0, 8, 0.25f, 0, false, false, 4), + new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), + new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), + }); + } super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java index b97224b3..c41d216e 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java @@ -22,6 +22,7 @@ protected enum WaterMasks { } protected WaterMasks waterMask; + protected BooleanMask waterArea; protected BooleanMask secondLevelLand; protected BooleanMask thirdLevelLand; @@ -51,6 +52,7 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame thirdLevelLand = new BooleanMask(1, random.nextLong(), symmetrySettings, "thirdLevelLand", pipeline); rampExclusion = new FloatMask(1, random.nextLong(), symmetrySettings,"rampExclusion", pipeline); waterAreaBlur = new FloatMask(1, random.nextLong(), symmetrySettings,"waterAreaBlur", pipeline); + waterArea = new BooleanMask(1, random.nextLong(), symmetrySettings,"waterArea", pipeline); noiseSmallestDetail = 5; noiseOctaveMultiplier = 1.0f; @@ -114,18 +116,15 @@ protected void landSetup() { private void addWaterAreasToNoiseMap(int mapSize) { // For water only, we can influence the likelihood of water to occur for different areas of the map + waterArea.setSize(mapSize + 1); if (waterMask == WaterMasks.SYMMETRY_LINE) { // Water will be more likely along the symmetry line(s), kinda splitting the map in half, or pie slices for odd symmetries - BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, - "symmetryLines", pipeline); waterArea.drawSymmetryLines(); waterArea.inflate(mapSize / 3f / symmetrySettings.teamSymmetry().getNumSymPoints()); waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); waterAreaBlur.blur(mapSize / 4); } else if (waterMask == WaterMasks.HOUR_GLASS) { // An unusual shape, which increase the likelihood of water along the symmetry lines and the corners of the map - BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, - "symmetryLines", pipeline); waterArea.drawSymmetryLines(); waterArea.inflate(mapSize / 12f); List symmetryPoints = waterArea.getSymmetryPointsWithOutOfBounds(new Vector2(0, 0), SymmetryType.SPAWN) @@ -138,8 +137,6 @@ private void addWaterAreasToNoiseMap(int mapSize) { waterAreaBlur.blur(mapSize / 3 / symmetrySettings.teamSymmetry().getNumSymPoints()); } else if (waterMask == WaterMasks.CENTER_LAKE) { // big ocean in the centre of the map - BooleanMask waterArea = new BooleanMask(landNoiseMap.getSize(), random.nextLong(), symmetrySettings, - "symmetryLines", pipeline); waterArea.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 3f, true); waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); waterAreaBlur.blur(mapSize / 4); From 3aaa7de7eac382864a6d00898f9c0ae908e4bd2e Mon Sep 17 00:00:00 2001 From: clive Date: Mon, 10 Nov 2025 20:51:11 +0800 Subject: [PATCH 06/12] more work on the navy, I think I've got the mex distribution issues fixed now --- .../faforever/neroxis/generator/MapStyle.java | 2 +- ...ghMexLandLowMexWaterResourceGenerator.java | 20 ++++++++++++++++++- .../FractalNavyLastTerrainGenerator.java | 2 +- .../FractalNoiseLastTerrainGenerator.java | 6 +++++- .../MultiLevelLastTerrainGenerator.java | 4 ++-- .../neroxis/map/placement/MexPlacer.java | 13 ++++++++---- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java b/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java index 0d1a4a9d..142f491a 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/MapStyle.java @@ -47,7 +47,7 @@ public enum MapStyle { RIVERS_AND_OCEANS(RiversAndOceansStyleGenerator::new, 0.75f), FRACTAL_LAND(FractalLandStyleGenerator::new, 0.25f), FRACTAL_PLATEAU(FractalPlateauStyleGenerator::new, 0.25f), - FRACTAL_NAVY(FractalNavyStyleGenerator::new, 0.01f), + FRACTAL_NAVY(FractalNavyStyleGenerator::new, 0.25f), FRACTAL_UPSIDE_DOWN(FractalUpsideDownStyleGenerator::new, 0.25f); private final Supplier generatorSupplier; diff --git a/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java index 9e986c2d..7daab31f 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java @@ -5,6 +5,7 @@ import com.faforever.neroxis.map.SCMap; import com.faforever.neroxis.map.SymmetrySettings; import com.faforever.neroxis.mask.FloatMask; +import com.faforever.neroxis.util.DebugUtil; import com.faforever.neroxis.util.Pipeline; public class HighMexLandLowMexWaterResourceGenerator extends BasicResourceGenerator { @@ -19,6 +20,23 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame resourceDensity = random.nextFloat(1.5f, 2.0f); } + @Override + public void placeResources() { + DebugUtil.timedRun("com.faforever.neroxis.map.generator", "generateResources", () -> { + mexPlacer.placeMexes(getMexCount(), resourceMask.getFinalMask(), waterResourceMask.getFinalMask(), 12, 12, 12); + hydroPlacer.placeHydros(generatorParameters.spawnCount(), resourceMask.getFinalMask().deflate(8)); + }); + } + + @Override + protected int getMexCount() { + int mapSize = generatorParameters.mapSize(); + int spawnCount = generatorParameters.spawnCount(); + + // 4 mexes per player, and about 24 mexes per 256 chunk of the map multiplied by resource density + return (spawnCount * 4) + StrictMath.round( (mapSize / 256f) * 24f * resourceDensity); + } + @Override public void setupPipeline() { waterResourceLimitNoiseMask.setSize(passableLand.getSize()); @@ -27,7 +45,7 @@ public void setupPipeline() { resourceMask.init(passableLand); resourceMask.add(passableWater .copy() - .subtract(waterResourceLimitNoiseMask.copyAsBooleanMask(0.01f))); + .subtract(waterResourceLimitNoiseMask.copyAsBooleanMask(0.1f))); resourceMask.subtract(unbuildable.copy().inflate(2)); waterResourceMask.setSize(resourceMask.getSize()); diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java index eaef6b6e..28fbe06d 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java @@ -23,7 +23,7 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame } else { // This is a fractal navy map, works well for 10K - 20K maps, with a good amount of the map being ocean. fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ - new FractalFlattenParams(0f, 1.0f, 0, 8, 0.25f, 0, false, false, 4), + new FractalFlattenParams(0f, 1.0f, 0, 8, 1f, 0, false, false, 4), new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index 86ef5305..1dfd5b4d 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -32,7 +32,11 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame rampNoise = new FloatMask(1, random.nextLong(), symmetrySettings, "rampNoise", pipeline); if (fractalParams.useRandomWaterMask()) { - waterMask = WaterMasks.values()[random.nextInt(WaterMasks.values().length)]; + switch (random.nextInt(1,3)) { + case 1: waterMask = WaterMasks.SYMMETRY_LINE; break; + case 2: waterMask = WaterMasks.HOUR_GLASS; break; + case 3: waterMask = WaterMasks.CENTER_LAKE; break; + } } noiseSmallestDetail = 2; diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java index c41d216e..61fa7a27 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java @@ -120,13 +120,13 @@ private void addWaterAreasToNoiseMap(int mapSize) { if (waterMask == WaterMasks.SYMMETRY_LINE) { // Water will be more likely along the symmetry line(s), kinda splitting the map in half, or pie slices for odd symmetries waterArea.drawSymmetryLines(); - waterArea.inflate(mapSize / 3f / symmetrySettings.teamSymmetry().getNumSymPoints()); + waterArea.inflate(StrictMath.min(256,mapSize / 4f / symmetrySettings.teamSymmetry().getNumSymPoints())); waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); waterAreaBlur.blur(mapSize / 4); } else if (waterMask == WaterMasks.HOUR_GLASS) { // An unusual shape, which increase the likelihood of water along the symmetry lines and the corners of the map waterArea.drawSymmetryLines(); - waterArea.inflate(mapSize / 12f); + waterArea.inflate(mapSize / 4f / symmetrySettings.teamSymmetry().getNumSymPoints()); List symmetryPoints = waterArea.getSymmetryPointsWithOutOfBounds(new Vector2(0, 0), SymmetryType.SPAWN) .stream() .map(Vector2::roundToNearestHalfPoint) diff --git a/shared/src/main/java/com/faforever/neroxis/map/placement/MexPlacer.java b/shared/src/main/java/com/faforever/neroxis/map/placement/MexPlacer.java index 7b39c17e..7ef6e28c 100644 --- a/shared/src/main/java/com/faforever/neroxis/map/placement/MexPlacer.java +++ b/shared/src/main/java/com/faforever/neroxis/map/placement/MexPlacer.java @@ -22,9 +22,14 @@ public MexPlacer(SCMap map, long seed) { } public void placeMexes(int mexCount, BooleanMask spawnMask, BooleanMask spawnMaskWater) { - map.getMexes().clear(); int mexSpacing = (int) (map.getSize() / 8f * StrictMath.min( - StrictMath.max(40f / (mexCount * map.getSpawnCount()), .25f), 2f)); + StrictMath.max(40f / (mexCount * map.getSpawnCount()), .25f), 2f)) / 2; + placeMexes(mexCount, spawnMask, spawnMaskWater, mexSpacing, 24, 48); + } + + public void placeMexes(int mexCount, BooleanMask spawnMask, BooleanMask spawnMaskWater, int mexSpacing, int spawnMexRadius, int remainingMexRadius) { + map.getMexes().clear(); + if (!spawnMask.getSymmetrySettings().spawnSymmetry().isPerfectSymmetry()) { spawnMask.limitToCenteredCircle(spawnMask.getSize() / 2f); } @@ -38,7 +43,7 @@ public void placeMexes(int mexCount, BooleanMask spawnMask, BooleanMask spawnMas map.getSpawns() .stream() .filter(spawn -> spawnMask.inTeam(spawn.getPosition(), false)) - .forEach(spawn -> spawnMask.fillCircle(spawn.getPosition(), 24, false)); + .forEach(spawn -> spawnMask.fillCircle(spawn.getPosition(), spawnMexRadius, false)); previousMexCount = map.getMexCount(); if (numMexesLeft > 8 && numMexesLeft > map.getSpawnCount()) { @@ -77,7 +82,7 @@ public void placeMexes(int mexCount, BooleanMask spawnMask, BooleanMask spawnMas map.getSpawns() .stream() .filter(spawn -> spawnMask.inTeam(spawn.getPosition(), false)) - .forEach(spawn -> spawnMask.fillCircle(spawn.getPosition(), 48, false)); + .forEach(spawn -> spawnMask.fillCircle(spawn.getPosition(), remainingMexRadius, false)); placeIndividualMexes(spawnMask, numMexesLeft, mexSpacing); spacePlacedMexes(spawnMask, mexSpacing, previousMexCount); From 91ed33084b952cf5845378793b9c5203e4815983 Mon Sep 17 00:00:00 2001 From: clive Date: Mon, 10 Nov 2025 21:41:35 +0800 Subject: [PATCH 07/12] Mr rabbit's suggestions --- .../FractalUpsideDownLastTerrainGenerator.java | 2 +- .../faforever/neroxis/mask/MapMaskMethods.java | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java index 78983303..c2432788 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java @@ -14,7 +14,7 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame fractalParams = new FractalParams(2, false, 2, 1.2f, 3, 3, new FractalFlattenParams[]{ new FractalFlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), new FractalFlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), - new FractalFlattenParams(15f, 50f, 13, 12.5f, 0.5f, 1, false, false, 4), + new FractalFlattenParams(15f, 50f, 12.5f, 12.5f, 0.5f, 1, false, false, 4), }); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); diff --git a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java index 49cde8f7..492b090f 100644 --- a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java +++ b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java @@ -135,12 +135,21 @@ public static BooleanMask pathAroundLocations(List locations, long seed } /** + * Flattens a height band in the terrain by remapping values within the specified height range + * to a destination height range using a slope-based curve. * + * @param exec the FloatMask to modify + * @param noiseMap the noise map used to determine which areas to flatten + * @param minHeight the minimum height of the band to flatten + * @param maxHeight the maximum height of the band to flatten + * @param destinationMinHeight the minimum height in the destination range + * @param destinationMaxHeight the maximum height in the destination range * @param slope = 1 → linear interpolation. * > 1 → slower start, faster rise. * < 1 → faster start, slower rise. - * @return - */ + * ≤ 0 → uses destinationMaxHeight for entire band. + * @param blurAmount the amount of blur to apply at the band edges (0 = no blur) + * @return the modified FloatMask */ public static FloatMask flattenHeightBand(FloatMask exec, FloatMask noiseMap, float minHeight, float maxHeight, float destinationMinHeight, float destinationMaxHeight, float slope, int blurAmount) { @@ -168,6 +177,10 @@ public static FloatMask flattenHeightBand(FloatMask exec, FloatMask noiseMap, fl private static float remapWithSlope(float value, float minHeight, float maxHeight, float destinationMinHeight, float destinationMaxHeight, float slope) { + // Handle edge case where height range is zero + if (maxHeight == minHeight) { + return destinationMaxHeight; + } // Normalize value to 0–1 range float normalized = (value - minHeight) / (maxHeight - minHeight); From def78fbc46b70ec6602ce96c0445f446df66a282 Mon Sep 17 00:00:00 2001 From: clive Date: Mon, 10 Nov 2025 23:24:26 +0800 Subject: [PATCH 08/12] Handle the minHeight > maxHeight condition --- .../main/java/com/faforever/neroxis/mask/MapMaskMethods.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java index 492b090f..e548f19e 100644 --- a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java +++ b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java @@ -159,7 +159,7 @@ public static FloatMask flattenHeightBand(FloatMask exec, FloatMask noiseMap, fl exec.setPrimitiveWithSymmetry(SymmetryType.SPAWN, (x, y) -> { float value = noise.getPrimitive(x, y); if (flattenMask.getPrimitive(x, y)) { - if (slope <= 0) { + if (slope <= 0 || minHeight >= maxHeight) { return destinationMaxHeight; } else { return remapWithSlope(value, minHeight, maxHeight, destinationMinHeight, destinationMaxHeight, slope); @@ -178,7 +178,7 @@ private static float remapWithSlope(float value, float minHeight, float maxHeigh float destinationMinHeight, float destinationMaxHeight, float slope) { // Handle edge case where height range is zero - if (maxHeight == minHeight) { + if (maxHeight >= minHeight) { return destinationMaxHeight; } From dcc60ed9bc946538a71cdbc08ee2bb41bf20b4f4 Mon Sep 17 00:00:00 2001 From: clive Date: Mon, 10 Nov 2025 23:51:48 +0800 Subject: [PATCH 09/12] oh man --- .../main/java/com/faforever/neroxis/mask/MapMaskMethods.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java index e548f19e..14cab73e 100644 --- a/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java +++ b/shared/src/main/java/com/faforever/neroxis/mask/MapMaskMethods.java @@ -159,7 +159,7 @@ public static FloatMask flattenHeightBand(FloatMask exec, FloatMask noiseMap, fl exec.setPrimitiveWithSymmetry(SymmetryType.SPAWN, (x, y) -> { float value = noise.getPrimitive(x, y); if (flattenMask.getPrimitive(x, y)) { - if (slope <= 0 || minHeight >= maxHeight) { + if (slope <= 0 || maxHeight <= minHeight) { return destinationMaxHeight; } else { return remapWithSlope(value, minHeight, maxHeight, destinationMinHeight, destinationMaxHeight, slope); @@ -178,7 +178,7 @@ private static float remapWithSlope(float value, float minHeight, float maxHeigh float destinationMinHeight, float destinationMaxHeight, float slope) { // Handle edge case where height range is zero - if (maxHeight >= minHeight) { + if (maxHeight <= minHeight) { return destinationMaxHeight; } From 200934bf438294b50f3ba57e414ceb362388cc19 Mon Sep 17 00:00:00 2001 From: clive Date: Wed, 12 Nov 2025 22:31:02 +0800 Subject: [PATCH 10/12] small tweak to spawnable area, and small formatting --- .../FractalLandLastTerrainGenerator.java | 16 ++++++----- .../FractalNavyLastTerrainGenerator.java | 28 +++++++++++-------- .../FractalNoiseLastTerrainGenerator.java | 1 + .../FractalPlateauLastTerrainGenerator.java | 14 ++++++---- ...FractalUpsideDownLastTerrainGenerator.java | 12 ++++---- 5 files changed, 41 insertions(+), 30 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java index ea5879d1..7c730871 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java @@ -11,13 +11,15 @@ public class FractalLandLastTerrainGenerator extends FractalNoiseLastTerrainGene @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { - fractalParams = new FractalParams(0f, false, 1, 1.5f, 8, 2, new FractalFlattenParams[]{ - new FractalFlattenParams(0, 1, 0, 1, 0.5f, 0, true, true, 4), - new FractalFlattenParams(1, 4, 1, 1, 0, 0, false, false, 4), - new FractalFlattenParams(4, 6, 13, 13, 0, 2, false, false, 4), - new FractalFlattenParams(6, 15, 11, 11, 0, 0, false, false, 4), - new FractalFlattenParams(15, 22, 16, 16, 0, 1, false, false, 4), - }); + fractalParams = new FractalParams( + 0f, false, 1, 1.5f, 8, 2, + new FractalFlattenParams[]{ + new FractalFlattenParams(0, 1, 0, 1, 0.5f, 0, true, true, 4), + new FractalFlattenParams(1, 4, 1, 1, 0, 0, false, false, 4), + new FractalFlattenParams(4, 6, 13, 13, 0, 2, false, false, 4), + new FractalFlattenParams(6, 15, 11, 11, 0, 0, false, false, 4), + new FractalFlattenParams(15, 22, 16, 16, 0, 1, false, false, 4), + }); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java index 28fbe06d..5f7b1ef7 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java @@ -14,20 +14,24 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame if (map.getSize() < 512) { // Small maps are very problematic, because of a lack of spawnable land area, and low mex count // This increases the area of the map dedicated to spawnable land and mexes - fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ - new FractalFlattenParams(0f, 0.5f, 0, 8, 0.25f, 0, false, false, 4), - new FractalFlattenParams(0.5f, 1f, 8, 16, 1f, 0, true, false, 4), - new FractalFlattenParams(1f, 27, 18, 18, 0, 1, false, true, 8), - new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), - }); + fractalParams = new FractalParams( + 16, true, 2, 1.5f, 6, 3, + new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 0.5f, 0, 8, 0.25f, 0, false, false, 4), + new FractalFlattenParams(0.5f, 1f, 8, 16, 1f, 0, true, false, 4), + new FractalFlattenParams(1f, 27, 18, 18, 0, 1, false, true, 8), + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), + }); } else { // This is a fractal navy map, works well for 10K - 20K maps, with a good amount of the map being ocean. - fractalParams = new FractalParams(16, true, 2, 1.5f, 6, 3, new FractalFlattenParams[]{ - new FractalFlattenParams(0f, 1.0f, 0, 8, 1f, 0, false, false, 4), - new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), - new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), - new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), - }); + fractalParams = new FractalParams( + 16, true, 2, 1.5f, 6, 3, + new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 1.0f, 0, 8, 1f, 0, false, false, 4), + new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), + new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), + }); } super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index 1dfd5b4d..c70f2380 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -186,6 +186,7 @@ protected void setupSpawnMaskPipeline() { } spawnMask.subtract(unbuildable) + .fillCenter(map.getSize() / 3, false) .deflate(4); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java index 73893458..b255c172 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java @@ -11,12 +11,14 @@ public class FractalPlateauLastTerrainGenerator extends FractalNoiseLastTerrainG @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { - fractalParams = new FractalParams(3f, false, 4, 1.2f, 4, 2, new FractalFlattenParams[]{ - new FractalFlattenParams(0f, 0.1f, 0, 4, 0.5f, 0, false, false, 4), - new FractalFlattenParams(0.1f, 1.0f, 4, 14, 2, 0, true, false, 4), - new FractalFlattenParams(1.0f, 27, 14, 15, 1f, 0, false, true, 4), - new FractalFlattenParams(27, 50, 24, 24, 0, 2, false, false, 4), - }); + fractalParams = new FractalParams( + 3f, false, 4, 1.2f, 4, 2, + new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 0.1f, 0, 4, 0.5f, 0, false, false, 4), + new FractalFlattenParams(0.1f, 1.0f, 4, 14, 2, 0, true, false, 4), + new FractalFlattenParams(1.0f, 27, 14, 15, 1f, 0, false, true, 4), + new FractalFlattenParams(27, 50, 24, 24, 0, 2, false, false, 4), + }); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java index c2432788..951a301f 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java @@ -11,11 +11,13 @@ public class FractalUpsideDownLastTerrainGenerator extends FractalNoiseLastTerra @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { - fractalParams = new FractalParams(2, false, 2, 1.2f, 3, 3, new FractalFlattenParams[]{ - new FractalFlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), - new FractalFlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), - new FractalFlattenParams(15f, 50f, 12.5f, 12.5f, 0.5f, 1, false, false, 4), - }); + fractalParams = new FractalParams( + 2, false, 2, 1.2f, 3, 3, + new FractalFlattenParams[]{ + new FractalFlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), + new FractalFlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), + new FractalFlattenParams(15f, 50f, 12.5f, 12.5f, 0.5f, 1, false, false, 4), + }); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } From 30f46bc2cb6dc5e1803a2a2727634d89299c92cf Mon Sep 17 00:00:00 2001 From: clive Date: Wed, 12 Nov 2025 23:33:19 +0800 Subject: [PATCH 11/12] rabbit was correct --- .../terrain/FractalNoiseLastTerrainGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index c70f2380..af64feb1 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -32,10 +32,10 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame rampNoise = new FloatMask(1, random.nextLong(), symmetrySettings, "rampNoise", pipeline); if (fractalParams.useRandomWaterMask()) { - switch (random.nextInt(1,3)) { - case 1: waterMask = WaterMasks.SYMMETRY_LINE; break; - case 2: waterMask = WaterMasks.HOUR_GLASS; break; - case 3: waterMask = WaterMasks.CENTER_LAKE; break; + switch (random.nextInt(3)) { + case 0: waterMask = WaterMasks.SYMMETRY_LINE; break; + case 1: waterMask = WaterMasks.HOUR_GLASS; break; + case 2: waterMask = WaterMasks.CENTER_LAKE; break; } } From 1ae770fe19731060412a0c9524850b1a2712f09d Mon Sep 17 00:00:00 2001 From: clive Date: Tue, 18 Nov 2025 21:16:21 +0800 Subject: [PATCH 12/12] Code review updates, and minor adjustments to Fractal Navy --- .../neroxis/generator/FractalParams.java | 4 +- ...ghMexLandLowMexWaterResourceGenerator.java | 11 +++- .../FractalLandLastTerrainGenerator.java | 9 ++- .../FractalNavyLastTerrainGenerator.java | 22 ++++--- .../FractalNoiseLastTerrainGenerator.java | 13 +--- .../FractalPlateauLastTerrainGenerator.java | 9 ++- ...FractalUpsideDownLastTerrainGenerator.java | 9 ++- .../MultiLevelLastTerrainGenerator.java | 63 +++++++++++-------- 8 files changed, 80 insertions(+), 60 deletions(-) diff --git a/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java b/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java index 85364044..e05c5ff4 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/FractalParams.java @@ -1,5 +1,7 @@ package com.faforever.neroxis.generator; +import java.util.List; + public record FractalParams( float waterHeight, boolean useRandomWaterMask, @@ -7,5 +9,5 @@ public record FractalParams( float noiseOctaveMultiplier, float noiseExpMultiplier, int teamSeparation, - FractalFlattenParams[] fractalFlattenParams + List fractalFlattenParams ) {} diff --git a/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java index 7daab31f..9a517f33 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/resource/HighMexLandLowMexWaterResourceGenerator.java @@ -23,7 +23,7 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame @Override public void placeResources() { DebugUtil.timedRun("com.faforever.neroxis.map.generator", "generateResources", () -> { - mexPlacer.placeMexes(getMexCount(), resourceMask.getFinalMask(), waterResourceMask.getFinalMask(), 12, 12, 12); + mexPlacer.placeMexes(getMexCount(), resourceMask.getFinalMask(), waterResourceMask.getFinalMask(), 16, 16, 12); hydroPlacer.placeHydros(generatorParameters.spawnCount(), resourceMask.getFinalMask().deflate(8)); }); } @@ -33,8 +33,13 @@ protected int getMexCount() { int mapSize = generatorParameters.mapSize(); int spawnCount = generatorParameters.spawnCount(); - // 4 mexes per player, and about 24 mexes per 256 chunk of the map multiplied by resource density - return (spawnCount * 4) + StrictMath.round( (mapSize / 256f) * 24f * resourceDensity); + // Add about 24 mexes per 256 chunk of the map multiplied by resource density + int mexCount = StrictMath.round( (mapSize / 256f) * 24f * resourceDensity); + + // Add an additional 4 mexes per player + mexCount += spawnCount * 4; + + return mexCount; } @Override diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java index 7c730871..79dc2485 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalLandLastTerrainGenerator.java @@ -7,19 +7,22 @@ import com.faforever.neroxis.map.SymmetrySettings; import com.faforever.neroxis.util.Pipeline; +import java.util.List; + public class FractalLandLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { fractalParams = new FractalParams( 0f, false, 1, 1.5f, 8, 2, - new FractalFlattenParams[]{ + List.of( new FractalFlattenParams(0, 1, 0, 1, 0.5f, 0, true, true, 4), new FractalFlattenParams(1, 4, 1, 1, 0, 0, false, false, 4), new FractalFlattenParams(4, 6, 13, 13, 0, 2, false, false, 4), new FractalFlattenParams(6, 15, 11, 11, 0, 0, false, false, 4), - new FractalFlattenParams(15, 22, 16, 16, 0, 1, false, false, 4), - }); + new FractalFlattenParams(15, 22, 16, 16, 0, 1, false, false, 4) + ) + ); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java index 5f7b1ef7..0255ad83 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNavyLastTerrainGenerator.java @@ -7,6 +7,8 @@ import com.faforever.neroxis.map.SymmetrySettings; import com.faforever.neroxis.util.Pipeline; +import java.util.List; + public class FractalNavyLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, @@ -15,23 +17,25 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame // Small maps are very problematic, because of a lack of spawnable land area, and low mex count // This increases the area of the map dedicated to spawnable land and mexes fractalParams = new FractalParams( - 16, true, 2, 1.5f, 6, 3, - new FractalFlattenParams[]{ + 16, true, 2, 1.5f, 5, 2, + List.of( new FractalFlattenParams(0f, 0.5f, 0, 8, 0.25f, 0, false, false, 4), new FractalFlattenParams(0.5f, 1f, 8, 16, 1f, 0, true, false, 4), new FractalFlattenParams(1f, 27, 18, 18, 0, 1, false, true, 8), - new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), - }); + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4) + ) + ); } else { // This is a fractal navy map, works well for 10K - 20K maps, with a good amount of the map being ocean. fractalParams = new FractalParams( - 16, true, 2, 1.5f, 6, 3, - new FractalFlattenParams[]{ + 16, true, 2, 1.5f, 5, 2, + List.of( new FractalFlattenParams(0f, 1.0f, 0, 8, 1f, 0, false, false, 4), new FractalFlattenParams(1.0f, 3f, 8, 16, 1f, 0, true, false, 4), - new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 8), - new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4), - }); + new FractalFlattenParams(3f, 27, 18, 18, 0, 1, false, true, 4), + new FractalFlattenParams(27, 50, 18, 35, 1, 1, false, false, 4) + ) + ); } super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java index af64feb1..93c859ff 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java @@ -153,18 +153,7 @@ protected void setupHeightmapPipeline() { } heightmap.add(waterHeight); - if (heightMapNoise.getSymmetrySettings().spawnSymmetry().isPerfectSymmetry()) { - heightMapNoise.addWhiteNoise(plateauHeight / 3).resample(mapSize / 64); - heightMapNoise.addWhiteNoise(plateauHeight / 3).resample(mapSize + 1); - heightMapNoise.addWhiteNoise(1) - .subtractAvg() - .clampMin(0f) - .setToValue(land.copy().invert().inflate(16), 0f) - .blur(mapSize / 16); - heightmap.add(heightMapNoise); - } - - if (symmetrySettings.spawnSymmetry().getNumSymPoints() == 3 || symmetrySettings.spawnSymmetry().getNumSymPoints() >= 5) { + if (!symmetrySettings.spawnSymmetry().isPerfectSymmetry()) { // For the odd symmetry, pie shaped maps, we need to limit the terrain to a circle with the full diameter of the map BooleanMask outerCircle = new BooleanMask(mapSize + 1, random.nextLong(), symmetrySettings, "outerCircle", pipeline); outerCircle.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 2f, true); diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java index b255c172..94230324 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalPlateauLastTerrainGenerator.java @@ -7,18 +7,21 @@ import com.faforever.neroxis.map.SymmetrySettings; import com.faforever.neroxis.util.Pipeline; +import java.util.List; + public class FractalPlateauLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { fractalParams = new FractalParams( 3f, false, 4, 1.2f, 4, 2, - new FractalFlattenParams[]{ + List.of( new FractalFlattenParams(0f, 0.1f, 0, 4, 0.5f, 0, false, false, 4), new FractalFlattenParams(0.1f, 1.0f, 4, 14, 2, 0, true, false, 4), new FractalFlattenParams(1.0f, 27, 14, 15, 1f, 0, false, true, 4), - new FractalFlattenParams(27, 50, 24, 24, 0, 2, false, false, 4), - }); + new FractalFlattenParams(27, 50, 24, 24, 0, 2, false, false, 4) + ) + ); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java index 951a301f..db4aa351 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalUpsideDownLastTerrainGenerator.java @@ -7,17 +7,20 @@ import com.faforever.neroxis.map.SymmetrySettings; import com.faforever.neroxis.util.Pipeline; +import java.util.List; + public class FractalUpsideDownLastTerrainGenerator extends FractalNoiseLastTerrainGenerator { @Override public void initialize(SCMap map, long seed, GeneratorParameters generatorParameters, SymmetrySettings symmetrySettings, Pipeline pipeline) { fractalParams = new FractalParams( 2, false, 2, 1.2f, 3, 3, - new FractalFlattenParams[]{ + List.of( new FractalFlattenParams(0f, 0.8f, 0, 10, 0.5f, 0, false, false, 4), new FractalFlattenParams(0.8f, 15f, 16, 16, 0, 1, true, true, 4), - new FractalFlattenParams(15f, 50f, 12.5f, 12.5f, 0.5f, 1, false, false, 4), - }); + new FractalFlattenParams(15f, 50f, 12.5f, 12.5f, 0.5f, 1, false, false, 4) + ) + ); super.initialize(map, seed, generatorParameters, symmetrySettings, pipeline); } diff --git a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java index 61fa7a27..c40acfe1 100644 --- a/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java +++ b/generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java @@ -50,9 +50,9 @@ public void initialize(SCMap map, long seed, GeneratorParameters generatorParame landNoiseMap = new FloatMask(1, getRandom().nextLong(), land.getSymmetrySettings(), "landNoiseMap", pipeline); secondLevelLand = new BooleanMask(1, random.nextLong(), symmetrySettings, "secondLevelLand", pipeline); thirdLevelLand = new BooleanMask(1, random.nextLong(), symmetrySettings, "thirdLevelLand", pipeline); - rampExclusion = new FloatMask(1, random.nextLong(), symmetrySettings,"rampExclusion", pipeline); - waterAreaBlur = new FloatMask(1, random.nextLong(), symmetrySettings,"waterAreaBlur", pipeline); - waterArea = new BooleanMask(1, random.nextLong(), symmetrySettings,"waterArea", pipeline); + rampExclusion = new FloatMask(1, random.nextLong(), symmetrySettings, "rampExclusion", pipeline); + waterAreaBlur = new FloatMask(1, random.nextLong(), symmetrySettings, "waterAreaBlur", pipeline); + waterArea = new BooleanMask(1, random.nextLong(), symmetrySettings, "waterArea", pipeline); noiseSmallestDetail = 5; noiseOctaveMultiplier = 1.0f; @@ -117,30 +117,41 @@ protected void landSetup() { private void addWaterAreasToNoiseMap(int mapSize) { // For water only, we can influence the likelihood of water to occur for different areas of the map waterArea.setSize(mapSize + 1); - if (waterMask == WaterMasks.SYMMETRY_LINE) { - // Water will be more likely along the symmetry line(s), kinda splitting the map in half, or pie slices for odd symmetries - waterArea.drawSymmetryLines(); - waterArea.inflate(StrictMath.min(256,mapSize / 4f / symmetrySettings.teamSymmetry().getNumSymPoints())); - waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); - waterAreaBlur.blur(mapSize / 4); - } else if (waterMask == WaterMasks.HOUR_GLASS) { - // An unusual shape, which increase the likelihood of water along the symmetry lines and the corners of the map - waterArea.drawSymmetryLines(); - waterArea.inflate(mapSize / 4f / symmetrySettings.teamSymmetry().getNumSymPoints()); - List symmetryPoints = waterArea.getSymmetryPointsWithOutOfBounds(new Vector2(0, 0), SymmetryType.SPAWN) - .stream() - .map(Vector2::roundToNearestHalfPoint) - .toList(); - waterArea.fillCircle(new Vector2(0, 0), mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true); - symmetryPoints.forEach(s -> waterArea.fillCircle(s, mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true)); - waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); - waterAreaBlur.blur(mapSize / 3 / symmetrySettings.teamSymmetry().getNumSymPoints()); - } else if (waterMask == WaterMasks.CENTER_LAKE) { - // big ocean in the centre of the map - waterArea.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 3f, true); - waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); - waterAreaBlur.blur(mapSize / 4); + + switch (waterMask) { + case WaterMasks.SYMMETRY_LINE: + // Water will be more likely along the symmetry line(s), kinda splitting the map in half, or pie slices for odd symmetries + waterArea.drawSymmetryLines(); + waterArea.inflate( + StrictMath.min(256, mapSize / 4f / symmetrySettings.teamSymmetry().getNumSymPoints())); + waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); + waterAreaBlur.blur(mapSize / 4); + break; + case WaterMasks.HOUR_GLASS: + // An unusual shape, which increase the likelihood of water along the symmetry lines and the corners of the map + waterArea.drawSymmetryLines(); + waterArea.inflate(mapSize / 4f / symmetrySettings.teamSymmetry().getNumSymPoints()); + List symmetryPoints = waterArea.getSymmetryPointsWithOutOfBounds(new Vector2(0, 0), + SymmetryType.SPAWN) + .stream() + .map(Vector2::roundToNearestHalfPoint) + .toList(); + waterArea.fillCircle(new Vector2(0, 0), + mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), true); + symmetryPoints.forEach( + s -> waterArea.fillCircle(s, mapSize / 2f / symmetrySettings.teamSymmetry().getNumSymPoints(), + true)); + waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); + waterAreaBlur.blur(mapSize / 3 / symmetrySettings.teamSymmetry().getNumSymPoints()); + break; + case WaterMasks.CENTER_LAKE: + // big ocean in the centre of the map + waterArea.fillCircle(new Vector2(mapSize / 2f, mapSize / 2f), mapSize / 3f, true); + waterAreaBlur = waterArea.copyAsFloatMask(0f, 1f); + waterAreaBlur.blur(mapSize / 8); + break; } + landNoiseMap.add(1f); landNoiseMap.subtract(waterAreaBlur); }