Major update of chunk system for 1.16.2
This commit is contained in:
@ -2,6 +2,8 @@ package world
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/bot/world/entity"
|
||||
"github.com/Tnze/go-mc/data/block"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
// World record all of the things in the world where player at
|
||||
@ -18,16 +20,16 @@ type Chunk struct {
|
||||
// Section store a 16*16*16 cube blocks
|
||||
type Section interface {
|
||||
// GetBlock return block status, offset can be calculate by SectionOffset.
|
||||
GetBlock(offset int) BlockStatus
|
||||
GetBlock(offset uint) BlockStatus
|
||||
// SetBlock is the reverse operation of GetBlock.
|
||||
SetBlock(offset int, s BlockStatus)
|
||||
SetBlock(offset uint, s BlockStatus)
|
||||
}
|
||||
|
||||
func SectionOffset(x, y, z int) (offset int) {
|
||||
func SectionIdx(x, y, z int) uint {
|
||||
// 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
|
||||
return uint(((y & 15) << 8) | (z << 4) | x)
|
||||
}
|
||||
|
||||
type BlockStatus uint32
|
||||
@ -59,14 +61,51 @@ func (w *World) GetBlockStatus(x, y, z int) BlockStatus {
|
||||
// Use n>>4 rather then n/16. It acts wrong if n<0.
|
||||
c := w.Chunks[ChunkLoc{x >> 4, z >> 4}]
|
||||
if c != nil {
|
||||
// (n&(16-1)) == (n<0 ? n%16+16 : n%16)
|
||||
if sec := c.Sections[y>>4]; sec != nil {
|
||||
return sec.GetBlock(SectionOffset(x&15, y&15, z&15))
|
||||
return sec.GetBlock(SectionIdx(x&15, y&15, z&15))
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (w *World) UnaryBlockUpdate(pos pk.Position, bStateID BlockStatus) bool {
|
||||
c := w.Chunks[ChunkLoc{X: pos.X >> 4, Z: pos.Z >> 4}]
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
sIdx, bIdx := pos.Y>>4, SectionIdx(pos.X&15, pos.Y&15, pos.Z&15)
|
||||
|
||||
if sec := c.Sections[sIdx]; sec == nil {
|
||||
sec = newSectionWithSize(uint(block.BitsPerBlock))
|
||||
sec.SetBlock(bIdx, bStateID)
|
||||
c.Sections[sIdx] = sec
|
||||
} else {
|
||||
sec.SetBlock(bIdx, bStateID)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *World) MultiBlockUpdate(loc ChunkLoc, sectionY int, blocks []pk.VarLong) bool {
|
||||
c := w.Chunks[loc]
|
||||
if c == nil {
|
||||
return false // not loaded
|
||||
}
|
||||
|
||||
sec := c.Sections[sectionY]
|
||||
if sec == nil {
|
||||
sec = newSectionWithSize(uint(block.BitsPerBlock))
|
||||
c.Sections[sectionY] = sec
|
||||
}
|
||||
|
||||
for _, b := range blocks {
|
||||
bStateID := b >> 12
|
||||
x, z, y := (b>>8)&0xf, (b>>4)&0xf, b&0xf
|
||||
sec.SetBlock(SectionIdx(int(x&15), int(y&15), int(z&15)), BlockStatus(bStateID))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// func (b Block) String() string {
|
||||
// return blockNameByID[b.id]
|
||||
// }
|
||||
|
Reference in New Issue
Block a user