change API of Section from (x, y, z int) to (offset int)

This commit is contained in:
Tnze
2020-05-21 17:28:42 +08:00
parent 2db43755f1
commit 2ae88b10f4
3 changed files with 27 additions and 28 deletions

View File

@ -103,11 +103,8 @@ type directSection struct {
data []uint64 data []uint64
} }
func (d *directSection) GetBlock(x, y, z int) BlockStatus { func (d *directSection) GetBlock(offset int) BlockStatus {
// According to wiki.vg: Data Array is given for each block with increasing x coordinates, offset *= d.bpb
// within rows of increasing z coordinates, within layers of increasing y coordinates.
// So offset equals to ( x*16^0 + z*16^1 + y*16^2 )*(bits per block).
offset := (x + z*16 + y*16*16) * d.bpb
padding := offset % 64 padding := offset % 64
block := uint32(d.data[offset/64] >> padding) block := uint32(d.data[offset/64] >> padding)
if padding > 64-d.bpb { if padding > 64-d.bpb {
@ -117,8 +114,8 @@ func (d *directSection) GetBlock(x, y, z int) BlockStatus {
return BlockStatus(block & (1<<d.bpb - 1)) // mask return BlockStatus(block & (1<<d.bpb - 1)) // mask
} }
func (d *directSection) SetBlock(x, y, z int, s BlockStatus) { func (d *directSection) SetBlock(offset int, s BlockStatus) {
offset := (x + z*16 + y*16*16) * d.bpb offset *= d.bpb
padding := offset % 64 padding := offset % 64
mask := uint64(math.MaxUint64<<(padding+d.bpb) | (1<<padding - 1)) mask := uint64(math.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
@ -137,12 +134,8 @@ func (d *directSection) clone(bpb int) *directSection {
bpb: bpb, bpb: bpb,
data: make([]uint64, 16*16*16*bpb/64), data: make([]uint64, 16*16*16*bpb/64),
} }
for x := 0; x < 16; x++ { for offset := 0; offset < 16*16*16; offset++ {
for y := 0; y < 16; y++ { newSection.SetBlock(offset, d.GetBlock(offset))
for z := 0; z < 16; z++ {
newSection.SetBlock(x, y, z, d.GetBlock(x, y, z))
}
}
} }
return newSection return newSection
} }
@ -153,14 +146,14 @@ type paletteSection struct {
directSection directSection
} }
func (p *paletteSection) GetBlock(x, y, z int) BlockStatus { func (p *paletteSection) GetBlock(offset int) BlockStatus {
v := p.directSection.GetBlock(x, y, z) v := p.directSection.GetBlock(offset)
return p.palette[v] return p.palette[v]
} }
func (p *paletteSection) SetBlock(x, y, z int, s BlockStatus) { func (p *paletteSection) SetBlock(offset int, s BlockStatus) {
if i, ok := p.palettesIndex[s]; ok { if i, ok := p.palettesIndex[s]; ok {
p.directSection.SetBlock(x, y, z, BlockStatus(i)) p.directSection.SetBlock(offset, BlockStatus(i))
return return
} }
i := len(p.palette) i := len(p.palette)
@ -172,5 +165,5 @@ func (p *paletteSection) SetBlock(x, y, z int, s BlockStatus) {
// So bpb+1 must enough for new len(p.palette). // So bpb+1 must enough for new len(p.palette).
p.directSection = *p.directSection.clone(p.bpb + 1) p.directSection = *p.directSection.clone(p.bpb + 1)
} }
p.directSection.SetBlock(x, y, z, BlockStatus(i)) p.directSection.SetBlock(offset, BlockStatus(i))
} }

View File

@ -23,11 +23,11 @@ func TestDirectSection_clone(t *testing.T) {
s := newDirectSection(9) s := newDirectSection(9)
dataset := randData(9) dataset := randData(9)
for i := 0; i < 16*16*16; i++ { for i := 0; i < 16*16*16; i++ {
s.SetBlock(i%16, i/16%16, i/16/16, dataset[i]) s.SetBlock(i, dataset[i])
} }
s = s.(*directSection).clone(data.BitsPerBlock) s = s.(*directSection).clone(data.BitsPerBlock)
for i := 0; i < 16*16*16; i++ { for i := 0; i < 16*16*16; i++ {
if s := s.GetBlock(i%16, i/16%16, i/16/16); dataset[i] != s { if s := s.GetBlock(i); dataset[i] != s {
t.Fatalf("direct section error: want: %v, get %v", dataset[i], s) t.Fatalf("direct section error: want: %v, get %v", dataset[i], s)
} }
} }
@ -48,13 +48,10 @@ func testSection(s Section, bpb int) func(t *testing.T) {
return func(t *testing.T) { return func(t *testing.T) {
for _, dataset := range [][16 * 16 * 16]BlockStatus{secData(bpb), randData(bpb)} { for _, dataset := range [][16 * 16 * 16]BlockStatus{secData(bpb), randData(bpb)} {
for i := 0; i < 16*16*16; i++ { for i := 0; i < 16*16*16; i++ {
s.SetBlock(i%16, i/16%16, i/16/16, dataset[i]) s.SetBlock(i, dataset[i])
} }
for i := 0; i < 16*16*16; i++ { for i := 0; i < 16*16*16; i++ {
if v := s.GetBlock(i%16, i/16%16, i/16/16); dataset[i] != v { if v := s.GetBlock(i); 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) t.Fatalf("direct section error: want: %v, get %v", dataset[i], v)
} }
} }

View File

@ -17,8 +17,17 @@ type Chunk struct {
// Section store a 16*16*16 cube blocks // Section store a 16*16*16 cube blocks
type Section interface { type Section interface {
GetBlock(x, y, z int) BlockStatus // GetBlock return block status, offset can be calculate by SectionOffset.
SetBlock(x, y, z int, s BlockStatus) GetBlock(offset int) BlockStatus
// SetBlock is the reverse operation of GetBlock.
SetBlock(offset int, s BlockStatus)
}
func SectionOffset(x, y, z int) (offset int) {
// According to wiki.vg: Data Array is given for each block with increasing x coordinates,
// within rows of increasing z coordinates, within layers of increasing y coordinates.
// So offset equals to ( x*16^0 + z*16^1 + y*16^2 )*(bits per block).
return x + z*16 + y*16*16
} }
type BlockStatus uint32 type BlockStatus uint32
@ -52,7 +61,7 @@ func (w *World) GetBlockStatus(x, y, z int) BlockStatus {
if c != nil { if c != nil {
// (n&(16-1)) == (n<0 ? n%16+16 : n%16) // (n&(16-1)) == (n<0 ? n%16+16 : n%16)
if sec := c.Sections[y>>4]; sec != nil { if sec := c.Sections[y>>4]; sec != nil {
return sec.GetBlock(x&15, y&15, z&15) return sec.GetBlock(SectionOffset(x&15, y&15, z&15))
} }
} }
return 0 return 0