bedrocktool/handlers/worlds/chunk.go

169 lines
4.8 KiB
Go
Raw Normal View History

2023-04-04 00:44:13 +00:00
package worlds
import (
"github.com/bedrock-tool/bedrocktool/locale"
2023-04-30 17:35:18 +00:00
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/chunk"
2023-04-01 22:22:50 +00:00
"github.com/repeale/fp-go"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sirupsen/logrus"
)
2023-04-04 00:42:17 +00:00
func (w *worldsHandler) processChangeDimension(pk *packet.ChangeDimension) {
2023-04-12 12:10:45 +00:00
w.SaveAndReset()
2023-01-29 21:20:13 +00:00
dimensionID := pk.Dimension
2023-04-04 00:42:17 +00:00
if w.serverState.ispre118 && dimensionID == 0 {
2023-01-29 21:20:13 +00:00
dimensionID += 10
}
2023-04-10 17:55:08 +00:00
w.worldState.dimension, _ = world.DimensionByID(int(dimensionID))
}
2023-04-04 00:42:17 +00:00
func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk) {
2023-01-29 22:07:42 +00:00
// ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS
if len(pk.RawPayload) == 0 {
logrus.Info(locale.Loc("empty_chunk", nil))
return
}
2023-03-25 21:19:14 +00:00
var subChunkCount int
switch pk.SubChunkCount {
case protocol.SubChunkRequestModeLimited:
fallthrough
case protocol.SubChunkRequestModeLimitless:
subChunkCount = 0
default:
subChunkCount = int(pk.SubChunkCount)
}
2023-04-04 00:42:17 +00:00
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.worldState.dimension.Range(), w.serverState.ispre118, w.bp.HasBlocks())
if err != nil {
logrus.Error(err)
return
}
for _, blockNBT := range blockNBTs {
2023-04-30 17:35:18 +00:00
x := int(blockNBT["x"].(int32))
y := int(blockNBT["y"].(int32))
z := int(blockNBT["z"].(int32))
w.worldState.blockNBTs[cube.Pos{x, y, z}] = blockNBT
}
2023-04-29 15:22:24 +00:00
w.worldState.chunks[(world.ChunkPos)(pk.Position)] = ch
2023-04-04 00:42:17 +00:00
max := w.worldState.dimension.Range().Height() / 16
2023-03-23 19:39:47 +00:00
switch pk.SubChunkCount {
case protocol.SubChunkRequestModeLimited:
max = int(pk.HighestSubChunk)
fallthrough
case protocol.SubChunkRequestModeLimitless:
2023-03-25 21:19:14 +00:00
var offsetTable []protocol.SubChunkOffset
2023-04-04 00:42:17 +00:00
r := w.worldState.dimension.Range()
2023-03-25 21:19:14 +00:00
for y := int8(r.Min() / 16); y < int8(r.Max()); y++ {
offsetTable = append(offsetTable, protocol.SubChunkOffset{0, y, 0})
}
2023-04-04 00:42:17 +00:00
dimId, _ := world.DimensionID(w.worldState.dimension)
w.proxy.Server.WritePacket(&packet.SubChunkRequest{
2023-03-30 11:48:03 +00:00
Dimension: int32(dimId),
Position: protocol.SubChunkPos{
pk.Position.X(), 0, pk.Position.Z(),
},
2023-01-29 21:20:13 +00:00
Offsets: offsetTable[:max],
})
2023-03-23 19:39:47 +00:00
default:
// legacy
2023-04-01 22:22:50 +00:00
empty := fp.Every(func(sub *chunk.SubChunk) bool {
return sub.Empty()
})(ch.Sub())
2023-03-23 19:39:47 +00:00
if !empty {
2023-04-29 15:22:24 +00:00
w.mapUI.SetChunk((world.ChunkPos)(pk.Position), ch, true)
2023-03-23 19:39:47 +00:00
}
}
}
2023-04-04 00:42:17 +00:00
func (w *worldsHandler) processSubChunk(pk *packet.SubChunk) {
2023-04-29 15:22:24 +00:00
posToRedraw := make(map[world.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])
2023-04-29 15:22:24 +00:00
pos = world.ChunkPos{absX, absZ}
)
2023-03-30 11:48:03 +00:00
ch, ok := w.worldState.chunks[pos]
2023-01-29 21:20:13 +00:00
if !ok {
logrus.Error(locale.Loc("subchunk_before_chunk", nil))
continue
}
blockNBTs, err := ch.ApplySubChunkEntry(uint8(absY), &sub)
if err != nil {
logrus.Error(err)
}
for _, blockNBT := range blockNBTs {
2023-04-30 17:35:18 +00:00
x := int(blockNBT["x"].(int32))
y := int(blockNBT["y"].(int32))
z := int(blockNBT["z"].(int32))
w.worldState.blockNBTs[cube.Pos{x, y, z}] = blockNBT
}
2023-01-29 21:20:13 +00:00
posToRedraw[pos] = true
}
// redraw the chunks
2023-01-29 21:20:13 +00:00
for pos := range posToRedraw {
2023-03-30 11:48:03 +00:00
w.mapUI.SetChunk(pos, w.worldState.chunks[pos], true)
}
w.mapUI.SchedRedraw()
}
2023-03-25 21:19:14 +00:00
func blockPosInChunk(pos protocol.BlockPos) (uint8, int16, uint8) {
return uint8(pos.X() & 0x0f), int16(pos.Y() & 0x0f), uint8(pos.Z() & 0x0f)
}
2023-04-04 00:42:17 +00:00
func (w *worldsHandler) ProcessChunkPackets(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.ChangeDimension:
w.processChangeDimension(pk)
case *packet.LevelChunk:
w.processLevelChunk(pk)
2023-04-04 00:42:17 +00:00
w.proxy.SendPopup(locale.Locm("popup_chunk_count", locale.Strmap{
"Count": len(w.worldState.chunks),
"Name": w.worldState.Name,
}, len(w.worldState.chunks)))
case *packet.SubChunk:
w.processSubChunk(pk)
2023-03-25 21:19:14 +00:00
case *packet.BlockActorData:
2023-04-30 17:35:18 +00:00
p := pk.Position
w.worldState.blockNBTs[cube.Pos{int(p.X()), int(p.Y()), int(p.Z())}] = pk.NBTData
2023-03-25 21:19:14 +00:00
case *packet.UpdateBlock:
2023-04-04 00:44:13 +00:00
if w.settings.BlockUpdates {
2023-04-29 15:22:24 +00:00
cp := world.ChunkPos{pk.Position.X() >> 4, pk.Position.Z() >> 4}
2023-03-30 11:48:03 +00:00
c, ok := w.worldState.chunks[cp]
2023-03-27 12:11:40 +00:00
if ok {
x, y, z := blockPosInChunk(pk.Position)
c.SetBlock(x, y, z, uint8(pk.Layer), pk.NewBlockRuntimeID)
w.mapUI.SetChunk(cp, c, true)
2023-03-27 12:11:40 +00:00
}
2023-03-25 21:19:14 +00:00
}
case *packet.UpdateSubChunkBlocks:
2023-04-04 00:44:13 +00:00
if w.settings.BlockUpdates {
2023-04-29 15:22:24 +00:00
cp := world.ChunkPos{pk.Position.X(), pk.Position.Z()}
2023-03-30 11:48:03 +00:00
c, ok := w.worldState.chunks[cp]
2023-03-27 12:11:40 +00:00
if ok {
for _, bce := range pk.Blocks {
x, y, z := blockPosInChunk(bce.BlockPos)
if bce.SyncedUpdateType == packet.BlockToEntityTransition {
c.SetBlock(x, y, z, 0, world.AirRID())
} else {
c.SetBlock(x, y, z, 0, bce.BlockRuntimeID)
}
2023-03-25 21:19:14 +00:00
}
w.mapUI.SetChunk(cp, c, true)
2023-03-25 21:19:14 +00:00
}
}
}
return pk
}