Skip to content

[1.18.2] GeologySampler disagrees with generated geology at 3D biome seams #266

Closed

Description

@SkyBlade1978

Summary

On the local OreSpawn 4.0.11.118021 candidate, the public GeologySampler can disagree with the geology actually generated for the same (x, z) column and WORLD_SURFACE_WG height at a 3D biome seam.

CakeWorld found a cakeworld:mint_crystal that OreSpawn could only have placed into its exact cakeworld:peppermint_rock host. The surrounding generated rock confirms Peppermint Rock, but GeologySampler.sampleColumn(x, z, surfaceY) predicts cakeworld:biscuit_stone for that position. Sampling the runtime biome at ore Y instead resolves the Peppermint geome/rock, showing a vertical biome seam, but the public API and OreSpawn's column-generation contract both classify one column from the surface biome.

This is the only remaining failure in CakeWorld's 274-test fixed-seed suite. The earlier dynamic-biome issues #262 and #263 pass on this candidate.

Environment

  • Minecraft 1.18.2
  • Forge 40.3.0
  • OreSpawn version: 4.0.11.118021 (local candidate; not yet published)
  • Local branch: feature/1.18.2-4.0.11-dynamic-biomes
  • Local commit: e478d926dcd764e05fa0f286fe23276ea17b2b18
  • Tested JAR SHA-256: E012F1CDC2DCBE387BD72EE337197803DE0CA30A8205D20CB9ACDF722F9EC5BB
  • Integrated test mod: CakeWorld
  • CakeWorld branch/HEAD: master-1.18.2 / 0a3fb0dd6788d2fcad78f82d20154a772ff93d05
  • Fixed world seed: 5059928472718672684
  • Template: cakeworld:edible_world

Provider rule that exposes the mismatch

CakeWorld's Mint Crystal uses a strict explicit host and cannot replace Biscuit Stone:

"cakeworld:ore/mint_crystal": {
  "block": "cakeworld:mint_crystal",
  "deep_output": "cakeworld:rock_candy_deposit",
  "deep_output_max_y": -24,
  "enabled": true,
  "dimensions": {
    "minecraft:overworld": {
      "enabled": true,
      "min_y": -56,
      "max_y": 80,
      "frequency": 1.0,
      "quantity": 5,
      "pattern": {
        "type": "orespawn:precision",
        "settings": {
          "spread": 4,
          "vertical_spread": 3,
          "node_size": 2,
          "length": 8
        }
      },
      "height_distribution": "bottom_triangle",
      "discard_chance_on_air_exposure": 0.65,
      "host_blocks": ["cakeworld:peppermint_rock"],
      "geomes": {
        "cakeworld:peppermint_fold": 5.0,
        "cakeworld:rock_candy_uplift": 2.5,
        "cakeworld:cocoa_basin": 0.0
      }
    }
  }
}

Integrated reproduction

Build the local OreSpawn candidate, then from the CakeWorld 1.18.2 checkout run the suite against a new, unused run directory:

$env:JAVA_HOME='C:\Users\johnb\.jdks\temurin-17.0.1+12\jdk-17.0.1+12'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
$env:GRADLE_USER_HOME='D:\CakeWorld\.gradle-verify-cache'

.\gradlew.bat runGameTestServer --no-daemon `
  '-PcakeworldLocalOreSpawnJar=D:\MinecraftMineralogy\OS118\OreSpawn\build\libs\OreSpawn-4.0.11.118021.jar' `
  -PcakeworldFreshWorldgenRuntime=true `
  -PcakeworldFreshWorldgenRunDirectory=run-fresh-worldgen-os411-host-attribution

Run the same command unchanged a second time for saved-world reload proof. The focused failing test is focusedexplicitorehostattributionaudit.

The audit preloads all surveyed chunks before creating the sampler, so this is not a stale dynamic-ID learning problem.

Expected

For a generated column, GeologySampler.sampleColumn(x, z, WORLD_SURFACE_WG).rockAt(y) should reproduce the pre-ore geology that OreSpawn used when generating that same column. A strict-host OreSpawn output should therefore agree with the sampler's predicted host at its Y coordinate, on both fresh generation and reload.

Actual

The fixed-seed audit observes 123 Mint Crystal outputs and two sampler disagreements. The first is:

position:             BlockPos{x=-2536, y=-1, z=-892}
output:               cakeworld:mint_crystal
WORLD_SURFACE_WG:     97
surface biome:        cakeworld:candy_plains
surface geome:        cakeworld:cocoa_basin
surface prediction:   cakeworld:biscuit_stone
ore-Y biome:          cakeworld:marshmallow_peaks
ore-Y geome:          cakeworld:peppermint_fold
ore-Y prediction:     cakeworld:peppermint_rock
neighbors:
  down:  cakeworld:peppermint_rock
  up:    cakeworld:peppermint_rock
  north: cakeworld:biscuit_stone
  south: cakeworld:mint_crystal
  west:  cakeworld:peppermint_rock
  east:  cakeworld:biscuit_stone

The final integrated result is:

274 GAME TESTS COMPLETE
1 required test failed:
- focusedexplicitorehostattributionaudit

The same mismatch was observed in the initial fresh-world pass and repeated saved-world reload passes.

Suspected source seam

The current local candidate has matching-looking entry points that nevertheless produce different results:

  • GeomeGeology.replaceStoneInChunk obtains WORLD_SURFACE_WG, reads the biome at (x, surfaceY, z), then calls classifyColumn once for the generated column (GeomeGeology.java, approximately lines 89-112).
  • OreSpawnGeologySampler.sampleColumn reads the biome at the caller-supplied (x, surfaceY, z) and passes it to GeomeGeology.sampleColumn (OreSpawnGeologySampler.java, approximately lines 58-67).
  • The public API documentation says this samples “exact production geology” and performs one biome/geome classification reused for every Y query (docs/API.md, approximately lines 117-131).

At runtime, the sampler's surface lookup is Candy Plains/Cocoa Basin, while the generated Peppermint Rock and exact-host Mint Crystal show that the effective generation classification was Peppermint Fold. The ore-Y biome is Marshmallow Peaks/Peppermint Fold.

This suggests the surface biome/classification seen during terrain generation is not stable or equivalent to the later public sampler around a vertical biome boundary. Dynamic biome wrapping, lookup timing, or cached classification state may be involved; that is an inference from the integrated evidence, not yet a proven root cause.

Suggested regression coverage

  1. During an integrated fixed-seed generation test, record the biome key, geome and predicted rocks used by replaceStoneInChunk for selected columns.
  2. After chunk completion, call GeologySampler.sampleColumn with the same (x, z, WORLD_SURFACE_WG) and assert identical biome/geome/rock predictions across representative Y values.
  3. Include a column where the biome at ore Y differs from the biome at surface Y.
  4. Repeat after saving and reopening the world.
  5. Run with dynamic-registry custom biomes so the [1.18.2] Geome ID fallback drops biome-dictionary weights for dynamic biomes #262/[1.18.2] Ore biome filters reject dynamic-registry biomes by object identity #263 paths remain covered.

Acceptance criteria

  • Public GeologySampler output agrees with the geology actually generated for the same column and surface Y.
  • Agreement holds at vertical biome seams and for dynamic-registry custom biomes.
  • Fresh generation and saved-world reload produce the same sampler attribution.
  • CakeWorld's focusedexplicitorehostattributionaudit reports 123+ outputs with zero violations.
  • The fix keeps biome/geome classification baked and avoids registry lookup, configuration reads, logging, string construction, or avoidable allocation inside the terrain-generation hot path.

Activity

  1. SkyBlade1978 commented on Aug 29, 2026

    @SkyBlade1978
    ContributorAuthor

    Local CakeWorld verification is now green against the proposed OreSpawn fix.

    Tested OreSpawn candidate:

    • branch: feature/1.18.2-4.0.12-geology-sampler
    • commit: 7c82ecc844ae9d241a108f4417c6c3b5b0bc29a2
    • version/JAR: OreSpawn-4.0.12.118021.jar
    • SHA-256: 0478D611A96020DAAE794B72E64EFD677B49A5B63BCB6179330D63317B16D6A6

    CakeWorld results using that exact JAR:

    • clean CakeWorld build: PASS
    • genuinely fresh fixed-seed world: all 274 required GameTests passed
    • same saved world reloaded: all 274 required GameTests passed
    • formerly failing focused attribution audit: outputs=123, violations=0
    • edible-world integrity scan: no unexpected raw geology in Overworld, Nether, or End (counts={} in all three; bedrock is the explicit exception)
    • Soda Ocean under-fluid evidence remained live: 8 Fizzy Pearls under lemonade outside authored reefs

    This locally verifies the fix for the reported seam/sampler mismatch. I have left the issue open for the OreSpawn maintainer/coding agent to merge and publish the candidate through the normal release process.

  2. SkyBlade1978 commented on Aug 29, 2026

    @SkyBlade1978
    ContributorAuthor

    Correction to my earlier green result: a stricter family-host attribution regression still reproduces a deep sampler mismatch against the same exact 4.0.12 candidate.

    Candidate:

    • branch: feature/1.18.2-4.0.12-geology-sampler
    • commit: 7c82ecc
    • JAR: OreSpawn-4.0.12.118021.jar
    • SHA-256: 0478D611A96020DAAE794B72E64EFD677B49A5B63BCB6179330D63317B16D6A6

    Focused CakeWorld GameTest:

    • namespace: cakeworld_ore_host_attribution
    • fixed-seed 9 x 9 chunk scan, y=-48..32, deliberately excluding the late surface/filler band
    • checks explicit Mint Crystal host attribution plus family-hosted Cocoa Cloud and Liquorice Vein outputs against the public GeologySampler
    • also proves Candy Glass remains a non-replaceable control

    Fresh result:

    • explicit hosts: 139 outputs, 0 violations
    • family hosts: 3,098 outputs, 2 violations
    • non-replaceable controls: 2,264

    Same-save reload reproduced the identical counts and the identical two deep violations.

    Violations:

    1. BlockPos{x=13, y=-17, z=-32}, Cocoa Cloud. Final WORLD_SURFACE_WG/Level first-free Y is 64, and the documented sampler call classifies the column as Peppermint Pinewoods / Peppermint Fold / Peppermint Rock (IGNEOUS_INTRUSIVE). OCEAN_FLOOR_WG first-free Y is 63 and instead classifies it as Candy Plains / Cocoa Basin / Chocolate Sponge (SEDIMENTARY), which agrees with the generated Cocoa Cloud host decision. Final neighbours are mixed Chocolate Sponge and Peppermint Rock.
    2. BlockPos{x=26, y=-9, z=-33}, Cocoa Cloud. WORLD_SURFACE_WG first-free Y 64 gives Peppermint Pinewoods / Peppermint Fold / Peppermint Rock; OCEAN_FLOOR_WG first-free Y 63 gives Candy Plains / Cocoa Basin / Wafer Rock (SEDIMENTARY), again agreeing with the generated Cocoa Cloud. Final neighbours are mixed Wafer Rock and Peppermint Rock.

    The current public contract says sampleColumn should receive the first-free result of Level.getHeight, subtracts one, and exactly matches chunk generation. StoneReplacer chooses its biome using the generation-time WORLD_SURFACE_WG height, but the final WORLD_SURFACE_WG height can be changed by later surface/decoration work. The public caller therefore cannot always reconstruct the generation-time column identity from the final Level height. OCEAN_FLOOR_WG happens to recover the expected identity for these two cells, but that is not the documented contract and should not be assumed generally.

    Acceptance expectation: after world generation and after reload, the documented public sampler path must reproduce the biome/geome/geology classification actually used by StoneReplacer for deep natural cells, with zero family-host attribution mismatches. If a final caller-supplied height cannot guarantee that, the API needs an overload or another stable input/lookup that does. The issue should remain open; the previous 274-test green result did not exercise this stricter family-host invariant.

  3. SkyBlade1978 commented on Sep 9, 2026

    @SkyBlade1978
    ContributorAuthor

    Closing as completed. The remaining family-host attribution seam was resolved by the 4.0.15 portion of 4.0.16.118021 in #270. Chunk geology and the public sampler now share the same direct quart/noise-biome lookup, with explicit stable biome IDs taking precedence over object aliases.

    The corrected fresh/reload regression reports zero generated-geology, sampler and family-host mismatches at 3D biome edges. The fix is merged on every target with three-dimensional biome attribution; older two-dimensional biome systems were explicitly audited as not applicable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions