bot can receive chunks now
This commit is contained in:
@ -18,8 +18,8 @@ type Block interface {
|
||||
//go:embed block_states.nbt
|
||||
var blockStates []byte
|
||||
|
||||
var toStateID map[Block]int
|
||||
var fromStateID []Block
|
||||
var ToStateID map[Block]int
|
||||
var StateList []Block
|
||||
|
||||
// BitsPerBlock indicates how many bits are needed to represent all possible
|
||||
// block states. This value is used to determine the size of the global palette.
|
||||
@ -41,8 +41,8 @@ func init() {
|
||||
if _, err = nbt.NewDecoder(z).Decode(&states); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
toStateID = make(map[Block]int, len(states))
|
||||
fromStateID = make([]Block, 0, len(states))
|
||||
ToStateID = make(map[Block]int, len(states))
|
||||
StateList = make([]Block, 0, len(states))
|
||||
for _, state := range states {
|
||||
block := fromID[state.Name]
|
||||
if state.Properties.Type != nbt.TagEnd {
|
||||
@ -51,29 +51,16 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if _, ok := toStateID[block]; ok {
|
||||
if _, ok := ToStateID[block]; ok {
|
||||
panic(fmt.Errorf("state %#v already exist", block))
|
||||
}
|
||||
toStateID[block] = len(fromStateID)
|
||||
fromStateID = append(fromStateID, block)
|
||||
ToStateID[block] = len(StateList)
|
||||
StateList = append(StateList, block)
|
||||
}
|
||||
BitsPerBlock = bits.Len(uint(len(fromStateID)))
|
||||
}
|
||||
|
||||
func FromStateID(stateID int) (b Block, ok bool) {
|
||||
if stateID >= 0 && stateID < len(fromStateID) {
|
||||
b = fromStateID[stateID]
|
||||
ok = true
|
||||
}
|
||||
return
|
||||
BitsPerBlock = bits.Len(uint(len(StateList)))
|
||||
}
|
||||
|
||||
func DefaultBlock(id string) (b Block, ok bool) {
|
||||
b, ok = fromID[id]
|
||||
return
|
||||
}
|
||||
|
||||
func ToStateID(b Block) (i int, ok bool) {
|
||||
i, ok = toStateID[b]
|
||||
return
|
||||
}
|
||||
|
@ -12,6 +12,6 @@ type (
|
||||
{{- range .}}
|
||||
func ({{.Name | ToGoTypeName}}) ID() string { return {{.Name | printf "%q"}} }
|
||||
{{- end}}
|
||||
var fromID = map[string]Block { {{- range .}}
|
||||
var FromID = map[string]Block { {{- range .}}
|
||||
{{.Name | printf "%#v"}}: {{.Name | ToGoTypeName}}{},{{end}}
|
||||
}
|
129
level/chunk.go
129
level/chunk.go
@ -10,19 +10,40 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/Tnze/go-mc/level/block"
|
||||
"github.com/Tnze/go-mc/nbt"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/Tnze/go-mc/save"
|
||||
)
|
||||
|
||||
type ChunkPos struct{ X, Z int }
|
||||
|
||||
func (c ChunkPos) WriteTo(w io.Writer) (n int64, err error) {
|
||||
n, err = pk.Int(c.X).WriteTo(w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n1, err := pk.Int(c.Z).WriteTo(w)
|
||||
return n + n1, err
|
||||
}
|
||||
|
||||
func (c *ChunkPos) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var x, z pk.Int
|
||||
if n, err = x.ReadFrom(r); err != nil {
|
||||
return n, err
|
||||
}
|
||||
var n1 int64
|
||||
if n1, err = z.ReadFrom(r); err != nil {
|
||||
return n + n1, err
|
||||
}
|
||||
*c = ChunkPos{int(x), int(z)}
|
||||
return n + n1, nil
|
||||
}
|
||||
|
||||
type Chunk struct {
|
||||
sync.Mutex
|
||||
Sections []Section
|
||||
HeightMaps HeightMaps
|
||||
}
|
||||
type HeightMaps struct {
|
||||
MotionBlocking *BitStorage
|
||||
WorldSurface *BitStorage
|
||||
Sections []Section
|
||||
HeightMaps HeightMaps
|
||||
BlockEntity []BlockEntity
|
||||
}
|
||||
|
||||
func EmptyChunk(secs int) *Chunk {
|
||||
@ -122,7 +143,7 @@ func ChunkFromSave(c *save.Chunk, secs int) *Chunk {
|
||||
blockCount++
|
||||
}
|
||||
var ok bool
|
||||
stateRawPalette[i], ok = block.ToStateID(b)
|
||||
stateRawPalette[i], ok = block.ToStateID[b]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("state id not found: %#v", b))
|
||||
}
|
||||
@ -176,7 +197,7 @@ func (c *Chunk) WriteTo(w io.Writer) (int64, error) {
|
||||
WorldSurface: c.HeightMaps.MotionBlocking.Raw(),
|
||||
}),
|
||||
pk.ByteArray(data),
|
||||
pk.VarInt(0), // TODO: Block Entity
|
||||
pk.Array(c.BlockEntity),
|
||||
&lightData{
|
||||
SkyLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||
BlockLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||
@ -186,10 +207,38 @@ func (c *Chunk) WriteTo(w io.Writer) (int64, error) {
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
func (c *Chunk) ReadFrom(r io.Reader) (int64, error) {
|
||||
var (
|
||||
heightmaps struct {
|
||||
MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"`
|
||||
WorldSurface []uint64 `nbt:"WORLD_SURFACE"`
|
||||
}
|
||||
data pk.ByteArray
|
||||
)
|
||||
|
||||
n, err := pk.Tuple{
|
||||
pk.NBT(&heightmaps),
|
||||
&data,
|
||||
pk.Array(&c.BlockEntity),
|
||||
&lightData{
|
||||
SkyLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||
BlockLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||
SkyLight: []pk.ByteArray{},
|
||||
BlockLight: []pk.ByteArray{},
|
||||
},
|
||||
}.ReadFrom(r)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
err = c.PutData(data)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (c *Chunk) Data() ([]byte, error) {
|
||||
var buff bytes.Buffer
|
||||
for _, section := range c.Sections {
|
||||
_, err := section.WriteTo(&buff)
|
||||
for i := range c.Sections {
|
||||
_, err := c.Sections[i].WriteTo(&buff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -197,6 +246,47 @@ func (c *Chunk) Data() ([]byte, error) {
|
||||
return buff.Bytes(), nil
|
||||
}
|
||||
|
||||
func (c *Chunk) PutData(data []byte) error {
|
||||
r := bytes.NewReader(data)
|
||||
for i := range c.Sections {
|
||||
_, err := c.Sections[i].ReadFrom(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type HeightMaps struct {
|
||||
MotionBlocking *BitStorage
|
||||
WorldSurface *BitStorage
|
||||
}
|
||||
|
||||
type BlockEntity struct {
|
||||
XZ int8
|
||||
Y int16
|
||||
Type int32
|
||||
Data nbt.RawMessage
|
||||
}
|
||||
|
||||
func (b BlockEntity) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return pk.Tuple{
|
||||
pk.Byte(b.XZ),
|
||||
pk.Short(b.Y),
|
||||
pk.VarInt(b.Type),
|
||||
pk.NBT(b.Data),
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
func (b *BlockEntity) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
return pk.Tuple{
|
||||
(*pk.Byte)(&b.XZ),
|
||||
(*pk.Short)(&b.Y),
|
||||
(*pk.VarInt)(&b.Type),
|
||||
pk.NBT(&b.Data),
|
||||
}.ReadFrom(r)
|
||||
}
|
||||
|
||||
type Section struct {
|
||||
blockCount int16
|
||||
States *PaletteContainer
|
||||
@ -207,7 +297,10 @@ func (s *Section) GetBlock(i int) int {
|
||||
return s.States.Get(i)
|
||||
}
|
||||
func (s *Section) SetBlock(i int, v int) {
|
||||
b, _ := block.FromStateID(s.States.Get(i))
|
||||
var b block.Block
|
||||
if stateID := s.States.Get(i); stateID >= 0 && stateID < len(block.StateList) {
|
||||
b = block.StateList[stateID]
|
||||
}
|
||||
if isAir(b) {
|
||||
s.blockCount--
|
||||
}
|
||||
@ -260,6 +353,20 @@ func (l *lightData) WriteTo(w io.Writer) (int64, error) {
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
func (l *lightData) ReadFrom(r io.Reader) (int64, error) {
|
||||
var TrustEdges pk.Boolean
|
||||
var RevSkyLightMask, RevBlockLightMask pk.BitSet
|
||||
return pk.Tuple{
|
||||
&TrustEdges, // Trust Edges
|
||||
&l.SkyLightMask,
|
||||
&l.BlockLightMask,
|
||||
&RevSkyLightMask,
|
||||
&RevBlockLightMask,
|
||||
pk.Array(&l.SkyLight),
|
||||
pk.Array(&l.BlockLight),
|
||||
}.ReadFrom(r)
|
||||
}
|
||||
|
||||
func isAir(b block.Block) bool {
|
||||
switch b.(type) {
|
||||
case block.Air, block.CaveAir, block.VoidAir:
|
||||
|
@ -274,6 +274,11 @@ func (l *linearPalette) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
if n, err = size.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
if int(size) > cap(l.values) {
|
||||
l.values = make([]state, size)
|
||||
} else {
|
||||
l.values = l.values[:size]
|
||||
}
|
||||
for i := 0; i < int(size); i++ {
|
||||
if nn, err := value.ReadFrom(r); err != nil {
|
||||
return n + nn, err
|
||||
|
Reference in New Issue
Block a user