convert between save.Chunk and level.Chunk

This commit is contained in:
Tnze
2021-12-20 01:50:31 +08:00
parent 8eaae6a202
commit 5bc8513039
7 changed files with 143 additions and 93 deletions

View File

@ -4,20 +4,24 @@ import (
"bytes"
"io"
"math/bits"
"strings"
"sync"
"unsafe"
"github.com/Tnze/go-mc/data/block"
"github.com/Tnze/go-mc/data/packetid"
"github.com/Tnze/go-mc/level"
pk "github.com/Tnze/go-mc/net/packet"
"github.com/Tnze/go-mc/save"
)
type Dimension interface {
Info() DimInfo
type Level interface {
Info() LevelInfo
PlayerJoin(p *Player)
PlayerQuit(p *Player)
}
type DimInfo struct {
type LevelInfo struct {
Name string
HashedSeed uint64
}
@ -29,6 +33,77 @@ type Chunk struct {
HeightMaps *level.BitStorage
}
func EmptyChunk(secs int) *Chunk {
sections := make([]Section, secs)
for i := range sections {
sections[i] = Section{
blockCount: 0,
States: level.NewStatesPaletteContainer(16*16*16, 0),
Biomes: level.NewBiomesPaletteContainer(4*4*4, 0),
}
}
return &Chunk{
Sections: sections,
HeightMaps: level.NewBitStorage(bits.Len(uint(secs)*16), 16*16, nil),
}
}
func ChunkFromSave(c *save.Chunk) *Chunk {
sections := make([]Section, len(c.Sections))
for i := range sections {
data := *(*[]uint64)((unsafe.Pointer)(&c.Sections[i].BlockStates.Data))
palette := c.Sections[i].BlockStates.Palette
rawPalette := make([]int, len(palette))
for i, v := range palette {
// TODO: Consider the properties of block, not only index the block name
rawPalette[i] = int(stateIDs[strings.TrimPrefix(v.Name, "minecraft:")])
}
sections[i].States = level.NewStatesPaletteContainerWithData(16*16*16, data, rawPalette)
}
return &Chunk{
Sections: sections,
HeightMaps: nil,
}
}
// TODO: This map should be moved to data/block.
var stateIDs map[string]uint32
func init() {
for i, v := range block.StateID {
name := block.ByID[v].Name
if _, ok := stateIDs[name]; !ok {
stateIDs[name] = i
}
}
}
func (c *Chunk) WriteTo(w io.Writer) (int64, error) {
data, err := c.Data()
if err != nil {
return 0, err
}
return pk.Tuple{
// Heightmaps
pk.NBT(struct {
MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"`
}{c.HeightMaps.Raw()}),
pk.ByteArray(data),
pk.VarInt(0), // TODO: Block Entity
}.WriteTo(w)
}
func (c *Chunk) Data() ([]byte, error) {
var buff bytes.Buffer
for _, section := range c.Sections {
_, err := section.WriteTo(&buff)
if err != nil {
return nil, err
}
}
return buff.Bytes(), nil
}
type Section struct {
blockCount int16
States *level.PaletteContainer
@ -65,47 +140,6 @@ func (s *Section) ReadFrom(r io.Reader) (int64, error) {
}.ReadFrom(r)
}
func EmptyChunk(secs int) *Chunk {
sections := make([]Section, secs)
for i := range sections {
sections[i] = Section{
blockCount: 0,
States: level.NewStatesPaletteContainer(16*16*16, 0),
Biomes: level.NewBiomesPaletteContainer(4*4*4, 0),
}
}
return &Chunk{
Sections: sections,
HeightMaps: level.NewBitStorage(bits.Len(uint(secs)*16), 16*16, nil),
}
}
func (c *Chunk) WriteTo(w io.Writer) (int64, error) {
data, err := c.Data()
if err != nil {
return 0, err
}
return pk.Tuple{
// Heightmaps
pk.NBT(struct {
MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"`
}{c.HeightMaps.Raw()}),
pk.ByteArray(data),
pk.VarInt(0), // TODO: Block Entity
}.WriteTo(w)
}
func (c *Chunk) Data() ([]byte, error) {
var buff bytes.Buffer
for _, section := range c.Sections {
_, err := section.WriteTo(&buff)
if err != nil {
return nil, err
}
}
return buff.Bytes(), nil
}
type lightData struct {
SkyLightMask pk.BitSet
BlockLightMask pk.BitSet
@ -149,8 +183,8 @@ func (s *SimpleDim) LoadChunk(pos ChunkPos, c *Chunk) {
s.Columns[pos] = c
}
func (s *SimpleDim) Info() DimInfo {
return DimInfo{
func (s *SimpleDim) Info() LevelInfo {
return LevelInfo{
Name: "minecraft:overworld",
HashedSeed: 1234567,
}

View File

@ -23,7 +23,7 @@ type GamePlay interface {
type Game struct {
eid int32
Dim Dimension
Dim Level
*PlayerList
}