convert between save.Chunk and level.Chunk
This commit is contained in:
@ -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,
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ type GamePlay interface {
|
||||
|
||||
type Game struct {
|
||||
eid int32
|
||||
Dim Dimension
|
||||
Dim Level
|
||||
*PlayerList
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user