Files
go-mc/bot/world/chunk.go
2019-12-14 22:30:12 +08:00

97 lines
2.3 KiB
Go

package world
import (
"bytes"
"fmt"
// "io"
"github.com/Tnze/go-mc/data"
pk "github.com/Tnze/go-mc/net/packet"
)
//DecodeChunkColumn decode the chunk data structure
func DecodeChunkColumn(mask int32, data []byte) (*Chunk, error) {
var c Chunk
r := bytes.NewReader(data)
for sectionY := 0; sectionY < 16; sectionY++ {
if (mask & (1 << uint(sectionY))) == 0 { // Is the given bit set in the mask?
continue
}
var (
BlockCount pk.Short
BitsPerBlock pk.Byte
)
if err := BlockCount.Decode(r); err != nil {
return nil, err
}
if err := BitsPerBlock.Decode(r); err != nil {
return nil, err
}
//读调色板
var palette []uint
if BitsPerBlock < 9 {
var length pk.VarInt
if err := length.Decode(r); err != nil {
return nil, fmt.Errorf("read palette (id len) fail: %v", err)
}
palette = make([]uint, length)
for id := uint(0); id < uint(length); id++ {
var stateID pk.VarInt
if err := stateID.Decode(r); err != nil {
return nil, fmt.Errorf("read palette (id) fail: %v", err)
}
palette[id] = uint(stateID)
}
}
//Section数据
var DataArrayLength pk.VarInt
if err := DataArrayLength.Decode(r); err != nil {
return nil, fmt.Errorf("read DataArrayLength fail: %v", err)
}
DataArray := make([]int64, DataArrayLength)
for i := 0; i < int(DataArrayLength); i++ {
if err := (*pk.Long)(&DataArray[i]).Decode(r); err != nil {
return nil, fmt.Errorf("read DataArray fail: %v", err)
}
}
//用数据填充区块
fillSection(&c.sections[sectionY], perBits(byte(BitsPerBlock)), DataArray, palette)
}
return &c, nil
}
func perBits(BitsPerBlock byte) uint {
switch {
case BitsPerBlock <= 4:
return 4
case BitsPerBlock < 9:
return uint(BitsPerBlock)
default:
return uint(data.BitsPerBlock) // DefaultBitsPerBlock
}
}
func fillSection(s *Section, bpb uint, DataArray []int64, palette []uint) {
mask := uint(1<<bpb - 1)
for n := 0; n < 16*16*16; n++ {
offset := uint(n * int(bpb))
data := uint(DataArray[offset/64])
data >>= offset % 64
if offset%64 > 64-bpb {
l := bpb + offset%64 - 64
data &= uint(DataArray[offset/64+1] << l)
}
data &= mask
if bpb < 9 {
s.blocks[n%16][n/(16*16)][n%(16*16)/16].id = palette[data]
} else {
s.blocks[n%16][n/(16*16)][n%(16*16)/16].id = data
}
}
}