Skip to content

Conversation

@clivepaterson
Copy link
Contributor

@clivepaterson clivepaterson commented Nov 23, 2025

As reported by Ravandel:
mapName = "neroxis_map_generator_snapshot_htauvztrkz3kc_bifq";
image
The fillCircle()call in SpawnPlacer.java:tryPlaceSpawns() will either draw a symmetry line or a circle.
So the above mapgen is doing this:
Current_After_fillCircle
Current_After_limitToSymmetryRegion

Summary by CodeRabbit

  • Improvements

    • Spawn placement now respects symmetry-driven exclusion zones when shaping spawn regions, improving team separation and consistency.
    • Terrain generation uses the selected symmetry to determine mountain/heightmap processing for a narrower set of symmetry types, producing more predictable terrain.
    • Symmetry line drawing expanded and parameterized to include additional symmetry patterns for better visual consistency.
  • Tests

    • Map-generator tests updated to use larger map size (512).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 23, 2025

Walkthrough

Replaces parameterless symmetry-line drawing with a symmetry-parameterized API, updates generators and spawn placement to use it, subtracts a symmetry-inflated region from spawn masks before further constraints, and narrows which symmetry types trigger the mountain-heightmap pipeline.

Changes

Cohort / File(s) Summary
Spawn placement
shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java
In tryPlaceSpawns, construct a symmetry-derived BooleanMask (draw symmetry lines with a random seed, inflate by a factor from teamSeparation/spawn symmetry) and subtract it from the spawn mask before edge fill and symmetry-region limiting.
BooleanMask API
shared/src/main/java/com/faforever/neroxis/mask/BooleanMask.java
Replaced public BooleanMask drawSymmetryLines() with public BooleanMask drawSymmetryLines(Symmetry symmetry); switched internal logic to the supplied symmetry; added explicit handling for QUAD (horizontal + vertical center lines) and DIAG (diagonals); retained multi-point and other symmetry behaviors.
Terrain generators
generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java, generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java
Updated calls to the new drawSymmetryLines signature (pass symmetrySettings.terrainSymmetry() or appropriate symmetry). In FractalNoiseLastTerrainGenerator.setupHeightmapPipeline(), restricted the mountain-heightmap branch to trigger only for POINT2 through POINT16 (excluding QUAD/DIAG).
Tests
generator/src/test/java/com/faforever/neroxis/generator/MapGeneratorTest.java
Increased map-size parameters from 256 to 512 in inequality-related tests and adjusted corresponding test invocations; no API signature changes in tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect SpawnPlacer subtraction to ensure it doesn't over-remove spawnable area and interacts correctly with subsequent edge/symmetry constraints.
  • Verify drawSymmetryLines(Symmetry) handling for QUAD and DIAG produce correct line geometry and expected inflation.
  • Confirm FractalNoiseLastTerrainGenerator's conditional correctly includes/excludes symmetry types for the mountain-heightmap pipeline.
  • Run the adjusted tests (map-size changes) to validate performance and correctness.

Poem

🐰 I traced the lines where mirrors meet,
I nibbled masks until the spawns found seat,
I drew the quad and diagonal with care,
Subtracted shadows, left clear plots to pair,
A hop, a tweak — the map now breathes and greets!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions 'spawnPlacer' and 'symmetry lines', but contains a typo ('symmtry') and doesn't clearly reflect the main objective of changing team separation for spawn placement in LastTerrain generators. Consider revising the title to be more specific and accurate, such as 'Update team separation method for spawn placement in LastTerrain' or 'Fix spawn separation using symmetry lines instead of circles'.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7756066 and 75d075b.

📒 Files selected for processing (5)
  • generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java (2 hunks)
  • generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java (1 hunks)
  • generator/src/test/java/com/faforever/neroxis/generator/MapGeneratorTest.java (3 hunks)
  • shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java (1 hunks)
  • shared/src/main/java/com/faforever/neroxis/mask/BooleanMask.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java
  • generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java
  • generator/src/test/java/com/faforever/neroxis/generator/MapGeneratorTest.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java (1)

