store blocknbt per block not in subchunks

This commit is contained in:
olebeck 2023-04-21 03:20:57 +02:00
parent 5a550002d3
commit ba7435c822
5 changed files with 48 additions and 59 deletions

View File

@ -11,7 +11,7 @@ import (
func (s *secondaryUser) ResetWorld() { func (s *secondaryUser) ResetWorld() {
s.chunks = make(map[world.ChunkPos]*chunk.Chunk) s.chunks = make(map[world.ChunkPos]*chunk.Chunk)
s.blockNBT = make(map[protocol.SubChunkPos][]map[string]any) s.blockNBTs = make(map[protocol.BlockPos][]map[string]any)
} }
func (s *secondaryUser) processChangeDimension(pk *packet.ChangeDimension) { func (s *secondaryUser) processChangeDimension(pk *packet.ChangeDimension) {
@ -26,7 +26,6 @@ func (s *secondaryUser) processChangeDimension(pk *packet.ChangeDimension) {
func (s *secondaryUser) processLevelChunk(pk *packet.LevelChunk) { func (s *secondaryUser) processLevelChunk(pk *packet.LevelChunk) {
// ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS // ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS
if len(pk.RawPayload) == 0 { if len(pk.RawPayload) == 0 {
logrus.Info(locale.Loc("empty_chunk", nil))
return return
} }
@ -45,11 +44,14 @@ func (s *secondaryUser) processLevelChunk(pk *packet.LevelChunk) {
logrus.Error(err) logrus.Error(err)
return return
} }
if blockNBTs != nil {
s.blockNBT[protocol.SubChunkPos{ for _, blockNBT := range blockNBTs {
pk.Position.X(), 0, pk.Position.Z(), x := blockNBT["x"].(int32)
}] = blockNBTs y := blockNBT["y"].(int32)
z := blockNBT["z"].(int32)
s.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBTs
} }
s.chunks[world.ChunkPos(pk.Position)] = ch s.chunks[world.ChunkPos(pk.Position)] = ch
for _, p := range s.server.Players() { for _, p := range s.server.Players() {
@ -83,11 +85,10 @@ func (s *secondaryUser) processSubChunk(pk *packet.SubChunk) {
offsets := make(map[world.ChunkPos]bool, len(pk.SubChunkEntries)) offsets := make(map[world.ChunkPos]bool, len(pk.SubChunkEntries))
for _, sub := range pk.SubChunkEntries { for _, sub := range pk.SubChunkEntries {
var ( var (
absX = pk.Position[0] + int32(sub.Offset[0]) absX = pk.Position[0] + int32(sub.Offset[0])
absY = pk.Position[1] + int32(sub.Offset[1]) absY = pk.Position[1] + int32(sub.Offset[1])
absZ = pk.Position[2] + int32(sub.Offset[2]) absZ = pk.Position[2] + int32(sub.Offset[2])
subPos = protocol.SubChunkPos{absX, absY, absZ} pos = world.ChunkPos{absX, absZ}
pos = world.ChunkPos{absX, absZ}
) )
offsets[pos] = true offsets[pos] = true
ch, ok := s.chunks[pos] ch, ok := s.chunks[pos]
@ -95,12 +96,15 @@ func (s *secondaryUser) processSubChunk(pk *packet.SubChunk) {
logrus.Error(locale.Loc("subchunk_before_chunk", nil)) logrus.Error(locale.Loc("subchunk_before_chunk", nil))
continue continue
} }
blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub) blockNBTs, err := ch.ApplySubChunkEntry(uint8(absY), &sub)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
if blockNBT != nil { for _, blockNBT := range blockNBTs {
s.blockNBT[subPos] = blockNBT x := blockNBT["x"].(int32)
y := blockNBT["y"].(int32)
z := blockNBT["z"].(int32)
s.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBTs
} }
chunk.LightArea([]*chunk.Chunk{ch}, 0, 0).Fill() chunk.LightArea([]*chunk.Chunk{ch}, 0, 0).Fill()

View File

@ -26,7 +26,7 @@ type secondaryUser struct {
hasCustomBlocks bool hasCustomBlocks bool
chunks map[world.ChunkPos]*chunk.Chunk chunks map[world.ChunkPos]*chunk.Chunk
blockNBT map[protocol.SubChunkPos][]map[string]any blockNBTs map[protocol.BlockPos][]map[string]any
dimension world.Dimension dimension world.Dimension
entities map[int64]*serverEntity entities map[int64]*serverEntity
@ -40,7 +40,7 @@ func NewSecondUser() *utils.ProxyHandler {
}, },
chunks: make(map[world.ChunkPos]*chunk.Chunk), chunks: make(map[world.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any), blockNBTs: make(map[protocol.BlockPos][]map[string]any),
dimension: world.Overworld, dimension: world.Overworld,
entities: make(map[int64]*serverEntity), entities: make(map[int64]*serverEntity),
} }

View File

@ -41,11 +41,13 @@ func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk) {
logrus.Error(err) logrus.Error(err)
return return
} }
if blockNBTs != nil { for _, blockNBT := range blockNBTs {
w.worldState.blockNBT[protocol.SubChunkPos{ x := blockNBT["x"].(int32)
pk.Position.X(), 0, pk.Position.Z(), y := blockNBT["y"].(int32)
}] = blockNBTs z := blockNBT["z"].(int32)
w.worldState.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBT
} }
w.worldState.chunks[pk.Position] = ch w.worldState.chunks[pk.Position] = ch
max := w.worldState.dimension.Range().Height() / 16 max := w.worldState.dimension.Range().Height() / 16
@ -84,23 +86,25 @@ func (w *worldsHandler) processSubChunk(pk *packet.SubChunk) {
for _, sub := range pk.SubChunkEntries { for _, sub := range pk.SubChunkEntries {
var ( var (
absX = pk.Position[0] + int32(sub.Offset[0]) absX = pk.Position[0] + int32(sub.Offset[0])
absY = pk.Position[1] + int32(sub.Offset[1]) absY = pk.Position[1] + int32(sub.Offset[1])
absZ = pk.Position[2] + int32(sub.Offset[2]) absZ = pk.Position[2] + int32(sub.Offset[2])
subPos = protocol.SubChunkPos{absX, absY, absZ} pos = protocol.ChunkPos{absX, absZ}
pos = protocol.ChunkPos{absX, absZ}
) )
ch, ok := w.worldState.chunks[pos] ch, ok := w.worldState.chunks[pos]
if !ok { if !ok {
logrus.Error(locale.Loc("subchunk_before_chunk", nil)) logrus.Error(locale.Loc("subchunk_before_chunk", nil))
continue continue
} }
blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub) blockNBTs, err := ch.ApplySubChunkEntry(uint8(absY), &sub)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
if blockNBT != nil { for _, blockNBT := range blockNBTs {
w.worldState.blockNBT[subPos] = blockNBT x := blockNBT["x"].(int32)
y := blockNBT["y"].(int32)
z := blockNBT["z"].(int32)
w.worldState.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBT
} }
posToRedraw[pos] = true posToRedraw[pos] = true
@ -131,19 +135,7 @@ func (w *worldsHandler) ProcessChunkPackets(pk packet.Packet) packet.Packet {
w.processSubChunk(pk) w.processSubChunk(pk)
case *packet.BlockActorData: case *packet.BlockActorData:
if w.settings.BlockUpdates { if w.settings.BlockUpdates {
sp := protocol.SubChunkPos{pk.Position.X() << 4, 0, pk.Position.Z() << 4} w.worldState.blockNBTs[pk.Position] = pk.NBTData
b, ok := w.worldState.blockNBT[sp]
if !ok {
w.worldState.blockNBT[sp] = []map[string]any{pk.NBTData}
} else {
for i, v := range b {
x, y, z := v["x"].(int32), v["y"].(int32), v["z"].(int32)
if x == pk.Position.X() && y == pk.Position.Y() && z == pk.Position.Z() {
b[i] = pk.NBTData
break
}
}
}
} }
case *packet.UpdateBlock: case *packet.UpdateBlock:
if w.settings.BlockUpdates { if w.settings.BlockUpdates {

View File

@ -84,9 +84,6 @@ func (w *worldsHandler) processItemPacketsServer(pk packet.Packet) packet.Packet
break break
} }
pos := existing.OpenPacket.ContainerPosition
cp := protocol.SubChunkPos{pos.X() << 4, pos.Z() << 4}
// create inventory // create inventory
inv := inventory.New(len(existing.Content.Content), nil) inv := inventory.New(len(existing.Content.Content), nil)
for i, c := range existing.Content.Content { for i, c := range existing.Content.Content {
@ -95,13 +92,9 @@ func (w *worldsHandler) processItemPacketsServer(pk packet.Packet) packet.Packet
} }
// put into subchunk // put into subchunk
nbts := w.worldState.blockNBT[cp] nbt, ok := w.worldState.blockNBTs[existing.OpenPacket.ContainerPosition]
for i, v := range nbts { if ok {
NBTPos := protocol.BlockPos{v["x"].(int32), v["y"].(int32), v["z"].(int32)} nbt["Items"] = nbtconv.InvToNBT(inv)
if NBTPos == pos {
w.worldState.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv)
break
}
} }
w.proxy.SendMessage(locale.Loc("saved_block_inv", nil)) w.proxy.SendMessage(locale.Loc("saved_block_inv", nil))

View File

@ -55,7 +55,7 @@ type WorldSettings struct {
type worldState struct { type worldState struct {
dimension world.Dimension dimension world.Dimension
chunks map[protocol.ChunkPos]*chunk.Chunk chunks map[protocol.ChunkPos]*chunk.Chunk
blockNBT map[protocol.SubChunkPos][]map[string]any blockNBTs map[protocol.BlockPos]map[string]any
entities map[uint64]*entityState entities map[uint64]*entityState
openItemContainers map[byte]*itemContainer openItemContainers map[byte]*itemContainer
Name string Name string
@ -219,7 +219,7 @@ func (w *worldsHandler) Reset() {
w.worldState = worldState{ w.worldState = worldState{
dimension: w.worldState.dimension, dimension: w.worldState.dimension,
chunks: make(map[protocol.ChunkPos]*chunk.Chunk), chunks: make(map[protocol.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any), blockNBTs: make(map[protocol.BlockPos]map[string]any),
entities: make(map[uint64]*entityState), entities: make(map[uint64]*entityState),
openItemContainers: make(map[byte]*itemContainer), openItemContainers: make(map[byte]*itemContainer),
Name: w.currentName(), Name: w.currentName(),
@ -256,13 +256,13 @@ func (w *worldState) Save(folder string) (*mcdb.DB, error) {
} }
// save block nbt data // save block nbt data
blockNBT := make(map[world.ChunkPos][]map[string]any) chunkBlockNBT := make(map[world.ChunkPos][]map[string]any)
for scp, v := range w.blockNBT { // 3d to 2d for bp, blockNBT := range w.blockNBTs { // 3d to 2d
cp := world.ChunkPos{scp.X(), scp.Z()} cp := world.ChunkPos{bp.X() >> 4, bp.Z() >> 4}
blockNBT[cp] = append(blockNBT[cp], v...) chunkBlockNBT[cp] = append(chunkBlockNBT[cp], blockNBT)
} }
for cp, v := range blockNBT { for cp, blockNBT := range chunkBlockNBT {
err = provider.SaveBlockNBT(cp, v, w.dimension) err = provider.SaveBlockNBT(cp, blockNBT, w.dimension)
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }