Summary
Ore biome include/exclude filters are baked as identity-based Set<Biome> values from ForgeRegistries.BIOMES, while chunk generation receives a Holder<Biome> from the server dynamic biome registry and passes only biome.value() to the filter. A runtime biome with the correct resource key but a different object identity is rejected by biome_ids (and will not be recognized by the corresponding dictionary-derived set).
This was observed with a CakeWorld underfluids ore restricted to cakeworld:soda_ocean: the biome, target fluid, valid floor hosts, and expected geome were all present, but the ore filter prevented any attributable OreSpawn placement.
Environment
- Minecraft 1.18.2
- Forge 40.3.0
- OreSpawn 4.0.10.118021
- CurseForge/Maven artifact:
curse.maven:mmd-orespawn-245586:8750114
- OreSpawn source tag:
4.0.10.118021 (ccfe01a207a66d5c66342c3d534237a1540b9a78)
- Integrated test mod: CakeWorld
- Fixed world seed:
5059928472718672684
Provider rule that exposes the problem
"cakeworld:ore/fizzy_pearl": {
"block": "cakeworld:fizzy_pearl",
"enabled": true,
"source_mod": "cakeworld",
"retrogen": false,
"dimensions": {
"minecraft:overworld": {
"enabled": true,
"min_y": -48,
"max_y": 80,
"frequency": 0.35,
"quantity": 4,
"pattern": {
"type": "orespawn:underfluids",
"settings": {
"spread": 5,
"vertical_spread": 4,
"node_size": 2,
"length": 8,
"fluid": "cakeworld:lemonade"
}
},
"height_distribution": "uniform",
"discard_chance_on_air_exposure": 0.0,
"host_families": ["sedimentary", "metamorphic"],
"biome_ids": ["cakeworld:soda_ocean"],
"geomes": {
"cakeworld:wafer_shelf": 3.0
}
}
}
}
Integrated reproduction
From the CakeWorld 1.18.2 checkout, resolve the released CurseForge artifact and run the fixed-seed suite:
$env:JAVA_HOME='C:\Users\johnb\.jdks\jdk-17.0.1'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
$env:GRADLE_USER_HOME='D:\CakeWorld\.gradle-verify-cache'
.\gradlew.bat runGameTestServer --no-daemon `
-PcakeworldFreshWorldgenRuntime=true `
-PcakeworldFreshWorldgenRunDirectory=run-fresh-worldgen-os410-cursemaven-r10
Use an empty run directory for the fresh-world pass, then run the same command unchanged for the same-save reload pass. The focused test is focusedfizzypearlattributionaudit; the broad attribution evidence is emitted by the Deep Pantry tests.
Expected
Resource-key-equivalent runtime biomes pass biome_ids and biome_dictionary include filters and are rejected by the corresponding exclude filters, regardless of whether the Biome object came from the Forge registry or the server dynamic registry.
Given Soda Ocean, Lemonade, valid sedimentary/metamorphic floor hosts, and Wafer Shelf columns, at least one Fizzy Pearl should be attributable to OreSpawn outside CakeWorld's authored Wafer Reef Nursery treasure positions.
Actual
Fresh generation found ten Fizzy Pearls and all ten were authored Wafer Reef treasures. On same-save reload, a deliberate Brick persistence sentinel had replaced one treasure; all nine remaining pearls were still authored and zero were attributable to OreSpawn.
Reload diagnostics:
Focused Soda Ocean diagnostics:
blocks={cakeworld:lemonade=242028, cakeworld:fizzy_pearl=9}
surface_biomes={cakeworld:cookie_forest=14, cakeworld:candy_plains=31, cakeworld:soda_ocean=36}
surface_geomes={cakeworld:wafer_shelf=50, cakeworld:cocoa_basin=31}
lemonade_floor={cakeworld:wafer_rock=10669, cakeworld:biscuit_crumbs=14458, cakeworld:chocolate_sponge=4610, ...}
Broad Soda Ocean attribution observation:
authored_reef_treasures=9
under_lemonade_outside_authored_reefs=0
OS-085: Soda Ocean contained Lemonade and compatible floor hosts but OreSpawn generated no Fizzy Pearls outside 9 authored Wafer Reef Nursery treasures
The result was deterministic on fresh generation and reload.
Source-level reproduction / suspected cause
The filter can be reproduced independently of underfluids: resolve a biome ID through ForgeRegistries.BIOMES, put that object in an identity-backed set, then obtain the same biome key from a server dynamic biome registry. The key is equal but the object identity is not, so Set.contains(runtimeBiome) returns false.
The current ore path has exactly that shape:
generateChunk receives Holder<Biome> but calls ore.acceptsBiome(biome.value()).
resolveBiomes creates an IdentityHashMap-backed set and resolves both explicit IDs and dictionary keys to Biome objects from ForgeRegistries.BIOMES.
BakedOre.acceptsBiome compares the runtime object directly against those identity sets.
FluidDepositFeature already demonstrates the stable-key approach: it bakes Set<ResourceKey<Biome>>, accepts a Holder<Biome>, unwraps its key, and compares keys rather than biome objects.
Suggested regression tests
- Bake an explicit
biome_ids include filter, supply a dynamic-registry holder with the same resource key but a distinct biome object, and assert it is accepted.
- Repeat for
biome_dictionary include filters.
- Repeat both cases for
excluded_biome_ids and excluded_biome_dictionary, asserting rejection.
- Run an integrated custom-biome ore rule on a fresh world and same-save reload.
Acceptance criteria
- Ore include/exclude filters use stable biome keys (or an equivalent registry-safe representation), not
Biome object identity.
- Exact-ID and biome-dictionary filters behave consistently for Forge and dynamic registry instances.
- Filtering remains baked and allocation-free in the per-chunk/per-attempt hot path.
- The CakeWorld fixed-seed fresh/reload audit produces at least one OreSpawn-attributable Fizzy Pearl outside authored reef treasure positions.
Scope note
This ticket is for the filter gate, which runs before the compiled pattern. After that gate is fixed, the underfluids pattern should be retested separately. Its vertical sampling behavior may warrant a separate report, but the current filtered run cannot provide independent runtime evidence for that question.
Summary
Ore biome include/exclude filters are baked as identity-based
Set<Biome>values fromForgeRegistries.BIOMES, while chunk generation receives aHolder<Biome>from the server dynamic biome registry and passes onlybiome.value()to the filter. A runtime biome with the correct resource key but a different object identity is rejected bybiome_ids(and will not be recognized by the corresponding dictionary-derived set).This was observed with a CakeWorld
underfluidsore restricted tocakeworld:soda_ocean: the biome, target fluid, valid floor hosts, and expected geome were all present, but the ore filter prevented any attributable OreSpawn placement.Environment
curse.maven:mmd-orespawn-245586:87501144.0.10.118021(ccfe01a207a66d5c66342c3d534237a1540b9a78)5059928472718672684Provider rule that exposes the problem
Integrated reproduction
From the CakeWorld 1.18.2 checkout, resolve the released CurseForge artifact and run the fixed-seed suite:
Use an empty run directory for the fresh-world pass, then run the same command unchanged for the same-save reload pass. The focused test is
focusedfizzypearlattributionaudit; the broad attribution evidence is emitted by the Deep Pantry tests.Expected
Resource-key-equivalent runtime biomes pass
biome_idsandbiome_dictionaryinclude filters and are rejected by the corresponding exclude filters, regardless of whether theBiomeobject came from the Forge registry or the server dynamic registry.Given Soda Ocean, Lemonade, valid sedimentary/metamorphic floor hosts, and Wafer Shelf columns, at least one Fizzy Pearl should be attributable to OreSpawn outside CakeWorld's authored Wafer Reef Nursery treasure positions.
Actual
Fresh generation found ten Fizzy Pearls and all ten were authored Wafer Reef treasures. On same-save reload, a deliberate Brick persistence sentinel had replaced one treasure; all nine remaining pearls were still authored and zero were attributable to OreSpawn.
Reload diagnostics:
The result was deterministic on fresh generation and reload.
Source-level reproduction / suspected cause
The filter can be reproduced independently of
underfluids: resolve a biome ID throughForgeRegistries.BIOMES, put that object in an identity-backed set, then obtain the same biome key from a server dynamic biome registry. The key is equal but the object identity is not, soSet.contains(runtimeBiome)returns false.The current ore path has exactly that shape:
generateChunkreceivesHolder<Biome>but callsore.acceptsBiome(biome.value()).resolveBiomescreates anIdentityHashMap-backed set and resolves both explicit IDs and dictionary keys toBiomeobjects fromForgeRegistries.BIOMES.BakedOre.acceptsBiomecompares the runtime object directly against those identity sets.FluidDepositFeaturealready demonstrates the stable-key approach: it bakesSet<ResourceKey<Biome>>, accepts aHolder<Biome>, unwraps its key, and compares keys rather than biome objects.Suggested regression tests
biome_idsinclude filter, supply a dynamic-registry holder with the same resource key but a distinct biome object, and assert it is accepted.biome_dictionaryinclude filters.excluded_biome_idsandexcluded_biome_dictionary, asserting rejection.Acceptance criteria
Biomeobject identity.Scope note
This ticket is for the filter gate, which runs before the compiled pattern. After that gate is fixed, the
underfluidspattern should be retested separately. Its vertical sampling behavior may warrant a separate report, but the current filtered run cannot provide independent runtime evidence for that question.