diff --git a/handlers/second-user/chunks.go b/handlers/second-user/chunks.go index b6acd78..cb6f2ef 100644 --- a/handlers/second-user/chunks.go +++ b/handlers/second-user/chunks.go @@ -11,7 +11,7 @@ import ( func (s *secondaryUser) ResetWorld() { 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) { @@ -26,7 +26,6 @@ func (s *secondaryUser) processChangeDimension(pk *packet.ChangeDimension) { func (s *secondaryUser) processLevelChunk(pk *packet.LevelChunk) { // ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS if len(pk.RawPayload) == 0 { - logrus.Info(locale.Loc("empty_chunk", nil)) return } @@ -45,11 +44,14 @@ func (s *secondaryUser) processLevelChunk(pk *packet.LevelChunk) { logrus.Error(err) return } - if blockNBTs != nil { - s.blockNBT[protocol.SubChunkPos{ - pk.Position.X(), 0, pk.Position.Z(), - }] = blockNBTs + + for _, blockNBT := range blockNBTs { + x := blockNBT["x"].(int32) + y := blockNBT["y"].(int32) + z := blockNBT["z"].(int32) + s.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBTs } + s.chunks[world.ChunkPos(pk.Position)] = ch 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)) 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 = world.ChunkPos{absX, absZ} + absX = pk.Position[0] + int32(sub.Offset[0]) + absY = pk.Position[1] + int32(sub.Offset[1]) + absZ = pk.Position[2] + int32(sub.Offset[2]) + pos = world.ChunkPos{absX, absZ} ) offsets[pos] = true ch, ok := s.chunks[pos] @@ -95,12 +96,15 @@ func (s *secondaryUser) processSubChunk(pk *packet.SubChunk) { logrus.Error(locale.Loc("subchunk_before_chunk", nil)) continue } - blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub) + blockNBTs, err := ch.ApplySubChunkEntry(uint8(absY), &sub) if err != nil { logrus.Error(err) } - if blockNBT != nil { - s.blockNBT[subPos] = blockNBT + for _, blockNBT := range blockNBTs { + 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() diff --git a/handlers/second-user/second-user.go b/handlers/second-user/second-user.go index 977ec16..e940fa7 100644 --- a/handlers/second-user/second-user.go +++ b/handlers/second-user/second-user.go @@ -26,7 +26,7 @@ type secondaryUser struct { hasCustomBlocks bool chunks map[world.ChunkPos]*chunk.Chunk - blockNBT map[protocol.SubChunkPos][]map[string]any + blockNBTs map[protocol.BlockPos][]map[string]any dimension world.Dimension entities map[int64]*serverEntity @@ -40,7 +40,7 @@ func NewSecondUser() *utils.ProxyHandler { }, 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, entities: make(map[int64]*serverEntity), } diff --git a/handlers/worlds/chunk.go b/handlers/worlds/chunk.go index 0fcf719..c115a31 100644 --- a/handlers/worlds/chunk.go +++ b/handlers/worlds/chunk.go @@ -41,11 +41,13 @@ func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk) { logrus.Error(err) return } - if blockNBTs != nil { - w.worldState.blockNBT[protocol.SubChunkPos{ - pk.Position.X(), 0, pk.Position.Z(), - }] = blockNBTs + for _, blockNBT := range blockNBTs { + x := blockNBT["x"].(int32) + y := blockNBT["y"].(int32) + z := blockNBT["z"].(int32) + w.worldState.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBT } + w.worldState.chunks[pk.Position] = ch max := w.worldState.dimension.Range().Height() / 16 @@ -84,23 +86,25 @@ func (w *worldsHandler) processSubChunk(pk *packet.SubChunk) { 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} + absX = pk.Position[0] + int32(sub.Offset[0]) + absY = pk.Position[1] + int32(sub.Offset[1]) + absZ = pk.Position[2] + int32(sub.Offset[2]) + pos = protocol.ChunkPos{absX, absZ} ) ch, ok := w.worldState.chunks[pos] if !ok { logrus.Error(locale.Loc("subchunk_before_chunk", nil)) continue } - blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub) + blockNBTs, err := ch.ApplySubChunkEntry(uint8(absY), &sub) if err != nil { logrus.Error(err) } - if blockNBT != nil { - w.worldState.blockNBT[subPos] = blockNBT + for _, blockNBT := range blockNBTs { + x := blockNBT["x"].(int32) + y := blockNBT["y"].(int32) + z := blockNBT["z"].(int32) + w.worldState.blockNBTs[protocol.BlockPos{x, y, z}] = blockNBT } posToRedraw[pos] = true @@ -131,19 +135,7 @@ func (w *worldsHandler) ProcessChunkPackets(pk packet.Packet) packet.Packet { w.processSubChunk(pk) case *packet.BlockActorData: if w.settings.BlockUpdates { - sp := protocol.SubChunkPos{pk.Position.X() << 4, 0, pk.Position.Z() << 4} - 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 - } - } - } + w.worldState.blockNBTs[pk.Position] = pk.NBTData } case *packet.UpdateBlock: if w.settings.BlockUpdates { diff --git a/handlers/worlds/items.go b/handlers/worlds/items.go index 3e84783..47473fe 100644 --- a/handlers/worlds/items.go +++ b/handlers/worlds/items.go @@ -84,9 +84,6 @@ func (w *worldsHandler) processItemPacketsServer(pk packet.Packet) packet.Packet break } - pos := existing.OpenPacket.ContainerPosition - cp := protocol.SubChunkPos{pos.X() << 4, pos.Z() << 4} - // create inventory inv := inventory.New(len(existing.Content.Content), nil) for i, c := range existing.Content.Content { @@ -95,13 +92,9 @@ func (w *worldsHandler) processItemPacketsServer(pk packet.Packet) packet.Packet } // put into subchunk - nbts := w.worldState.blockNBT[cp] - for i, v := range nbts { - NBTPos := protocol.BlockPos{v["x"].(int32), v["y"].(int32), v["z"].(int32)} - if NBTPos == pos { - w.worldState.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv) - break - } + nbt, ok := w.worldState.blockNBTs[existing.OpenPacket.ContainerPosition] + if ok { + nbt["Items"] = nbtconv.InvToNBT(inv) } w.proxy.SendMessage(locale.Loc("saved_block_inv", nil)) diff --git a/handlers/worlds/world.go b/handlers/worlds/world.go index a0de390..ca1e64a 100644 --- a/handlers/worlds/world.go +++ b/handlers/worlds/world.go @@ -55,7 +55,7 @@ type WorldSettings struct { type worldState struct { dimension world.Dimension chunks map[protocol.ChunkPos]*chunk.Chunk - blockNBT map[protocol.SubChunkPos][]map[string]any + blockNBTs map[protocol.BlockPos]map[string]any entities map[uint64]*entityState openItemContainers map[byte]*itemContainer Name string @@ -219,7 +219,7 @@ func (w *worldsHandler) Reset() { w.worldState = worldState{ dimension: w.worldState.dimension, 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), openItemContainers: make(map[byte]*itemContainer), Name: w.currentName(), @@ -256,13 +256,13 @@ func (w *worldState) Save(folder string) (*mcdb.DB, error) { } // save block nbt data - blockNBT := make(map[world.ChunkPos][]map[string]any) - for scp, v := range w.blockNBT { // 3d to 2d - cp := world.ChunkPos{scp.X(), scp.Z()} - blockNBT[cp] = append(blockNBT[cp], v...) + chunkBlockNBT := make(map[world.ChunkPos][]map[string]any) + for bp, blockNBT := range w.blockNBTs { // 3d to 2d + cp := world.ChunkPos{bp.X() >> 4, bp.Z() >> 4} + chunkBlockNBT[cp] = append(chunkBlockNBT[cp], blockNBT) } - for cp, v := range blockNBT { - err = provider.SaveBlockNBT(cp, v, w.dimension) + for cp, blockNBT := range chunkBlockNBT { + err = provider.SaveBlockNBT(cp, blockNBT, w.dimension) if err != nil { logrus.Error(err) }