Initial commit: RegionIO Minecraft server core (26.1.2/protocol 775)
Vanilla-faithful overworld generator (final_density + multi-noise biomes), full connection lifecycle (status/login/configuration/play), chunk streaming, creative block editing, and the protocol/nbt/registry infrastructure.
This commit is contained in:
commit
a7bb9496ae
146 changed files with 217621 additions and 0 deletions
88
internal/world/terrain.go
Normal file
88
internal/world/terrain.go
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package world
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"regionio/internal/worldgen"
|
||||
)
|
||||
|
||||
// SeaLevel is the water surface height for generated terrain.
|
||||
const SeaLevel = 63
|
||||
|
||||
// NewTerrainGenerator returns a chunk generator backed by a density function.
|
||||
// The density tree is built once (shared, read-only noise state) and sampled
|
||||
// per block.
|
||||
func NewTerrainGenerator(seed int64) Generator {
|
||||
density := worldgen.SimpleTerrain(seed)
|
||||
return func(cx, cz int32) *Chunk {
|
||||
return generateFromDensity(density, cx, cz)
|
||||
}
|
||||
}
|
||||
|
||||
// generateFromDensity fills a chunk by sampling the density function (>0 is
|
||||
// solid). The per-column sampling is the expensive part and is run in parallel
|
||||
// across the 16 x-rows; chunk assembly is sequential to avoid racing on lazy
|
||||
// section allocation. Sampling the density only reads shared noise state, so it
|
||||
// is safe to run concurrently.
|
||||
func generateFromDensity(d worldgen.DensityFunction, cx, cz int32) *Chunk {
|
||||
c := NewChunk(cx, cz, BiomePlains)
|
||||
|
||||
var columns [16][16][WorldHeight]uint16
|
||||
var wg sync.WaitGroup
|
||||
for lx := 0; lx < 16; lx++ {
|
||||
wg.Add(1)
|
||||
go func(lx int) {
|
||||
defer wg.Done()
|
||||
for lz := 0; lz < 16; lz++ {
|
||||
wx := float64(int(cx)*16 + lx)
|
||||
wz := float64(int(cz)*16 + lz)
|
||||
computeColumn(d, wx, wz, &columns[lx][lz])
|
||||
}
|
||||
}(lx)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for lx := 0; lx < 16; lx++ {
|
||||
for lz := 0; lz < 16; lz++ {
|
||||
col := &columns[lx][lz]
|
||||
for i := 0; i < WorldHeight; i++ {
|
||||
if s := col[i]; s != StateAir {
|
||||
c.SetBlock(lx, MinY+i, lz, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// computeColumn fills out with the block state for each Y in one column.
|
||||
func computeColumn(d worldgen.DensityFunction, wx, wz float64, out *[WorldHeight]uint16) {
|
||||
var solid [WorldHeight]bool
|
||||
top := -1
|
||||
for i := 0; i < WorldHeight; i++ {
|
||||
y := MinY + i
|
||||
if d.Compute(worldgen.FunctionContext{X: wx, Y: float64(y), Z: wz}) > 0 {
|
||||
solid[i] = true
|
||||
top = i
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < WorldHeight; i++ {
|
||||
y := MinY + i
|
||||
switch {
|
||||
case y == MinY:
|
||||
out[i] = StateBedrock
|
||||
case solid[i]:
|
||||
switch {
|
||||
case i == top && y >= SeaLevel:
|
||||
out[i] = StateGrass
|
||||
case i > top-4:
|
||||
out[i] = StateDirt
|
||||
default:
|
||||
out[i] = StateStone
|
||||
}
|
||||
case y < SeaLevel:
|
||||
out[i] = StateWater
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue