The paletteSection can auto increase its underlying directSection.
This commit is contained in:
@ -3,9 +3,9 @@ package world
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
// "io"
|
|
||||||
"github.com/Tnze/go-mc/data"
|
"github.com/Tnze/go-mc/data"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DecodeChunkColumn decode the chunk data structure.
|
// DecodeChunkColumn decode the chunk data structure.
|
||||||
@ -120,15 +120,18 @@ func (d *directSection) GetBlock(x, y, z int) BlockStatus {
|
|||||||
func (d *directSection) SetBlock(x, y, z int, s BlockStatus) {
|
func (d *directSection) SetBlock(x, y, z int, s BlockStatus) {
|
||||||
offset := (x + z*16 + y*16*16) * d.bpb
|
offset := (x + z*16 + y*16*16) * d.bpb
|
||||||
padding := offset % 64
|
padding := offset % 64
|
||||||
const maxUint64 = 1<<64 - 1
|
mask := uint64(math.MaxUint64<<(padding+d.bpb) | (1<<padding - 1))
|
||||||
mask := uint64(maxUint64<<(padding+d.bpb) | (1<<padding - 1))
|
|
||||||
d.data[offset/64] = d.data[offset/64]&mask | uint64(s)<<padding
|
d.data[offset/64] = d.data[offset/64]&mask | uint64(s)<<padding
|
||||||
if padding > 64-d.bpb {
|
if padding > 64-d.bpb {
|
||||||
l := padding - (64 - d.bpb)
|
l := padding - (64 - d.bpb)
|
||||||
d.data[offset/64+1] = d.data[offset/64+1]&(maxUint64<<l) | uint64(s)>>(64-padding)
|
d.data[offset/64+1] = d.data[offset/64+1]&(math.MaxUint64<<l) | uint64(s)>>(64-padding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *directSection) CanContain(s BlockStatus) bool {
|
||||||
|
return s <= (1<<d.bpb - 1)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *directSection) clone(bpb int) *directSection {
|
func (d *directSection) clone(bpb int) *directSection {
|
||||||
newSection := &directSection{
|
newSection := &directSection{
|
||||||
bpb: bpb,
|
bpb: bpb,
|
||||||
@ -163,5 +166,11 @@ func (p *paletteSection) SetBlock(x, y, z int, s BlockStatus) {
|
|||||||
i := len(p.palette)
|
i := len(p.palette)
|
||||||
p.palette = append(p.palette, s)
|
p.palette = append(p.palette, s)
|
||||||
p.palettesIndex[s] = i
|
p.palettesIndex[s] = i
|
||||||
|
if !p.directSection.CanContain(BlockStatus(i)) {
|
||||||
|
// Increase the underlying directSection
|
||||||
|
// Suppose that old bpb fit len(p.palette) before it appended.
|
||||||
|
// So bpb+1 must enough for new len(p.palette).
|
||||||
|
p.directSection = *p.directSection.clone(p.bpb + 1)
|
||||||
|
}
|
||||||
p.directSection.SetBlock(x, y, z, BlockStatus(i))
|
p.directSection.SetBlock(x, y, z, BlockStatus(i))
|
||||||
}
|
}
|
||||||
|
@ -14,26 +14,49 @@ func newDirectSection(bpb int) Section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDirectSection(t *testing.T) {
|
func TestDirectSection(t *testing.T) {
|
||||||
for bpb := 4; bpb < data.BitsPerBlock; bpb++ {
|
for bpb := 4; bpb <= data.BitsPerBlock; bpb++ {
|
||||||
testSection(t, newDirectSection(bpb), bpb)
|
testSection(newDirectSection(bpb), bpb)(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDirectSection_clone(t *testing.T) {
|
||||||
|
s := newDirectSection(9)
|
||||||
|
dataset := randData(9)
|
||||||
|
for i := 0; i < 16*16*16; i++ {
|
||||||
|
s.SetBlock(i%16, i/16%16, i/16/16, dataset[i])
|
||||||
|
}
|
||||||
|
s = s.(*directSection).clone(data.BitsPerBlock)
|
||||||
|
for i := 0; i < 16*16*16; i++ {
|
||||||
|
if s := s.GetBlock(i%16, i/16%16, i/16/16); dataset[i] != s {
|
||||||
|
t.Fatalf("direct section error: want: %v, get %v", dataset[i], s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPaletteSection(t *testing.T) {
|
func TestPaletteSection(t *testing.T) {
|
||||||
testSection(t, &paletteSection{
|
t.Run("Correctness", testSection(&paletteSection{
|
||||||
palettesIndex: make(map[BlockStatus]int),
|
palettesIndex: make(map[BlockStatus]int),
|
||||||
directSection: *(newDirectSection(7).(*directSection)),
|
directSection: *(newDirectSection(7).(*directSection)),
|
||||||
}, 7)
|
}, 7))
|
||||||
|
t.Run("AutomaticExpansion", testSection(&paletteSection{
|
||||||
|
palettesIndex: make(map[BlockStatus]int),
|
||||||
|
directSection: *(newDirectSection(4).(*directSection)),
|
||||||
|
}, 9))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSection(t *testing.T, s Section, bpb int) {
|
func testSection(s Section, bpb int) func(t *testing.T) {
|
||||||
for _, dataset := range [][16 * 16 * 16]BlockStatus{secData(bpb), randData(bpb)} {
|
return func(t *testing.T) {
|
||||||
for i := 0; i < 16*16*16; i++ {
|
for _, dataset := range [][16 * 16 * 16]BlockStatus{secData(bpb), randData(bpb)} {
|
||||||
s.SetBlock(i%16, i/16%16, i/16/16, dataset[i])
|
for i := 0; i < 16*16*16; i++ {
|
||||||
}
|
s.SetBlock(i%16, i/16%16, i/16/16, dataset[i])
|
||||||
for i := 0; i < 16*16*16; i++ {
|
}
|
||||||
if s := s.GetBlock(i%16, i/16%16, i/16/16); dataset[i] != s {
|
for i := 0; i < 16*16*16; i++ {
|
||||||
t.Fatalf("direct section error: want: %v, get %v", dataset[i], s)
|
if v := s.GetBlock(i%16, i/16%16, i/16/16); dataset[i] != v {
|
||||||
|
//for i := 0; i < 18; i++ {
|
||||||
|
// t.Log(s.(*paletteSection).directSection.GetBlock(i%16, i/16%16, i/16/16))
|
||||||
|
//}
|
||||||
|
t.Fatalf("direct section error: want: %v, get %v", dataset[i], v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user