world: ruined portal stub matches vanilla's saved start bit-for-bit

Three fixes close the loop against the captured region file: the giant
roll precedes the template draw, surfaceY is the topmost non-air block
(getHeight already returns one past it), and structure biome refs
resolve through has_structure/ tags to the extracted tag files. The
weighted variant pick walks a fresh per-attempt GenerationContext
stream while failed entries drop from the pick stream without reseeding.

TestRuinedPortalStubMatchesVanillaStart pins chunk (1,0) to vanilla's
own saved start: portal_6, CLOCKWISE_90, mirror NONE, air pocket,
template position (16,12,0) — and asserts the neighbouring fixture
chunks stay portal-free.
This commit is contained in:
Daniar Mannanov 2026-08-26 14:42:18 +03:00
parent 798a3ec7b4
commit 90eb08f37d
4 changed files with 88 additions and 3 deletions

View file

@ -199,9 +199,12 @@ func ruinedPortalVariantPoint(od *worldgen.OverworldDensity, sets *worldgen.Stru
airPocket := sampleProbability(random, setup.AirPocketProbability)
templateName := ruinedPortalTemplates[int(random.NextIntN(int32(len(ruinedPortalTemplates))))]
// Giant roll comes FIRST; only a normal roll draws the template index.
templateName := ""
if random.NextFloat() < 0.05 {
templateName = ruinedPortalGiants[int(random.NextIntN(int32(len(ruinedPortalGiants))))]
} else {
templateName = ruinedPortalTemplates[int(random.NextIntN(int32(len(ruinedPortalTemplates))))]
}
_, size, err := loadTemplateCached(templateName)
if err != nil {