87-92: LGTM - Team separation improved via symmetry line subtraction.

The approach correctly addresses the spawn separation issue described in the PR by:

  1. Drawing symmetry lines based on teamSymmetry
  2. Inflating by a factor scaled to the spawn symmetry count
  3. Subtracting from the spawn mask before applying other constraints

This aligns with the refined approach discussed in previous review iterations (keeping fillCenter() and adding symmetry line subtraction).

shared/src/main/java/com/faforever/neroxis/mask/BooleanMask.java (1)

803-841: LGTM - QUAD and DIAG symmetry handling correctly added.

The new cases for QUAD (drawing both horizontal and vertical center lines) and DIAG (drawing both diagonals) are implemented correctly and handle their respective symmetries as expected.

Note: numSymPoints is computed from symmetrySettings.teamSymmetry() regardless of the passed symmetry parameter. This means the POINTn cases use the team symmetry's point count. This works safely because callers consistently pass the appropriate symmetry value that aligns with this sourcing.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java (2)

84-96: Check teamSeparationMask inflation math and symmetry-count edge cases

The new mask logic looks coherent, but a couple of edge cases are worth double‑checking:

  • teamSeparationMask uses map.getSize() + 1 while you already have mapSize; consider using mapSize + 1 for consistency and to avoid accidental divergence if mapSize ever changes.
  • For non‑perfect symmetry, inflate((float) teamSeparation / spawnSymmetry.getNumSymPoints()) can become very small for large numSymPoints (e.g. 7/9‑way). That may effectively remove most of the intended team separation from the lines, leaving only the central fillCircle to do the work. A small max(…, minRadius) clamp or at least an assertion that getNumSymPoints() > 0 might make this more robust.
  • It might also be worth confirming via tests that the odd‑symmetry cases you care about (3, 5, 7, 9) still produce the expected visual separation at both small and large teamSeparation values.

98-101: Spawn area restriction order and POINT2 double fill

Two related points here:

  1. The new chain
    fillSides(...).subtract(teamSeparationMask).fillEdge(mapSize / 32, false).limitToSymmetryRegion()
    changes the effective playable area compared to the previous center‑fill approach. This looks intentional, but because fillEdge here uses /32 while the other placeSpawns overload still uses /16, it’s worth confirming that the extra near‑edge freedom for this path is desired and tested for small maps and high spawnCount.

  2. In the loop below, for Symmetry.POINT2 you call fillCircle(symmetryPoint, teammateSeparation, false) twice (once unconditionally, once inside the if block). That second pass is effectively a no‑op and appears to be leftover from an earlier version where radii differed. You can safely drop the if (spawnSymmetry == Symmetry.POINT2) block, or repurpose it if you actually intended a different radius there (e.g. teamSeparation).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c2e3471 and 5cc12e8.

📒 Files selected for processing (1)
  • shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Comment on lines 87 to 100
BooleanMask teamSeparationMask = new BooleanMask(map.getSize() + 1, random.nextLong(),
spawnMask.getSymmetrySettings());
teamSeparationMask.drawSymmetryLines();
if (spawnSymmetry.isPerfectSymmetry()) {
teamSeparationMask.inflate(teamSeparation / 2f);
} else {
teamSeparationMask.inflate((float) teamSeparation / spawnSymmetry.getNumSymPoints())
.fillCircle(mapSize / 2f, mapSize / 2f, mapSize / 4f, true);
}

BooleanMask spawnMaskCopy = spawnMask.copy();
spawnMaskCopy.fillSides(map.getSize() / spawnCount * 3 / 2, false)
.fillCenter(teamSeparation, false)
.fillEdge(map.getSize() / 32, false)
spawnMaskCopy.fillSides(mapSize / spawnCount * 3 / 2, false)
.subtract(teamSeparationMask)
.fillEdge(mapSize / 32, false)
Copy link
Member

