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:
Master290 2026-06-24 00:32:51 +03:00
commit a7bb9496ae
146 changed files with 217621 additions and 0 deletions

View file

@ -0,0 +1,122 @@
package worldgen
import (
"math"
"strconv"
)
// PerlinNoise is an octave sum of ImprovedNoise layers, matching the official
// PerlinNoise (non-legacy factory path).
type PerlinNoise struct {
octaves []*ImprovedNoise // entries may be nil for zero amplitudes
amplitudes []float64
firstOctave int
lowestFreqInputFactor float64
lowestFreqValueFactor float64
maxValue float64
}
// NewPerlinNoise builds a PerlinNoise over the given amplitudes starting at
// firstOctave. Each octave is seeded by the positional factory's hash of
// "octave_<n>", exactly as vanilla does.
func NewPerlinNoise(r RandomSource, firstOctave int, amplitudes []float64) *PerlinNoise {
count := len(amplitudes)
p := &PerlinNoise{
octaves: make([]*ImprovedNoise, count),
amplitudes: amplitudes,
firstOctave: firstOctave,
}
factory := r.ForkPositional()
for k := 0; k < count; k++ {
if amplitudes[k] != 0 {
octave := firstOctave + k
p.octaves[k] = NewImprovedNoise(factory.FromHashOf("octave_" + strconv.Itoa(octave)))
}
}
p.lowestFreqInputFactor = math.Pow(2, float64(firstOctave))
p.lowestFreqValueFactor = math.Pow(2, float64(count-1)) / (math.Pow(2, float64(count)) - 1)
p.maxValue = p.edgeValue(2.0)
return p
}
// NewLegacyPerlinNoise builds a PerlinNoise with the legacy (non-positional)
// octave seeding used by BlendedNoise: octaves are drawn sequentially from r,
// starting with the zero octave, then descending. Skipped (zero-amplitude)
// octaves consume a fixed number of draws.
func NewLegacyPerlinNoise(r RandomSource, firstOctave int, amplitudes []float64) *PerlinNoise {
octaves := len(amplitudes)
zeroIdx := -firstOctave
p := &PerlinNoise{
octaves: make([]*ImprovedNoise, octaves),
amplitudes: amplitudes,
firstOctave: firstOctave,
}
zeroOctave := NewImprovedNoise(r) // always drawn
if zeroIdx >= 0 && zeroIdx < octaves && amplitudes[zeroIdx] != 0 {
p.octaves[zeroIdx] = zeroOctave
}
for i := zeroIdx - 1; i >= 0; i-- {
if i < octaves && amplitudes[i] != 0 {
p.octaves[i] = NewImprovedNoise(r)
} else {
r.ConsumeCount(262) // skipOctave
}
}
p.lowestFreqInputFactor = math.Pow(2, float64(-zeroIdx))
p.lowestFreqValueFactor = math.Pow(2, float64(octaves-1)) / (math.Pow(2, float64(octaves)) - 1)
p.maxValue = p.edgeValue(2.0)
return p
}
// GetOctaveNoise returns the i-th octave from the high-frequency end (vanilla's
// reverse indexing), or nil if that octave's amplitude is zero.
func (p *PerlinNoise) GetOctaveNoise(i int) *ImprovedNoise {
return p.octaves[len(p.octaves)-1-i]
}
// MaxBrokenValue is PerlinNoise.maxBrokenValue: edgeValue(yScale + 2).
func (p *PerlinNoise) MaxBrokenValue(yScale float64) float64 { return p.edgeValue(yScale + 2.0) }
// GetValue samples the octave sum at (x, y, z).
func (p *PerlinNoise) GetValue(x, y, z float64) float64 { return p.GetValueY(x, y, z, 0, 0) }
// GetValueY is the 5-argument octave sum used with Y-smearing.
func (p *PerlinNoise) GetValueY(x, y, z, yScale, yFudge float64) float64 {
d := 0.0
inputFactor := p.lowestFreqInputFactor
valueFactor := p.lowestFreqValueFactor
for i, oct := range p.octaves {
if oct != nil {
g := oct.NoiseY(wrap(x*inputFactor), wrap(y*inputFactor), wrap(z*inputFactor),
yScale*inputFactor, yFudge*inputFactor)
d += p.amplitudes[i] * g * valueFactor
}
inputFactor *= 2.0
valueFactor /= 2.0
}
return d
}
// MaxValue returns the theoretical maximum magnitude.
func (p *PerlinNoise) MaxValue() float64 { return p.maxValue }
func (p *PerlinNoise) edgeValue(x float64) float64 {
e := 0.0
valueFactor := p.lowestFreqValueFactor
for i, oct := range p.octaves {
if oct != nil {
e += p.amplitudes[i] * x * valueFactor
}
valueFactor /= 2.0
}
return e
}
// wrap is PerlinNoise.wrap: folds large coordinates back near the origin to
// preserve floating-point precision. The constant is 2^25.
func wrap(value float64) float64 {
const period = 3.3554432e7
return value - float64(int64(math.Floor(value/period+0.5)))*period
}