Schedule features from mutable regions

This commit is contained in:
Daniar Mannanov 2026-08-11 13:23:45 +03:00
parent 4ff62d7c96
commit d01e576dcc
2 changed files with 72 additions and 5 deletions

View file

@ -128,6 +128,28 @@ func (r *decorationRegion) sourceBiomes() []string {
return names
}
func (r *decorationRegion) scheduledFeatures(stage int) ([]worldgen.ScheduledFeature, error) {
set, err := worldgen.LoadFeatureSet()
if err != nil {
return nil, err
}
if err := r.ensureSourceNeighborhood(); err != nil {
return nil, err
}
return set.FeatureSchedule(possibleBiomeOrder(), r.sourceBiomes(), stage)
}
func (r *decorationRegion) ensureSourceNeighborhood() error {
for cx := r.sourceX - 1; cx <= r.sourceX+1; cx++ {
for cz := r.sourceZ - 1; cz <= r.sourceZ+1; cz++ {
if _, ok := r.chunks[[2]int32{cx, cz}]; !ok {
return fmt.Errorf("world: source biome neighborhood missing (%d,%d)", cx, cz)
}
}
}
return nil
}
func (r *decorationRegion) placementContext(biomeAllows func(worldgen.FeaturePosition) bool) worldgen.PlacementContext {
set, err := worldgen.LoadFeatureSet()
if err != nil {

View file

@ -66,10 +66,14 @@ func TestDecorationRegionHeightmapsMatchPlacementSemantics(t *testing.T) {
}
func TestDecorationRegionSourceBiomesUseThreeByThreeChunks(t *testing.T) {
center := NewChunk(0, 0, BiomePlains)
east := NewChunk(1, 0, biomeIDByName("minecraft:desert"))
outside := NewChunk(2, 0, biomeIDByName("minecraft:forest"))
region, err := newDecorationRegion([]*Chunk{center, east, outside})
var chunks []*Chunk
for cx := int32(-1); cx <= 1; cx++ {
for cz := int32(-1); cz <= 1; cz++ {
chunks = append(chunks, NewChunk(cx, cz, BiomePlains))
}
}
chunks = append(chunks, NewChunk(2, 0, biomeIDByName("minecraft:forest")))
region, err := newDecorationRegion(chunks)
if err != nil {
t.Fatal(err)
}
@ -77,8 +81,49 @@ func TestDecorationRegionSourceBiomesUseThreeByThreeChunks(t *testing.T) {
t.Fatal(err)
}
got := region.sourceBiomes()
want := []string{"minecraft:plains", "minecraft:desert"}
want := []string{"minecraft:plains"}
if !reflect.DeepEqual(got, want) {
t.Fatalf("source biomes = %v, want %v", got, want)
}
}
func TestDecorationRegionSchedulesRealFeatureStage(t *testing.T) {
var chunks []*Chunk
for cx := int32(-1); cx <= 1; cx++ {
for cz := int32(-1); cz <= 1; cz++ {
chunks = append(chunks, NewChunk(cx, cz, BiomePlains))
}
}
region, err := newDecorationRegion(chunks)
if err != nil {
t.Fatal(err)
}
if err := region.setSource(0, 0); err != nil {
t.Fatal(err)
}
features, err := region.scheduledFeatures(undergroundOresStage)
if err != nil {
t.Fatal(err)
}
if len(features) == 0 {
t.Fatal("plains underground stage produced no scheduled features")
}
for i, feature := range features {
if i > 0 && feature.Index <= features[i-1].Index {
t.Fatalf("feature %s index %d is not after index %d", feature.Name, feature.Index, features[i-1].Index)
}
}
}
func TestDecorationRegionRequiresSourceBiomeNeighborhood(t *testing.T) {
region, err := newDecorationRegion([]*Chunk{NewChunk(0, 0, BiomePlains)})
if err != nil {
t.Fatal(err)
}
if err := region.setSource(0, 0); err != nil {
t.Fatal(err)
}
if _, err := region.scheduledFeatures(undergroundOresStage); err == nil {
t.Fatal("missing source neighborhood succeeded")
}
}