biome map stuff
This commit is contained in:
@@ -1630,6 +1630,7 @@
|
|||||||
"loginPacket": "pc/1.21.3",
|
"loginPacket": "pc/1.21.3",
|
||||||
"mapIcons": "pc/1.20.2",
|
"mapIcons": "pc/1.20.2",
|
||||||
"materials": "pc/1.21.8",
|
"materials": "pc/1.21.8",
|
||||||
|
"multi_noise_biome_source_parameter_list": "pc/1.21.8",
|
||||||
"particles": "pc/1.21.8",
|
"particles": "pc/1.21.8",
|
||||||
"protocol": "pc/1.21.8",
|
"protocol": "pc/1.21.8",
|
||||||
"recipes": "pc/1.21.8",
|
"recipes": "pc/1.21.8",
|
||||||
@@ -1657,6 +1658,7 @@
|
|||||||
"loginPacket": "pc/1.21.9",
|
"loginPacket": "pc/1.21.9",
|
||||||
"mapIcons": "pc/1.20.2",
|
"mapIcons": "pc/1.20.2",
|
||||||
"materials": "pc/1.21.9",
|
"materials": "pc/1.21.9",
|
||||||
|
"multi_noise_biome_source_parameter_list": "pc/1.21.9",
|
||||||
"particles": "pc/1.21.9",
|
"particles": "pc/1.21.9",
|
||||||
"protocol": "pc/1.21.9",
|
"protocol": "pc/1.21.9",
|
||||||
"recipes": "pc/1.21.9",
|
"recipes": "pc/1.21.9",
|
||||||
@@ -1711,6 +1713,7 @@
|
|||||||
"loginPacket": "pc/1.21.11",
|
"loginPacket": "pc/1.21.11",
|
||||||
"mapIcons": "pc/1.20.2",
|
"mapIcons": "pc/1.20.2",
|
||||||
"materials": "pc/1.21.11",
|
"materials": "pc/1.21.11",
|
||||||
|
"multi_noise_biome_source_parameter_list": "pc/1.21.11",
|
||||||
"particles": "pc/1.21.11",
|
"particles": "pc/1.21.11",
|
||||||
"protocol": "pc/1.21.11",
|
"protocol": "pc/1.21.11",
|
||||||
"recipes": "pc/1.21.11",
|
"recipes": "pc/1.21.11",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,9 @@ func peaksAndValleys(weirdness float64) float64 {
|
|||||||
return -(math.Abs(math.Abs(weirdness)-0.6666667) - 0.33333334) * 3.0
|
return -(math.Abs(math.Abs(weirdness)-0.6666667) - 0.33333334) * 3.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sample returns the raw climate parameters at the block position.
|
||||||
|
// The returned id is currently unused and always 0; use SampleBiome to resolve
|
||||||
|
// the biome from a multi-noise parameter list.
|
||||||
func (b BiomeNoise) Sample(x, y, z int) (t, h, c, e, d, w float64, combinedData [6]int64, id int) {
|
func (b BiomeNoise) Sample(x, y, z int) (t, h, c, e, d, w float64, combinedData [6]int64, id int) {
|
||||||
px := float64(x)
|
px := float64(x)
|
||||||
pz := float64(z)
|
pz := float64(z)
|
||||||
@@ -85,3 +88,11 @@ func (b BiomeNoise) Sample(x, y, z int) (t, h, c, e, d, w float64, combinedData
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SampleBiome samples the climate noise at (x, y, z) and resolves it through
|
||||||
|
// the supplied multi-noise parameter list. preset should be one of the
|
||||||
|
// MultiNoise* constants.
|
||||||
|
func (b BiomeNoise) SampleBiome(x, y, z int, data *MultiNoiseData, preset string) (string, error) {
|
||||||
|
_, _, _, _, _, _, combined, _ := b.Sample(x, y, z)
|
||||||
|
return data.Lookup(preset, combined[0], combined[1], combined[2], combined[3], combined[4], combined[5])
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/mc/data"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MultiNoisePreset names the two built-in multi-noise parameter lists.
|
||||||
|
const (
|
||||||
|
MultiNoiseOverworld = "minecraft:overworld"
|
||||||
|
MultiNoiseNether = "minecraft:nether"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParamRange is a single quantized parameter range [Min, Max].
|
||||||
|
type ParamRange struct {
|
||||||
|
Min, Max int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParameterPoint is a 6-D parameter box plus an offset used by Minecraft's
|
||||||
|
// climate distance function.
|
||||||
|
type ParameterPoint struct {
|
||||||
|
Biome string
|
||||||
|
Temperature ParamRange
|
||||||
|
Humidity ParamRange
|
||||||
|
Continentalness ParamRange
|
||||||
|
Erosion ParamRange
|
||||||
|
Depth ParamRange
|
||||||
|
Weirdness ParamRange
|
||||||
|
Offset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiNoiseData holds the parameter lists for each preset.
|
||||||
|
type MultiNoiseData struct {
|
||||||
|
Presets map[string][]ParameterPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// raw JSON shapes.
|
||||||
|
type rawParameter struct {
|
||||||
|
Temperature [2]int64 `json:"temperature"`
|
||||||
|
Humidity [2]int64 `json:"humidity"`
|
||||||
|
Continentalness [2]int64 `json:"continentalness"`
|
||||||
|
Erosion [2]int64 `json:"erosion"`
|
||||||
|
Depth [2]int64 `json:"depth"`
|
||||||
|
Weirdness [2]int64 `json:"weirdness"`
|
||||||
|
Offset float64 `json:"offset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type rawEntry struct {
|
||||||
|
Biome string `json:"biome"`
|
||||||
|
Parameters rawParameter `json:"parameters"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type rawMultiNoise map[string][]rawEntry
|
||||||
|
|
||||||
|
// LoadMultiNoise loads the expanded multi-noise parameter list for a Minecraft
|
||||||
|
// version. The data is expected to be present under the
|
||||||
|
// "multi_noise_biome_source_parameter_list" key in minecraft-data.
|
||||||
|
func LoadMultiNoise(version string) (*MultiNoiseData, error) {
|
||||||
|
var raw rawMultiNoise
|
||||||
|
if err := data.LoadVersionedJson(version, "multi_noise_biome_source_parameter_list", &raw); err != nil {
|
||||||
|
return nil, fmt.Errorf("load multi_noise for %s: %w", version, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := &MultiNoiseData{Presets: make(map[string][]ParameterPoint, len(raw))}
|
||||||
|
for preset, entries := range raw {
|
||||||
|
points := make([]ParameterPoint, len(entries))
|
||||||
|
for i, e := range entries {
|
||||||
|
points[i] = ParameterPoint{
|
||||||
|
Biome: e.Biome,
|
||||||
|
Temperature: ParamRange{Min: e.Parameters.Temperature[0], Max: e.Parameters.Temperature[1]},
|
||||||
|
Humidity: ParamRange{Min: e.Parameters.Humidity[0], Max: e.Parameters.Humidity[1]},
|
||||||
|
Continentalness: ParamRange{Min: e.Parameters.Continentalness[0], Max: e.Parameters.Continentalness[1]},
|
||||||
|
Erosion: ParamRange{Min: e.Parameters.Erosion[0], Max: e.Parameters.Erosion[1]},
|
||||||
|
Depth: ParamRange{Min: e.Parameters.Depth[0], Max: e.Parameters.Depth[1]},
|
||||||
|
Weirdness: ParamRange{Min: e.Parameters.Weirdness[0], Max: e.Parameters.Weirdness[1]},
|
||||||
|
Offset: int64(math.Round(e.Parameters.Offset * 10000.0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Presets[preset] = points
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup finds the biome whose parameter box is closest to the supplied
|
||||||
|
// quantized climate parameters. The preset argument should be one of the
|
||||||
|
// MultiNoise* constants.
|
||||||
|
func (m *MultiNoiseData) Lookup(preset string, t, h, c, e, d, w int64) (string, error) {
|
||||||
|
points, ok := m.Presets[preset]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("unknown multi-noise preset: %s", preset)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(points) == 0 {
|
||||||
|
return "", fmt.Errorf("multi-noise preset %s has no entries", preset)
|
||||||
|
}
|
||||||
|
|
||||||
|
bestBiome := ""
|
||||||
|
bestDist := int64(math.MaxInt64)
|
||||||
|
|
||||||
|
for _, p := range points {
|
||||||
|
dist := distanceToRange(t, p.Temperature) +
|
||||||
|
distanceToRange(h, p.Humidity) +
|
||||||
|
distanceToRange(c, p.Continentalness) +
|
||||||
|
distanceToRange(e, p.Erosion) +
|
||||||
|
distanceToRange(d, p.Depth) +
|
||||||
|
distanceToRange(w, p.Weirdness) +
|
||||||
|
p.Offset
|
||||||
|
|
||||||
|
if dist < bestDist {
|
||||||
|
bestDist = dist
|
||||||
|
bestBiome = p.Biome
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestBiome, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func distanceToRange(value int64, r ParamRange) int64 {
|
||||||
|
if value < r.Min {
|
||||||
|
d := r.Min - value
|
||||||
|
return d * d
|
||||||
|
}
|
||||||
|
if value > r.Max {
|
||||||
|
d := value - r.Max
|
||||||
|
return d * d
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadMultiNoise(t *testing.T) {
|
||||||
|
for _, version := range []string{"1.21.8", "1.21.9", "1.21.11"} {
|
||||||
|
data, err := LoadMultiNoise(version)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("LoadMultiNoise(%q): %v", version, err)
|
||||||
|
}
|
||||||
|
if len(data.Presets[MultiNoiseOverworld]) == 0 {
|
||||||
|
t.Errorf("%s: overworld preset empty", version)
|
||||||
|
}
|
||||||
|
if len(data.Presets[MultiNoiseNether]) == 0 {
|
||||||
|
t.Errorf("%s: nether preset empty", version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiNoiseLookup_NetherOrigin(t *testing.T) {
|
||||||
|
data, err := LoadMultiNoise("1.21.11")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("LoadMultiNoise: %v", err)
|
||||||
|
}
|
||||||
|
biome, err := data.Lookup(MultiNoiseNether, 0, 0, 0, 0, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Lookup: %v", err)
|
||||||
|
}
|
||||||
|
if biome != "minecraft:nether_wastes" {
|
||||||
|
t.Errorf("nether origin = %s, want minecraft:nether_wastes", biome)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBiomeNoise_SampleBiome(t *testing.T) {
|
||||||
|
var worldSeed int64 = 70388202460762
|
||||||
|
x := XoroshiroFromSeed(worldSeed)
|
||||||
|
x.Mix()
|
||||||
|
b := BiomeNoiseFromXoroshiro(x, false)
|
||||||
|
data, err := LoadMultiNoise("1.21.11")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("LoadMultiNoise: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
biome, err := b.SampleBiome(-1, -16, 0, data, MultiNoiseOverworld)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("SampleBiome: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := "minecraft:bamboo_jungle"
|
||||||
|
if biome != expected {
|
||||||
|
t.Errorf("SampleBiome(-1, -16, 0) = %s, want %s", biome, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user