From b8c57be2f7509d9a72c052aa570566fedb608863 Mon Sep 17 00:00:00 2001 From: Daniar Mannanov Date: Tue, 18 Aug 2026 01:43:55 +0300 Subject: [PATCH] Add vanilla base batch generator --- internal/world/vanilla.go | 30 ++++++++++++++++++++++--- internal/world/vanilla_batch_test.go | 33 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 internal/world/vanilla_batch_test.go diff --git a/internal/world/vanilla.go b/internal/world/vanilla.go index 1735518..021659b 100644 --- a/internal/world/vanilla.go +++ b/internal/world/vanilla.go @@ -26,6 +26,32 @@ type cornerGrid [cellsXZ + 1][cellsY + 1][cellsXZ + 1]float64 // final_density tree for the given seed, plus a simplified cosmetic pass // (beaches and trees) layered on the bit-accurate terrain. func NewVanillaGenerator(seed int64) Generator { + od, fluidPicker, veins, carver := vanillaGeneratorInputs(seed) + return func(cx, cz int32) *Chunk { + return generateVanilla(od, fluidPicker, veins, carver, seed, cx, cz) + } +} + +// NewVanillaBaseBatchGenerator returns an opt-in batch generator for the +// terrain stage. It builds the target and its 3x3 source neighborhood without +// decoration; a future region decorator can then mutate that neighborhood and +// publish the finished chunks atomically through Cache.SetBatchGenerator. +// Production still uses NewVanillaGenerator until that publication step is +// integrated, because this batch intentionally returns undecorated terrain. +func NewVanillaBaseBatchGenerator(seed int64) BatchGenerator { + od, fluidPicker, veins, carver := vanillaGeneratorInputs(seed) + return func(targetX, targetZ int32) (map[[2]int32]*Chunk, error) { + batch := make(map[[2]int32]*Chunk, 9) + for cx := targetX - 1; cx <= targetX+1; cx++ { + for cz := targetZ - 1; cz <= targetZ+1; cz++ { + batch[[2]int32{cx, cz}] = generateVanillaWithoutDecoration(od, fluidPicker, veins, carver, seed, cx, cz) + } + } + return batch, nil + } +} + +func vanillaGeneratorInputs(seed int64) (*worldgen.OverworldDensity, worldgen.FluidPicker, *worldgen.OreVeinifier, *worldgen.Carver) { od, err := worldgen.LoadOverworldFinalDensity(seed) if err != nil { panic("world: loading overworld density: " + err.Error()) @@ -37,9 +63,7 @@ func NewVanillaGenerator(seed int64) Generator { panic("world: loading carvers: " + err.Error()) } initCarverReplaceable(carver.ReplaceableBlocks()) - return func(cx, cz int32) *Chunk { - return generateVanilla(od, fluidPicker, veins, carver, seed, cx, cz) - } + return od, fluidPicker, veins, carver } func generateVanilla(od *worldgen.OverworldDensity, fluidPicker worldgen.FluidPicker, veins *worldgen.OreVeinifier, carver *worldgen.Carver, seed int64, cx, cz int32) *Chunk { diff --git a/internal/world/vanilla_batch_test.go b/internal/world/vanilla_batch_test.go new file mode 100644 index 0000000..ebb9219 --- /dev/null +++ b/internal/world/vanilla_batch_test.go @@ -0,0 +1,33 @@ +package world + +import "testing" + +func TestVanillaBaseBatchCoversSourceNeighborhood(t *testing.T) { + batch, err := NewVanillaBaseBatchGenerator(12345)(2, -3) + if err != nil { + t.Fatal(err) + } + if len(batch) != 9 { + t.Fatalf("base batch size = %d, want 9", len(batch)) + } + for cx := int32(1); cx <= 3; cx++ { + for cz := int32(-4); cz <= -2; cz++ { + chunk := batch[[2]int32{cx, cz}] + if chunk == nil { + t.Fatalf("missing base chunk (%d,%d)", cx, cz) + } + if chunk.X != cx || chunk.Z != cz { + t.Fatalf("chunk coordinates = (%d,%d), want (%d,%d)", chunk.X, chunk.Z, cx, cz) + } + for y := SeaLevel; y < 160; y++ { + for x := 0; x < 16; x++ { + for z := 0; z < 16; z++ { + if chunk.GetBlock(x, y, z) == StateOakLog { + t.Fatalf("base chunk (%d,%d) contains decoration oak log", cx, cz) + } + } + } + } + } + } +}