From 4fa0a5e55490f33dd4ff00e453c59a18dc72957e Mon Sep 17 00:00:00 2001 From: Daniar Mannanov Date: Mon, 17 Aug 2026 10:56:05 +0300 Subject: [PATCH] Match very biased height sampling --- internal/world/store.go | 2 +- internal/worldgen/features.go | 5 ++--- internal/worldgen/features_test.go | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/internal/world/store.go b/internal/world/store.go index 7011bf6..26b0fd9 100644 --- a/internal/world/store.go +++ b/internal/world/store.go @@ -33,7 +33,7 @@ const dataVersion26 = 4790 // first time it ran: chunkAt prefers the store over the generator, so the // already-explored area around spawn keeps its old terrain and every later fix // looks like it did nothing in exactly the place you are standing. -const generatorVersion = 19 +const generatorVersion = 20 // generatorVersionTag is the NBT key holding generatorVersion. It is namespaced // because it is ours, not part of the vanilla chunk format. diff --git a/internal/worldgen/features.go b/internal/worldgen/features.go index 774f966..82a18c5 100644 --- a/internal/worldgen/features.go +++ b/internal/worldgen/features.go @@ -210,9 +210,8 @@ func (p PlacementPlan) SampleY(r RandomSource, minY, height int) int { if span-inner <= 0 { return lo } - first := lo + inner + int(r.NextIntN(int32(span-inner))) - second := lo + int(r.NextIntN(int32(first-lo))) - return lo + int(r.NextIntN(int32(second-lo+inner))) + first := int(r.NextIntN(int32(span - inner))) + return lo + int(r.NextIntN(int32(first+inner))) } return lo + int(r.NextIntN(int32(span))) } diff --git a/internal/worldgen/features_test.go b/internal/worldgen/features_test.go index 23eb42f..a0aef29 100644 --- a/internal/worldgen/features_test.go +++ b/internal/worldgen/features_test.go @@ -137,6 +137,26 @@ func TestPlacementHeightDistributionsStayWithinInclusiveBounds(t *testing.T) { } } +func TestVeryBiasedToBottomConsumesVanillaDraws(t *testing.T) { + plan := PlacementPlan{ + HeightDistribution: "minecraft:very_biased_to_bottom", + MinY: HeightProvider{Absolute: intPtr(-64)}, + MaxY: HeightProvider{Absolute: intPtr(320)}, + } + gotRandom := NewLegacy(12345) + wantRandom := NewLegacy(12345) + for sample := 0; sample < 16; sample++ { + first := int(wantRandom.NextIntN(377)) + want := -64 + int(wantRandom.NextIntN(int32(first+8))) + if got := plan.SampleY(gotRandom, -64, 384); got != want { + t.Fatalf("sample %d = %d, want %d", sample, got, want) + } + } + if got, want := gotRandom.NextLong(), wantRandom.NextLong(); got != want { + t.Fatalf("random state after samples = %d, want %d", got, want) + } +} + func TestPlacementPositionsPreservesModifierOrder(t *testing.T) { modifier := func(raw string) PlacementModifier { var value PlacementModifier