up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled

This commit is contained in:
2026-07-09 08:33:57 +08:00
commit 26ed99fda6
845 changed files with 75419 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
package chunk
import (
"bytes"
"sync"
)
const (
// SubChunkVersion is the current version of the written sub chunks, specifying the format they are
// written on disk and over network.
SubChunkVersion = 9
// CurrentBlockVersion is the current version of blocks (states) of the game. This version is composed
// of 4 bytes indicating a version, interpreted as a big endian int. The current version represents
// 1.16.0.14 {1, 16, 0, 14}.
CurrentBlockVersion int32 = 18040335
)
var (
// pool is used to pool byte buffers used for encoding chunks.
pool = sync.Pool{
New: func() any {
return bytes.NewBuffer(make([]byte, 0, 1024))
},
}
)
type (
// SerialisedData holds the serialised data of a chunk. It consists of the chunk's block data itself, a height
// map, the biomes and entities and block entities.
SerialisedData struct {
// sub holds the data of the serialised sub chunks in a chunk. Sub chunks that are empty or that otherwise
// don't exist are represented as an empty slice (or technically, nil).
SubChunks [][]byte
// Biomes is the biome data of the chunk, which is composed of a biome storage for each sub-chunk.
Biomes []byte
}
// blockEntry represents a block as found in a disk save of a world.
blockEntry struct {
Name string `nbt:"name"`
State map[string]any `nbt:"states"`
Version int32 `nbt:"version"`
}
)
// Encode encodes Chunk to an intermediate representation SerialisedData. An Encoding may be passed to encode either for
// network or disk purposed, the most notable difference being that the network encoding generally uses varints and no
// NBT.
func Encode(c *Chunk, e Encoding) SerialisedData {
d := SerialisedData{SubChunks: make([][]byte, len(c.sub))}
for i := range c.sub {
d.SubChunks[i] = EncodeSubChunk(c, e, i)
}
d.Biomes = EncodeBiomes(c, e)
return d
}
// EncodeSubChunk encodes a sub-chunk from a chunk into bytes. An Encoding may be passed to encode either for network or
// disk purposed, the most notable difference being that the network encoding generally uses varints and no NBT.
func EncodeSubChunk(c *Chunk, e Encoding, ind int) []byte {
buf := pool.Get().(*bytes.Buffer)
defer func() {
buf.Reset()
pool.Put(buf)
}()
s := c.sub[ind]
_, _ = buf.Write([]byte{SubChunkVersion, byte(len(s.storages)), uint8(ind + (c.r[0] >> 4))})
for _, storage := range s.storages {
encodePalettedStorage(buf, storage, nil, e, BlockPaletteEncoding{Blocks: c.br})
}
sub := make([]byte, buf.Len())
_, _ = buf.Read(sub)
return sub
}
// EncodeBiomes encodes the biomes of a chunk into bytes. An Encoding may be passed to encode either for network or
// disk purposed, the most notable difference being that the network encoding generally uses varints and no NBT.
func EncodeBiomes(c *Chunk, e Encoding) []byte {
buf := pool.Get().(*bytes.Buffer)
defer func() {
buf.Reset()
pool.Put(buf)
}()
var previous *PalettedStorage
for _, b := range c.biomes {
encodePalettedStorage(buf, b, previous, e, BiomePaletteEncoding)
previous = b
}
biomes := make([]byte, buf.Len())
_, _ = buf.Read(biomes)
return biomes
}
// encodePalettedStorage encodes a PalettedStorage into a bytes.Buffer. The Encoding passed is used to write the Palette
// of the PalettedStorage.
func encodePalettedStorage(buf *bytes.Buffer, storage, previous *PalettedStorage, e Encoding, pe paletteEncoding) {
if storage.Equal(previous) {
_, _ = buf.Write([]byte{0x7f<<1 | e.network()})
return
}
b := make([]byte, len(storage.indices)*4+1)
b[0] = byte(storage.bitsPerIndex<<1) | e.network()
for i, v := range storage.indices {
// Explicitly don't use the binary package to greatly improve performance of writing the uint32s.
b[i*4+1], b[i*4+2], b[i*4+3], b[i*4+4] = byte(v), byte(v>>8), byte(v>>16), byte(v>>24)
}
_, _ = buf.Write(b)
e.encodePalette(buf, storage.palette, pe)
}