bedrocktool/subcommands/world/chunk.go

118 lines
2.9 KiB
Go

package world
import (
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sirupsen/logrus"
)
func (w *WorldState) processChangeDimension(pk *packet.ChangeDimension) {
if len(w.chunks) > 0 {
w.SaveAndReset()
} else {
logrus.Info(locale.Loc("not_saving_empty", nil))
w.Reset()
}
dimensionID := pk.Dimension
if w.ispre118 {
dimensionID += 10
}
w.Dim = dimensionIDMap[uint8(dimensionID)]
}
func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) {
_, exists := w.chunks[pk.Position]
if exists {
return
}
// ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS
if len(pk.RawPayload) == 0 {
logrus.Info(locale.Loc("empty_chunk", nil))
return
}
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, int(pk.SubChunkCount), w.Dim.Range(), w.ispre118, w.bp != nil)
if err != nil {
logrus.Error(err)
return
}
if blockNBTs != nil {
w.blockNBT[protocol.SubChunkPos{
pk.Position.X(), 0, pk.Position.Z(),
}] = blockNBTs
}
w.chunks[pk.Position] = ch
if pk.SubChunkRequestMode == protocol.SubChunkRequestModeLegacy {
w.ui.SetChunk(pk.Position, ch)
} else {
w.ui.SetChunk(pk.Position, nil)
// request all the subchunks
max := w.Dim.Range().Height() / 16
if pk.SubChunkRequestMode == protocol.SubChunkRequestModeLimited {
max = int(pk.HighestSubChunk)
}
w.proxy.Server.WritePacket(&packet.SubChunkRequest{
Dimension: int32(w.Dim.EncodeDimension()),
Position: protocol.SubChunkPos{
pk.Position.X(), 0, pk.Position.Z(),
},
Offsets: offsetTable[:max],
})
}
}
func (w *WorldState) processSubChunk(pk *packet.SubChunk) {
posToRedraw := make(map[protocol.ChunkPos]bool)
for _, sub := range pk.SubChunkEntries {
var (
absX = pk.Position[0] + int32(sub.Offset[0])
absY = pk.Position[1] + int32(sub.Offset[1])
absZ = pk.Position[2] + int32(sub.Offset[2])
subPos = protocol.SubChunkPos{absX, absY, absZ}
pos = protocol.ChunkPos{absX, absZ}
)
ch, ok := w.chunks[pos]
if !ok {
logrus.Error(locale.Loc("subchunk_before_chunk", nil))
continue
}
blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub)
if err != nil {
logrus.Error(err)
}
if blockNBT != nil {
w.blockNBT[subPos] = blockNBT
}
posToRedraw[pos] = true
}
// redraw the chunks
for pos := range posToRedraw {
w.ui.SetChunk(pos, w.chunks[pos])
}
w.ui.SchedRedraw()
}
func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.ChangeDimension:
w.processChangeDimension(pk)
case *packet.LevelChunk:
w.processLevelChunk(pk)
w.proxy.SendPopup(locale.Locm("popup_chunk_count", locale.Strmap{"Count": len(w.chunks), "Name": w.WorldName}, len(w.chunks)))
case *packet.SubChunk:
w.processSubChunk(pk)
}
return pk
}