@Sheikah45 Sheikah45 Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a rather big difference to change it from fillCenter to fillCircle. Fill center was filling along the symmetry center. So this would have a big impact on non point symmetry separation. I think just the symmetry lines is enough without changing from fill center to fill circle

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cause could also be an impropely chosen team symmetry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yep, so take2 attempt.
Keeping the fillCenter(), which yep, makes more sense to keep it.
And just subtract the symmerty lines.

Which has highlighted some bugs in the drawSymmetryLines() function actually...
Seems line the QUAD and DIAG symmetries weren't implemented proplerly in drawSymmetryLines(), which I have fixed now, noice....
And yeah, now I see why we need to pass the SymmetryType as a parameter to the drawSymmetryLines(), so I've updated that aswell, noice...

But yep anyway, this seems to fix these egde cases now where the fillCenter() isn't pushing the teams apart enough.
So the above neroxis_map_generator_snapshot_htauvztrkz3kc_bifq now does this:
image
image
image
image

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
shared/src/main/java/com/faforever/neroxis/mask/BooleanMask.java (1)

803-841: Clarify coupling between symmetry parameter and teamSymmetry().getNumSymPoints()

The new drawSymmetryLines(Symmetry symmetry) nicely adds QUAD and DIAG support, but it still drives the “slice” logic off symmetrySettings.teamSymmetry().getNumSymPoints() rather than the passed-in symmetry. That means:

  • For numSymPoints == 3 or >= 5, the method ignores the symmetry value entirely and always draws radial slices.
  • In the POINT3/5/7/9/11/13/15 case, the number of slices still comes from team symmetry, not from the symmetry argument.

If all callers always pass a symmetry consistent with teamSymmetry(), this preserves old behavior; otherwise this can be surprising and hard to reason about. Consider either:

  • Deriving numSymPoints from the symmetry parameter (or a helper on Symmetry), or
  • Documenting in Javadoc that this API is intentionally tied to teamSymmetry and that the symmetry argument only selects orientation/axes.

This is mostly about API clarity and future maintainability rather than an immediate bug.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc12e8 and a54b3e9.

📒 Files selected for processing (4)
  • generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java (2 hunks)
  • generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java (1 hunks)
  • shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java (1 hunks)
  • shared/src/main/java/com/faforever/neroxis/mask/BooleanMask.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • shared/src/main/java/com/faforever/neroxis/map/placement/SpawnPlacer.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (3)
generator/src/main/java/com/faforever/neroxis/generator/terrain/MultiLevelLastTerrainGenerator.java (1)

121-129: Explicit terrain symmetry for water masks looks correct

Passing symmetrySettings.terrainSymmetry() into waterArea.drawSymmetryLines(...) for both SYMMETRY_LINE and HOUR_GLASS keeps behavior aligned with terrain symmetry and matches the new API without changing the surrounding logic.

Also applies to: 130-146

generator/src/main/java/com/faforever/neroxis/generator/terrain/FractalNoiseLastTerrainGenerator.java (2)

54-56: Symmetry lines initialization matches new BooleanMask API

Using symmetryLines.drawSymmetryLines(symmetrySettings.terrainSymmetry()) is consistent with the new signature and with how symmetry lines are later used for mountains and blurring.


140-153: Confirm intended restriction of mountain ridge pipeline to POINT symmetries

The mountain-heightmap pipeline now only runs when terrainSymmetry is one of POINT2POINT16, and falls back to “just add heightmapLand” for other symmetries (e.g., QUAD/DIAG). That’s a non-trivial behavioral change; please confirm this is intentional for spawn-last generators and that you’re happy to lose symmetry-line mountain ridges for non-POINT terrain symmetries.

@clivepaterson clivepaterson changed the title Change the team separation for spawn last Updates to spawnPlacer for LastTerrain's and fixes to symmtry lines. Nov 28, 2025
@Sheikah45 Sheikah45 force-pushed the team-separation-for-spawn-last branch from 7756066 to 75d075b Compare December 7, 2025 16:14
@Sheikah45 Sheikah45 enabled auto-merge (squash) December 7, 2025 16:15
@Sheikah45 Sheikah45 merged commit 61aca49 into FAForever:develop Dec 7, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants