From 10c3b8771eae2432025495e9ad0ab33d5b5c54f4 Mon Sep 17 00:00:00 2001 From: Tnze Date: Sun, 19 Dec 2021 09:53:45 +0800 Subject: [PATCH] SingleValuePalette --- save/bitstorage.go | 4 +- save/bitstorage_test.go | 2 +- save/palette.go | 98 ++++++++++++++++++++++++++++++++++------- server/dimension.go | 2 +- 4 files changed, 87 insertions(+), 19 deletions(-) diff --git a/save/bitstorage.go b/save/bitstorage.go index 4622d95..4d7a54b 100644 --- a/save/bitstorage.go +++ b/save/bitstorage.go @@ -123,8 +123,8 @@ func (b *BitStorage) Len() int { return b.length } -// Longs return the underling array of uint64 for encoding/decoding. -func (b *BitStorage) Longs() []uint64 { +// Raw return the underling array of uint64 for encoding/decoding. +func (b *BitStorage) Raw() []uint64 { if b == nil { return []uint64{} } diff --git a/save/bitstorage_test.go b/save/bitstorage_test.go index ab1bd93..8896da5 100644 --- a/save/bitstorage_test.go +++ b/save/bitstorage_test.go @@ -42,5 +42,5 @@ func ExampleNewBitStorage_heightmaps() { type HeightMaps struct { MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"` } - _ = pk.NBT(HeightMaps{bs.Longs()}) + _ = pk.NBT(HeightMaps{bs.Raw()}) } diff --git a/save/palette.go b/save/palette.go index 6bf90f4..52adb0e 100644 --- a/save/palette.go +++ b/save/palette.go @@ -2,6 +2,7 @@ package save import ( "io" + "strconv" pk "github.com/Tnze/go-mc/net/packet" ) @@ -10,7 +11,8 @@ type BlockState interface { } type PaletteContainer struct { - maps blockMaps + maps blockMaps + config func(p *PaletteContainer, bits byte) palette BitStorage } @@ -21,20 +23,7 @@ func (p *PaletteContainer) ReadFrom(r io.Reader) (n int64, err error) { if err != nil { return } - switch bits { - case 0: - // TODO: SingleValuePalette - case 1, 2, 3, 4: - p.palette = &linearPalette{ - onResize: nil, - maps: p.maps, - bits: 4, - } - case 5, 6, 7, 8: - // TODO: HashMapPalette - default: - // TODO: GlobalPalette - } + p.config(p, byte(bits)) nn, err := p.palette.ReadFrom(r) n += nn @@ -50,6 +39,46 @@ func (p *PaletteContainer) ReadFrom(r io.Reader) (n int64, err error) { return n, nil } +func createStatesPalette(p *PaletteContainer, bits byte) { + switch bits { + case 0: + p.palette = &singleValuePalette{ + onResize: nil, + maps: p.maps, + v: nil, + } + case 1, 2, 3, 4: + p.palette = &linearPalette{ + onResize: nil, + maps: p.maps, + bits: 4, + } + case 5, 6, 7, 8: + // TODO: HashMapPalette + default: + // TODO: GlobalPalette + } +} + +func createBiomesPalette(p *PaletteContainer, bits byte) { + switch bits { + case 0: + p.palette = &singleValuePalette{ + onResize: nil, + maps: p.maps, + v: nil, + } + case 1, 2, 3: + p.palette = &linearPalette{ + onResize: nil, + maps: p.maps, + bits: 4, + } + default: + // TODO: GlobalPalette + } +} + func (p *PaletteContainer) WriteTo(w io.Writer) (n int64, err error) { return pk.Tuple{ pk.UnsignedByte(p.bits), @@ -70,6 +99,45 @@ type blockMaps interface { getValue(id int) (state BlockState) } +type singleValuePalette struct { + onResize func(n int, v BlockState) int + maps blockMaps + v BlockState +} + +func (s *singleValuePalette) id(v BlockState) int { + if s.v == nil { + s.v = v + return 0 + } + if s.v == v { + return 0 + } + // We have 2 values now. At least 1 bit is required. + return s.onResize(1, v) +} + +func (s *singleValuePalette) value(i int) BlockState { + if s.v != nil && i == 0 { + return s.v + } + panic("singleValuePalette: " + strconv.Itoa(i) + " out of bounds") +} + +func (s *singleValuePalette) ReadFrom(r io.Reader) (n int64, err error) { + var i pk.VarInt + n, err = i.ReadFrom(r) + if err != nil { + return + } + s.v = s.maps.getValue(int(i)) + return +} + +func (s *singleValuePalette) WriteTo(w io.Writer) (n int64, err error) { + return pk.VarInt(s.maps.getID(s.v)).WriteTo(w) +} + type linearPalette struct { onResize func(n int, v BlockState) int maps blockMaps diff --git a/server/dimension.go b/server/dimension.go index 203931e..c0ff19f 100644 --- a/server/dimension.go +++ b/server/dimension.go @@ -37,7 +37,7 @@ func (c *chunkData) WriteTo(w io.Writer) (int64, error) { // Heightmaps pk.NBT(struct { MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"` - }{c.HeightMaps.Longs()}), + }{c.HeightMaps.Raw()}), pk.ByteArray(c.Data()), // TODO: Chunk Data pk.VarInt(0), // TODO: Block Entity }.WriteTo(w)