重构 BiomesState, fix typo
This commit is contained in:
@ -1,83 +1,102 @@
|
|||||||
package biome
|
package biome
|
||||||
|
|
||||||
import "math/bits"
|
import (
|
||||||
|
"errors"
|
||||||
|
"math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
type Type int
|
type Type int
|
||||||
|
|
||||||
|
func (t Type) MarshalText() (text []byte, err error) {
|
||||||
|
if t >= 0 && int(t) < len(biomesNames) {
|
||||||
|
return []byte(biomesNames[t]), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) UnmarshalText(text []byte) error {
|
||||||
|
var ok bool
|
||||||
|
*t, ok = biomesIDs[string(text)]
|
||||||
|
if ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("unknown type")
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BitsPerBiome int
|
BitsPerBiome int
|
||||||
BiomesIDs map[string]Type
|
biomesIDs map[string]Type
|
||||||
BiomesNames = []string{
|
biomesNames = []string{
|
||||||
"the_void",
|
"minecraft:the_void",
|
||||||
"plains",
|
"minecraft:plains",
|
||||||
"sunflower_plains",
|
"minecraft:sunflower_plains",
|
||||||
"snowy_plains",
|
"minecraft:snowy_plains",
|
||||||
"ice_spikes",
|
"minecraft:ice_spikes",
|
||||||
"desert",
|
"minecraft:desert",
|
||||||
"swamp",
|
"minecraft:swamp",
|
||||||
"mangrove_swamp",
|
"minecraft:mangrove_swamp",
|
||||||
"forest",
|
"minecraft:forest",
|
||||||
"flower_forest",
|
"minecraft:flower_forest",
|
||||||
"birch_forest",
|
"minecraft:birch_forest",
|
||||||
"dark_forest",
|
"minecraft:dark_forest",
|
||||||
"old_growth_birch_forest",
|
"minecraft:old_growth_birch_forest",
|
||||||
"old_growth_pine_taiga",
|
"minecraft:old_growth_pine_taiga",
|
||||||
"old_growth_spruce_taiga",
|
"minecraft:old_growth_spruce_taiga",
|
||||||
"taiga",
|
"minecraft:taiga",
|
||||||
"snowy_taiga",
|
"minecraft:snowy_taiga",
|
||||||
"savanna",
|
"minecraft:savanna",
|
||||||
"savanna_plateau",
|
"minecraft:savanna_plateau",
|
||||||
"windswept_hills",
|
"minecraft:windswept_hills",
|
||||||
"windswept_gravelly_hills",
|
"minecraft:windswept_gravelly_hills",
|
||||||
"windswept_forest",
|
"minecraft:windswept_forest",
|
||||||
"windswept_savanna",
|
"minecraft:windswept_savanna",
|
||||||
"jungle",
|
"minecraft:jungle",
|
||||||
"sparse_jungle",
|
"minecraft:sparse_jungle",
|
||||||
"bamboo_jungle",
|
"minecraft:bamboo_jungle",
|
||||||
"badlands",
|
"minecraft:badlands",
|
||||||
"eroded_badlands",
|
"minecraft:eroded_badlands",
|
||||||
"wooded_badlands",
|
"minecraft:wooded_badlands",
|
||||||
"meadow",
|
"minecraft:meadow",
|
||||||
"grove",
|
"minecraft:grove",
|
||||||
"snowy_slopes",
|
"minecraft:snowy_slopes",
|
||||||
"frozen_peaks",
|
"minecraft:frozen_peaks",
|
||||||
"jagged_peaks",
|
"minecraft:jagged_peaks",
|
||||||
"stony_peaks",
|
"minecraft:stony_peaks",
|
||||||
"river",
|
"minecraft:river",
|
||||||
"frozen_river",
|
"minecraft:frozen_river",
|
||||||
"beach",
|
"minecraft:beach",
|
||||||
"snowy_beach",
|
"minecraft:snowy_beach",
|
||||||
"stony_shore",
|
"minecraft:stony_shore",
|
||||||
"warm_ocean",
|
"minecraft:warm_ocean",
|
||||||
"lukewarm_ocean",
|
"minecraft:lukewarm_ocean",
|
||||||
"deep_lukewarm_ocean",
|
"minecraft:deep_lukewarm_ocean",
|
||||||
"ocean",
|
"minecraft:ocean",
|
||||||
"deep_ocean",
|
"minecraft:deep_ocean",
|
||||||
"cold_ocean",
|
"minecraft:cold_ocean",
|
||||||
"deep_cold_ocean",
|
"minecraft:deep_cold_ocean",
|
||||||
"frozen_ocean",
|
"minecraft:frozen_ocean",
|
||||||
"deep_frozen_ocean",
|
"minecraft:deep_frozen_ocean",
|
||||||
"mushroom_fields",
|
"minecraft:mushroom_fields",
|
||||||
"dripstone_caves",
|
"minecraft:dripstone_caves",
|
||||||
"lush_caves",
|
"minecraft:lush_caves",
|
||||||
"deep_dark",
|
"minecraft:deep_dark",
|
||||||
"nether_wastes",
|
"minecraft:nether_wastes",
|
||||||
"warped_forest",
|
"minecraft:warped_forest",
|
||||||
"crimson_forest",
|
"minecraft:crimson_forest",
|
||||||
"soul_sand_valley",
|
"minecraft:soul_sand_valley",
|
||||||
"basalt_deltas",
|
"minecraft:basalt_deltas",
|
||||||
"the_end",
|
"minecraft:the_end",
|
||||||
"end_highlands",
|
"minecraft:end_highlands",
|
||||||
"end_midlands",
|
"minecraft:end_midlands",
|
||||||
"small_end_islands",
|
"minecraft:small_end_islands",
|
||||||
"end_barrens",
|
"minecraft:end_barrens",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
BitsPerBiome = bits.Len(uint(len(BiomesNames)))
|
BitsPerBiome = bits.Len(uint(len(biomesNames)))
|
||||||
BiomesIDs = make(map[string]Type, len(BiomesNames))
|
biomesIDs = make(map[string]Type, len(biomesNames))
|
||||||
for i, v := range BiomesNames {
|
for i, v := range biomesNames {
|
||||||
BiomesIDs[v] = Type(i)
|
biomesIDs[v] = Type(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ func (b *BitStorage) WriteTo(w io.Writer) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fix recalculate BitStorage internal values for given bits.
|
// Fix recalculate BitStorage internal values for given bits.
|
||||||
// Typically, you should call this method after ReadFrom is called, internal data is changed.
|
// Typically, you should call this method after ReadFrom is called, which cause internal data is changed.
|
||||||
func (b *BitStorage) Fix(bits int) error {
|
func (b *BitStorage) Fix(bits int) error {
|
||||||
if bits == 0 {
|
if bits == 0 {
|
||||||
b.mask = 0
|
b.mask = 0
|
||||||
|
@ -7,9 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/level/biome"
|
|
||||||
"github.com/Tnze/go-mc/level/block"
|
"github.com/Tnze/go-mc/level/block"
|
||||||
"github.com/Tnze/go-mc/nbt"
|
"github.com/Tnze/go-mc/nbt"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
@ -59,7 +57,12 @@ func EmptyChunk(secs int) *Chunk {
|
|||||||
return &Chunk{
|
return &Chunk{
|
||||||
Sections: sections,
|
Sections: sections,
|
||||||
HeightMaps: HeightMaps{
|
HeightMaps: HeightMaps{
|
||||||
MotionBlocking: NewBitStorage(bits.Len(uint(secs)*16), 16*16, nil),
|
WorldSurfaceWG: NewBitStorage(bits.Len(uint(secs)*16+1), 16*16, nil),
|
||||||
|
WorldSurface: NewBitStorage(bits.Len(uint(secs)*16+1), 16*16, nil),
|
||||||
|
OceanFloorWG: NewBitStorage(bits.Len(uint(secs)*16+1), 16*16, nil),
|
||||||
|
OceanFloor: NewBitStorage(bits.Len(uint(secs)*16+1), 16*16, nil),
|
||||||
|
MotionBlocking: NewBitStorage(bits.Len(uint(secs)*16+1), 16*16, nil),
|
||||||
|
MotionBlockingNoLeaves: NewBitStorage(bits.Len(uint(secs)*16+1), 16*16, nil),
|
||||||
},
|
},
|
||||||
Status: StatusEmpty,
|
Status: StatusEmpty,
|
||||||
}
|
}
|
||||||
@ -145,13 +148,12 @@ func readStatesPalette(palette []save.BlockState, data []uint64) (paletteData *P
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func readBiomesPalette(palette []string, data []uint64) (*PaletteContainer[BiomesState], error) {
|
func readBiomesPalette(palette []save.BiomeState, data []uint64) (*PaletteContainer[BiomesState], error) {
|
||||||
biomesRawPalette := make([]BiomesState, len(palette))
|
biomesRawPalette := make([]BiomesState, len(palette))
|
||||||
var ok bool
|
|
||||||
for i, v := range palette {
|
for i, v := range palette {
|
||||||
biomesRawPalette[i], ok = biome.BiomesIDs[strings.TrimPrefix(v, "minecraft:")]
|
err := biomesRawPalette[i].UnmarshalText([]byte(v))
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unknown biomes: %s", v)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewBiomesPaletteContainerWithData(4*4*4, data, biomesRawPalette), nil
|
return NewBiomesPaletteContainerWithData(4*4*4, data, biomesRawPalette), nil
|
||||||
@ -180,7 +182,10 @@ func ChunkToSave(c *Chunk, dst *save.Chunk) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
biomes.Palette, biomes.Data = writeBiomesPalette(v.Biomes)
|
biomes.Palette, biomes.Data, err = writeBiomesPalette(v.Biomes)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
s.SkyLight = v.SkyLight
|
s.SkyLight = v.SkyLight
|
||||||
s.BlockLight = v.BlockLight
|
s.BlockLight = v.BlockLight
|
||||||
}
|
}
|
||||||
@ -198,6 +203,7 @@ func ChunkToSave(c *Chunk, dst *save.Chunk) (err error) {
|
|||||||
func writeStatesPalette(paletteData *PaletteContainer[BlocksState]) (palette []save.BlockState, data []uint64, err error) {
|
func writeStatesPalette(paletteData *PaletteContainer[BlocksState]) (palette []save.BlockState, data []uint64, err error) {
|
||||||
rawPalette := paletteData.palette.export()
|
rawPalette := paletteData.palette.export()
|
||||||
palette = make([]save.BlockState, len(rawPalette))
|
palette = make([]save.BlockState, len(rawPalette))
|
||||||
|
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
for i, v := range rawPalette {
|
for i, v := range rawPalette {
|
||||||
b := block.StateList[v]
|
b := block.StateList[v]
|
||||||
@ -213,19 +219,27 @@ func writeStatesPalette(paletteData *PaletteContainer[BlocksState]) (palette []s
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = append(data, paletteData.data.Raw()...)
|
|
||||||
|
|
||||||
|
data = make([]uint64, len(paletteData.data.Raw()))
|
||||||
|
copy(data, paletteData.data.Raw())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeBiomesPalette(paletteData *PaletteContainer[BiomesState]) (palette []string, data []uint64) {
|
func writeBiomesPalette(paletteData *PaletteContainer[BiomesState]) (palette []save.BiomeState, data []uint64, err error) {
|
||||||
rawPalette := paletteData.palette.export()
|
rawPalette := paletteData.palette.export()
|
||||||
palette = make([]string, len(rawPalette))
|
palette = make([]save.BiomeState, len(rawPalette))
|
||||||
for i, v := range rawPalette {
|
|
||||||
palette[i] = biome.BiomesNames[v]
|
|
||||||
}
|
|
||||||
data = append(data, paletteData.data.Raw()...)
|
|
||||||
|
|
||||||
|
var biomeID []byte
|
||||||
|
for i, v := range rawPalette {
|
||||||
|
biomeID, err = v.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
palette[i] = save.BiomeState(biomeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = make([]uint64, len(paletteData.data.Raw()))
|
||||||
|
copy(data, paletteData.data.Raw())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// RawMessage stores the raw binary data of NBT.
|
// RawMessage stores the raw binary data of NBT.
|
||||||
// This is usable if you want to store an unknown NBT data and parse it later.
|
// This is usable if you want to store an unknown NBT data and use it later.
|
||||||
// Notice that this struct doesn't store the tag name. To convert RawMessage to valid NBT binary value:
|
//
|
||||||
|
// Notice that this struct doesn't store the root tag name.
|
||||||
|
//
|
||||||
|
// To convert RawMessage to valid NBT binary value:
|
||||||
// Encoder.Encode(RawMessage, Name) = []byte{ Type (1 byte) | n (2 byte) | Name (n byte) | Data}.
|
// Encoder.Encode(RawMessage, Name) = []byte{ Type (1 byte) | n (2 byte) | Name (n byte) | Data}.
|
||||||
type RawMessage struct {
|
type RawMessage struct {
|
||||||
Type byte
|
Type byte
|
||||||
|
@ -34,23 +34,24 @@ type Chunk struct {
|
|||||||
|
|
||||||
type Section struct {
|
type Section struct {
|
||||||
Y int8
|
Y int8
|
||||||
BlockStates struct {
|
BlockStates PaletteContainer[BlockState] `nbt:"block_states"`
|
||||||
Palette []BlockState `nbt:"palette"`
|
Biomes PaletteContainer[BiomeState] `nbt:"biomes"`
|
||||||
Data []uint64 `nbt:"data"`
|
|
||||||
} `nbt:"block_states"`
|
|
||||||
Biomes struct {
|
|
||||||
Palette []string `nbt:"palette"`
|
|
||||||
Data []uint64 `nbt:"data"`
|
|
||||||
} `nbt:"biomes"`
|
|
||||||
SkyLight []byte
|
SkyLight []byte
|
||||||
BlockLight []byte
|
BlockLight []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PaletteContainer[T any] struct {
|
||||||
|
Palette []T `nbt:"palette"`
|
||||||
|
Data []uint64 `nbt:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
type BlockState struct {
|
type BlockState struct {
|
||||||
Name string
|
Name string
|
||||||
Properties nbt.RawMessage
|
Properties nbt.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BiomeState string
|
||||||
|
|
||||||
// Load read column data from []byte
|
// Load read column data from []byte
|
||||||
func (c *Chunk) Load(data []byte) (err error) {
|
func (c *Chunk) Load(data []byte) (err error) {
|
||||||
var r io.Reader = bytes.NewReader(data[1:])
|
var r io.Reader = bytes.NewReader(data[1:])
|
||||||
@ -87,6 +88,8 @@ func (c *Chunk) Data(compressingType byte) ([]byte, error) {
|
|||||||
w = gzip.NewWriter(&buff)
|
w = gzip.NewWriter(&buff)
|
||||||
case 2:
|
case 2:
|
||||||
w = zlib.NewWriter(&buff)
|
w = zlib.NewWriter(&buff)
|
||||||
|
case 3:
|
||||||
|
w = &buff
|
||||||
}
|
}
|
||||||
err := nbt.NewEncoder(w).Encode(c, "")
|
err := nbt.NewEncoder(w).Encode(c, "")
|
||||||
return buff.Bytes(), err
|
return buff.Bytes(), err
|
||||||
|
Reference in New Issue
Block a user