From 1e990d7fcbf40398235bbdef8f42e54c02fc6405 Mon Sep 17 00:00:00 2001 From: olebeck <31539311+olebeck@users.noreply.github.com> Date: Thu, 30 Mar 2023 13:48:03 +0200 Subject: [PATCH] performance optimizations --- cmd/bedrocktool/main.go | 9 + go.mod | 5 +- go.sum | 6 + subcommands/debug.go | 21 +- subcommands/resourcepack-d/resourcepack-d.go | Bin 5439 -> 5439 bytes subcommands/world/chunk.go | 57 ++-- subcommands/world/chunk.png | Bin 513 -> 432 bytes subcommands/world/chunk_test.go | 14 + subcommands/world/entity.go | 20 +- subcommands/world/items.go | 36 +-- subcommands/world/map_item.go | 14 +- subcommands/world/world.go | 257 ++++++++++--------- utils/packet_logger.go | 105 ++++---- utils/utils.go | 32 +-- utils/zip.go | 7 + 15 files changed, 320 insertions(+), 263 deletions(-) diff --git a/cmd/bedrocktool/main.go b/cmd/bedrocktool/main.go index 22c48a2..bcca4a6 100644 --- a/cmd/bedrocktool/main.go +++ b/cmd/bedrocktool/main.go @@ -41,6 +41,15 @@ func (c *CLI) Start(ctx context.Context, cancel context.CancelFunc) error { } func main() { + /* + cf, _ := os.Create("cpu.pprof") + err := pprof.StartCPUProfile(cf) + if err != nil { + logrus.Error(err) + } + defer pprof.StopCPUProfile() + */ + defer func() { if err := recover(); err != nil { logrus.Errorf(locale.Loc("fatal_error", nil)) diff --git a/go.mod b/go.mod index 12d6420..6b7dd14 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ go 1.20 replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.28.1-1 //replace github.com/df-mc/dragonfly => ./dragonfly -replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.9.3-10 +replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.9.4-3 //replace gioui.org => ./gio replace gioui.org => github.com/olebeck/gio v0.0.0-20230321105529-d424f1a59af9 @@ -15,7 +15,7 @@ require ( gioui.org v0.0.0-20230323230841-d7b1c7c33b33 gioui.org/x v0.0.0-20230313161557-05b40af72ed0 github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 - github.com/df-mc/dragonfly v0.9.3 + github.com/df-mc/dragonfly v0.9.4 github.com/df-mc/goleveldb v1.1.9 github.com/fatih/color v1.15.0 github.com/flytam/filenamify v1.1.2 @@ -48,6 +48,7 @@ require ( github.com/changkun/lockfree v0.0.1 // indirect github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 // indirect github.com/df-mc/atomic v1.10.0 // indirect + github.com/df-mc/worldupgrader v1.0.3 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-text/typesetting v0.0.0-20221214153724-0399769901d5 // indirect github.com/golang/protobuf v1.5.2 // indirect diff --git a/go.sum b/go.sum index bde7c50..33d44d1 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/df-mc/atomic v1.10.0 h1:0ZuxBKwR/hxcFGorKiHIp+hY7hgY+XBTzhCYD2NqSEg= github.com/df-mc/atomic v1.10.0/go.mod h1:Gw9rf+rPIbydMjA329Jn4yjd/O2c/qusw3iNp4tFGSc= github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU= github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk= +github.com/df-mc/worldupgrader v1.0.3 h1:3nbthy6vfSNQZdqHBR+E5Fh3mCeWmCwLtqrYDiPUG5I= +github.com/df-mc/worldupgrader v1.0.3/go.mod h1:6ybkJ/BV9b0XkcPzcLmvgT9Nv/xgBXdDQTmRhu7b8zQ= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/flytam/filenamify v1.1.2 h1:dGlfWU4zrhDlsmvob4IFcfgjG5vIjfo4UwLyec6Wx94= @@ -83,6 +85,10 @@ github.com/nicksnyder/go-i18n/v2 v2.2.1 h1:aOzRCdwsJuoExfZhoiXHy4bjruwCMdt5otbYo github.com/nicksnyder/go-i18n/v2 v2.2.1/go.mod h1:fF2++lPHlo+/kPaj3nB0uxtPwzlPm+BlgwGX7MkeGj0= github.com/olebeck/dragonfly v0.9.3-10 h1:USruaK+8c3gsX9CtDzInLbwsdoZxcYjmnC8t/H4/Zjw= github.com/olebeck/dragonfly v0.9.3-10/go.mod h1:nnnmYWgSTNQb9x33nBthqN/2vyHlUaijfo+e2y3W5j4= +github.com/olebeck/dragonfly v0.9.4-1 h1:AvP0JALUJqkDBTCT/7tOrIndKIrIol1rX6XFcbOwpLI= +github.com/olebeck/dragonfly v0.9.4-1/go.mod h1:Iu46xugbkTQ9CcUj+zPC4VvKP94CmxxLGtW8pHgAPr4= +github.com/olebeck/dragonfly v0.9.4-2 h1:e1bzsTxcPMaUUs2B6wnCbc1FE96XcdBbL7mp1LE92NI= +github.com/olebeck/dragonfly v0.9.4-2/go.mod h1:k8OQvjmfj+JbrwQf1qHfMETlFHOp0WJLjILN+QVqh+c= github.com/olebeck/gio v0.0.0-20230321105529-d424f1a59af9 h1:TqDsMHwjW5ZYfh+RE8ussT62m0qXqo+QjzSXb7BCVA4= github.com/olebeck/gio v0.0.0-20230321105529-d424f1a59af9/go.mod h1:+W1Kpf96YcfissZocFqIp6O42FDTuphkObbEybp+Ffc= github.com/olebeck/gophertunnel v1.28.1-1 h1:bw2jeMz94YHF5qQYhq1Yq/6fALkklGu7k26YbPI4DSs= diff --git a/subcommands/debug.go b/subcommands/debug.go index 52dbb2d..c935bdb 100644 --- a/subcommands/debug.go +++ b/subcommands/debug.go @@ -3,7 +3,6 @@ package subcommands import ( "context" "flag" - "strings" "github.com/bedrock-tool/bedrocktool/locale" "github.com/bedrock-tool/bedrocktool/utils" @@ -11,14 +10,12 @@ import ( type DebugProxyCMD struct { ServerAddress string - Filter string } func (*DebugProxyCMD) Name() string { return "debug-proxy" } func (*DebugProxyCMD) Synopsis() string { return locale.Loc("debug_proxy_synopsis", nil) } func (c *DebugProxyCMD) SetFlags(f *flag.FlagSet) { f.StringVar(&c.ServerAddress, "address", "", locale.Loc("remote_address", nil)) - f.StringVar(&c.Filter, "filter", "", locale.Loc("packet_filter", nil)) } func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error { @@ -29,27 +26,11 @@ func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error { utils.Options.Debug = true - filters := strings.Split(c.Filter, ",") - if len(filters) > 0 { - for _, v := range filters { - if len(v) == 0 { - continue - } - if string(v[0]) == "*" { - v = v[1:] - } - v = strings.TrimPrefix(v, "packet.") - v = "packet." + v - utils.ExtraVerbose = append(utils.ExtraVerbose, v) - } - } - proxy, err := utils.NewProxy() if err != nil { return err } - err = proxy.Run(ctx, address) - return err + return proxy.Run(ctx, address) } func init() { diff --git a/subcommands/resourcepack-d/resourcepack-d.go b/subcommands/resourcepack-d/resourcepack-d.go index bcdba78af8ecb180f8b3c355b874f68498e48ccc..e3480d52ef76075e931e97801fefeb69716a1c5e 100644 GIT binary patch literal 5439 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 diff --git a/subcommands/world/chunk.go b/subcommands/world/chunk.go index ed027a6..e39f1fc 100644 --- a/subcommands/world/chunk.go +++ b/subcommands/world/chunk.go @@ -9,21 +9,21 @@ import ( "github.com/sirupsen/logrus" ) -func (w *WorldState) processChangeDimension(pk *packet.ChangeDimension) { - if len(w.chunks) > 0 { +func (w *worldsServer) processChangeDimension(pk *packet.ChangeDimension) { + if len(w.worldState.chunks) > 0 { w.SaveAndReset() } else { logrus.Info(locale.Loc("not_saving_empty", nil)) - w.Reset() + w.Reset(w.CurrentName()) } dimensionID := pk.Dimension - if w.ispre118 { + if w.serverState.ispre118 { dimensionID += 10 } - w.Dim = dimensionIDMap[uint8(dimensionID)] + w.worldState.Dim = dimensionIDMap[uint8(dimensionID)] } -func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) { +func (w *worldsServer) processLevelChunk(pk *packet.LevelChunk) { // ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS if len(pk.RawPayload) == 0 { logrus.Info(locale.Loc("empty_chunk", nil)) @@ -40,32 +40,35 @@ func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) { subChunkCount = int(pk.SubChunkCount) } - ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.Dim.Range(), w.ispre118, w.bp.HasBlocks()) + ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.worldState.Dim.Range(), w.serverState.ispre118, w.bp.HasBlocks()) if err != nil { logrus.Error(err) return } if blockNBTs != nil { - w.blockNBT[protocol.SubChunkPos{ + w.worldState.blockNBT[protocol.SubChunkPos{ pk.Position.X(), 0, pk.Position.Z(), }] = blockNBTs } - w.chunks[pk.Position] = ch + w.worldState.chunks[pk.Position] = ch - max := w.Dim.Range().Height() / 16 + max := w.worldState.Dim.Range().Height() / 16 switch pk.SubChunkCount { case protocol.SubChunkRequestModeLimited: max = int(pk.HighestSubChunk) fallthrough case protocol.SubChunkRequestModeLimitless: var offsetTable []protocol.SubChunkOffset - r := w.Dim.Range() + r := w.worldState.Dim.Range() for y := int8(r.Min() / 16); y < int8(r.Max()); y++ { offsetTable = append(offsetTable, protocol.SubChunkOffset{0, y, 0}) } + dimId, ok := world.DimensionID(w.worldState.Dim) + _ = ok + w.proxy.Server.WritePacket(&packet.SubChunkRequest{ - Dimension: int32(w.Dim.EncodeDimension()), + Dimension: int32(dimId), Position: protocol.SubChunkPos{ pk.Position.X(), 0, pk.Position.Z(), }, @@ -86,7 +89,7 @@ func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) { } } -func (w *WorldState) processSubChunk(pk *packet.SubChunk) { +func (w *worldsServer) processSubChunk(pk *packet.SubChunk) { posToRedraw := make(map[protocol.ChunkPos]bool) for _, sub := range pk.SubChunkEntries { @@ -97,7 +100,7 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) { subPos = protocol.SubChunkPos{absX, absY, absZ} pos = protocol.ChunkPos{absX, absZ} ) - ch, ok := w.chunks[pos] + ch, ok := w.worldState.chunks[pos] if !ok { logrus.Error(locale.Loc("subchunk_before_chunk", nil)) continue @@ -107,7 +110,7 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) { logrus.Error(err) } if blockNBT != nil { - w.blockNBT[subPos] = blockNBT + w.worldState.blockNBT[subPos] = blockNBT } posToRedraw[pos] = true @@ -115,7 +118,7 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) { // redraw the chunks for pos := range posToRedraw { - w.mapUI.SetChunk(pos, w.chunks[pos], true) + w.mapUI.SetChunk(pos, w.worldState.chunks[pos], true) } w.mapUI.SchedRedraw() } @@ -124,22 +127,22 @@ func blockPosInChunk(pos protocol.BlockPos) (uint8, int16, uint8) { return uint8(pos.X() & 0x0f), int16(pos.Y() & 0x0f), uint8(pos.Z() & 0x0f) } -func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet { +func (w *worldsServer) 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))) + 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) case *packet.BlockActorData: - if w.blockUpdates { + if w.settings.blockUpdates { sp := protocol.SubChunkPos{pk.Position.X() << 4, 0, pk.Position.Z() << 4} - b, ok := w.blockNBT[sp] + b, ok := w.worldState.blockNBT[sp] if !ok { - w.blockNBT[sp] = []map[string]any{pk.NBTData} + 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) @@ -151,19 +154,19 @@ func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet { } } case *packet.UpdateBlock: - if w.blockUpdates { + if w.settings.blockUpdates { cp := protocol.ChunkPos{pk.Position.X() >> 4, pk.Position.Z() >> 4} - c, ok := w.chunks[cp] + c, ok := w.worldState.chunks[cp] if ok { x, y, z := blockPosInChunk(pk.Position) c.SetBlock(x, y, z, uint8(pk.Layer), pk.NewBlockRuntimeID) - w.mapUI.SetChunk(cp, w.chunks[cp], true) + w.mapUI.SetChunk(cp, w.worldState.chunks[cp], true) } } case *packet.UpdateSubChunkBlocks: - if w.blockUpdates { + if w.settings.blockUpdates { cp := protocol.ChunkPos{pk.Position.X(), pk.Position.Z()} - c, ok := w.chunks[cp] + c, ok := w.worldState.chunks[cp] if ok { for _, bce := range pk.Blocks { x, y, z := blockPosInChunk(bce.BlockPos) @@ -173,7 +176,7 @@ func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet { c.SetBlock(x, y, z, 0, bce.BlockRuntimeID) } } - w.mapUI.SetChunk(cp, w.chunks[cp], true) + w.mapUI.SetChunk(cp, w.worldState.chunks[cp], true) } } } diff --git a/subcommands/world/chunk.png b/subcommands/world/chunk.png index e4b8236971363378d94d65f044391cbd2fc53e39..d628c0d7ce43a32e3031ab9207aef02bdc6940a5 100644 GIT binary patch delta 406 zcmV;H0crk$1h4~;B!72FL_t(|oML%4bIZP)@14{I8NguQ&G!rp495PCwwz#NU|{(2 z?F$bV4@3&WX5#($je&uI_v1GR@|R#|U|@i#Mgu%tJYT+jVfoC@#qi=Mh=hX|KQUFq z0TUV@;-oL%z95^5tbhgXBs`{~Xh3%oUiV;e5+u0LLWUwIF@HfE^O>Iuf;NJkl_BxFYtW zypVYK7;&6|f#KCwQ8Dk=3=9m5dd@D$_JjK2$J=`h3=BWs-uv~J%thv%mQ|b79~I4-t*$J^^7!M)N>ZuHUU%!20X8Ody zz;OHbBYi6=ZnbY*cT^z8|1dbu@st+U=OaK4?07*qoM6N<$g7b;P AUH||9 delta 487 zcmVbp(uC}{{sI9J$TW4yK2 zE!{eLhmn*F+kgLMBFY7MN@VP^bqf7p`sLR)$;WpqX__i35%E3WuqBd+h<&18_-FUQ zoeIzePKP_kMx#i@;Kh?SueQ2de+a@kpEI13E`OKV3|=Wpxe z-K^=$Z?8>l-y~V$P+619V?n*Tx>sln#-m2Hkd;2&dtZ!A(phAL^` diff --git a/subcommands/world/chunk_test.go b/subcommands/world/chunk_test.go index b32619e..9fa2e87 100644 --- a/subcommands/world/chunk_test.go +++ b/subcommands/world/chunk_test.go @@ -3,6 +3,7 @@ package world_test import ( "image/png" "os" + "runtime/pprof" "testing" "github.com/bedrock-tool/bedrocktool/subcommands/world" @@ -21,19 +22,32 @@ func Test(t *testing.T) { func Benchmark_chunk_decode(b *testing.B) { data, _ := os.ReadFile("chunk.bin") + + cf, _ := os.Create("cpu.pprof") + err := pprof.StartCPUProfile(cf) + if err != nil { + b.Error(err) + } for i := 0; i < b.N; i++ { _, _, err := chunk.NetworkDecode(33, data, 6, cube.Range{0, 255}, true, false) if err != nil { b.Error(err) } } + pprof.StopCPUProfile() } func Benchmark_render_chunk(b *testing.B) { data, _ := os.ReadFile("chunk.bin") ch, _, _ := chunk.NetworkDecode(33, data, 6, cube.Range{0, 255}, true, false) + cf, _ := os.Create("cpu.pprof") + err := pprof.StartCPUProfile(cf) + if err != nil { + b.Error(err) + } for i := 0; i < b.N; i++ { world.Chunk2Img(ch, true) } + pprof.StopCPUProfile() } diff --git a/subcommands/world/entity.go b/subcommands/world/entity.go index c7fb442..1f948af 100644 --- a/subcommands/world/entity.go +++ b/subcommands/world/entity.go @@ -61,8 +61,8 @@ func (e serverEntity) Type() world.EntityType { return e.EntityType } -func (w *WorldState) processAddActor(pk *packet.AddActor) { - e, ok := w.entities[pk.EntityRuntimeID] +func (w *worldsServer) processAddActor(pk *packet.AddActor) { + e, ok := w.worldState.entities[pk.EntityRuntimeID] if !ok { e = &entityState{ RuntimeID: pk.EntityRuntimeID, @@ -71,7 +71,7 @@ func (w *WorldState) processAddActor(pk *packet.AddActor) { Inventory: make(map[byte]map[byte]protocol.ItemInstance), Metadata: make(map[uint32]any), } - w.entities[pk.EntityRuntimeID] = e + w.worldState.entities[pk.EntityRuntimeID] = e w.bp.AddEntity(behaviourpack.EntityIn{ Identifier: pk.EntityType, @@ -211,25 +211,25 @@ func (s *entityState) ToServerEntity() serverEntity { return e } -func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet { +func (w *worldsServer) ProcessEntityPackets(pk packet.Packet) packet.Packet { switch pk := pk.(type) { case *packet.AddActor: w.processAddActor(pk) case *packet.RemoveActor: case *packet.SetActorData: - e, ok := w.entities[pk.EntityRuntimeID] + e, ok := w.worldState.entities[pk.EntityRuntimeID] if ok { for k, v := range pk.EntityMetadata { e.Metadata[k] = v } } case *packet.SetActorMotion: - e, ok := w.entities[pk.EntityRuntimeID] + e, ok := w.worldState.entities[pk.EntityRuntimeID] if ok { e.Velocity = pk.Velocity } case *packet.MoveActorDelta: - e, ok := w.entities[pk.EntityRuntimeID] + e, ok := w.worldState.entities[pk.EntityRuntimeID] if ok { if pk.Flags&packet.MoveActorDeltaFlagHasX != 0 { e.Position[0] = pk.Position[0] @@ -251,14 +251,14 @@ func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet { //} } case *packet.MoveActorAbsolute: - e, ok := w.entities[pk.EntityRuntimeID] + e, ok := w.worldState.entities[pk.EntityRuntimeID] if ok { e.Position = pk.Position e.Pitch = pk.Rotation.X() e.Yaw = pk.Rotation.Y() } case *packet.MobEquipment: - e, ok := w.entities[pk.EntityRuntimeID] + e, ok := w.worldState.entities[pk.EntityRuntimeID] if ok { w, ok := e.Inventory[pk.WindowID] if !ok { @@ -268,7 +268,7 @@ func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet { w[pk.HotBarSlot] = pk.NewItem } case *packet.MobArmourEquipment: - e, ok := w.entities[pk.EntityRuntimeID] + e, ok := w.worldState.entities[pk.EntityRuntimeID] if ok { e.Helmet = &pk.Helmet e.Chestplate = &pk.Chestplate diff --git a/subcommands/world/items.go b/subcommands/world/items.go index 3f877d9..bac9d6f 100644 --- a/subcommands/world/items.go +++ b/subcommands/world/items.go @@ -17,25 +17,25 @@ type itemContainer struct { Content *packet.InventoryContent } -func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { +func (w *worldsServer) processItemPacketsServer(pk packet.Packet) packet.Packet { switch pk := pk.(type) { case *packet.ContainerOpen: // add to open containers - existing, ok := w.openItemContainers[pk.WindowID] + existing, ok := w.worldState.openItemContainers[pk.WindowID] if !ok { existing = &itemContainer{} } - w.openItemContainers[pk.WindowID] = &itemContainer{ + w.worldState.openItemContainers[pk.WindowID] = &itemContainer{ OpenPacket: pk, Content: existing.Content, } case *packet.InventoryContent: if pk.WindowID == 0x0 { // inventory - w.playerInventory = pk.Content + w.serverState.playerInventory = pk.Content } else { // save content - existing, ok := w.openItemContainers[byte(pk.WindowID)] + existing, ok := w.worldState.openItemContainers[byte(pk.WindowID)] if ok { existing.Content = pk } @@ -43,10 +43,10 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { case *packet.InventorySlot: if pk.WindowID == 0x0 { - w.playerInventory[pk.Slot] = pk.NewItem + w.serverState.playerInventory[pk.Slot] = pk.NewItem } else { // save content - existing, ok := w.openItemContainers[byte(pk.WindowID)] + existing, ok := w.worldState.openItemContainers[byte(pk.WindowID)] if ok { existing.Content.Content[pk.Slot] = pk.NewItem } @@ -56,7 +56,7 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { case *packet.ContainerClose: // find container info - existing, ok := w.openItemContainers[byte(pk.WindowID)] + existing, ok := w.worldState.openItemContainers[byte(pk.WindowID)] switch pk.WindowID { case protocol.WindowIDArmour: // todo handle @@ -88,11 +88,11 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { } // put into subchunk - nbts := w.blockNBT[cp] + 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.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv) + w.worldState.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv) break } } @@ -100,7 +100,7 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { w.proxy.SendMessage(locale.Loc("saved_block_inv", nil)) // remove it again - delete(w.openItemContainers, byte(pk.WindowID)) + delete(w.worldState.openItemContainers, byte(pk.WindowID)) } case *packet.ItemComponent: @@ -113,7 +113,7 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { return pk } -func (w *WorldState) processItemPacketsClient(pk packet.Packet, forward *bool) packet.Packet { +func (w *worldsServer) processItemPacketsClient(pk packet.Packet, forward *bool) packet.Packet { switch pk := pk.(type) { case *packet.ItemStackRequest: var requests []protocol.ItemStackRequest @@ -184,15 +184,15 @@ func stackToItem(it protocol.ItemStack) item.Stack { return nbtconv.ReadItem(it.NBTData, &s) } -func (w *WorldState) playerData() (ret map[string]any) { +func (w *worldsServer) playerData() (ret map[string]any) { ret = map[string]any{ "format_version": "1.12.0", "identifier": "minecraft:player", } - if len(w.playerInventory) > 0 { - inv := inventory.New(len(w.playerInventory), nil) - for i, ii := range w.playerInventory { + if len(w.serverState.playerInventory) > 0 { + inv := inventory.New(len(w.serverState.playerInventory), nil) + for i, ii := range w.serverState.playerInventory { inv.SetItem(i, stackToItem(ii.Stack)) } ret["Inventory"] = nbtconv.InvToNBT(inv) @@ -373,8 +373,8 @@ func (w *WorldState) playerData() (ret map[string]any) { } ret["Rotation"] = []float32{ - w.PlayerPos.Pitch, - w.PlayerPos.Yaw, + w.serverState.PlayerPos.Pitch, + w.serverState.PlayerPos.Yaw, } return diff --git a/subcommands/world/map_item.go b/subcommands/world/map_item.go index f1636eb..ccf0800 100644 --- a/subcommands/world/map_item.go +++ b/subcommands/world/map_item.go @@ -79,10 +79,10 @@ type MapUI struct { l sync.RWMutex ticker *time.Ticker - w *WorldState + w *worldsServer } -func NewMapUI(w *WorldState) *MapUI { +func NewMapUI(w *worldsServer) *MapUI { m := &MapUI{ img: image.NewRGBA(image.Rect(0, 0, 128, 128)), zoomLevel: 16, @@ -198,8 +198,8 @@ func (m *MapUI) Redraw() { m.l.Unlock() middle := protocol.ChunkPos{ - int32(m.w.PlayerPos.Position.X()), - int32(m.w.PlayerPos.Position.Z()), + int32(m.w.serverState.PlayerPos.Position.X()), + int32(m.w.serverState.PlayerPos.Position.Z()), } chunksPerLine := float64(128 / m.zoomLevel) @@ -227,7 +227,7 @@ func (m *MapUI) Redraw() { min, max := m.GetBounds() m.w.gui.Message(messages.UpdateMap, messages.UpdateMapPayload{ ChunkCount: len(m.renderedChunks), - Rotation: m.w.PlayerPos.Yaw, + Rotation: m.w.serverState.PlayerPos.Yaw, UpdatedTiles: updatedChunks, Tiles: m.renderedChunks, BoundsMin: min, @@ -265,14 +265,14 @@ func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk, complete bool) m.SchedRedraw() } -func (w *WorldState) ProcessAnimate(pk *packet.Animate) { +func (w *worldsServer) ProcessAnimate(pk *packet.Animate) { if pk.ActionType == packet.AnimateActionSwingArm { w.mapUI.ChangeZoom() w.proxy.SendPopup(locale.Loc("zoom_level", locale.Strmap{"Level": w.mapUI.zoomLevel})) } } -func (w *WorldState) processMapPacketsClient(pk packet.Packet, forward *bool) packet.Packet { +func (w *worldsServer) processMapPacketsClient(pk packet.Packet, forward *bool) packet.Packet { switch pk := pk.(type) { case *packet.MovePlayer: w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw) diff --git a/subcommands/world/world.go b/subcommands/world/world.go index 9623481..e666401 100644 --- a/subcommands/world/world.go +++ b/subcommands/world/world.go @@ -1,7 +1,6 @@ package world import ( - "bytes" "context" "encoding/json" "flag" @@ -41,53 +40,69 @@ type TPlayerPos struct { // the state used for drawing and saving -type WorldState struct { +type worldSettings struct { + // settings + voidGen bool + withPacks bool + saveImage bool + blockUpdates bool +} + +type worldState struct { + Dim world.Dimension + chunks map[protocol.ChunkPos]*chunk.Chunk + blockNBT map[protocol.SubChunkPos][]map[string]any + entities map[uint64]*entityState + openItemContainers map[byte]*itemContainer + Name string +} + +type serverState struct { + ChunkRadius int + ispre118 bool + worldCounter int + + playerInventory []protocol.ItemInstance + PlayerPos TPlayerPos + + Name string +} + +type worldsServer struct { ctx context.Context proxy *utils.ProxyContext mapUI *MapUI gui utils.UI bp *behaviourpack.BehaviourPack - // save state - ChunkRadius int - chunks map[protocol.ChunkPos]*chunk.Chunk - blockNBT map[protocol.SubChunkPos][]map[string]any - openItemContainers map[byte]*itemContainer - playerInventory []protocol.ItemInstance - entities map[uint64]*entityState - Dim world.Dimension - PlayerPos TPlayerPos - worldCounter int - WorldName string - ServerName string - ispre118 bool - - // settings - voidGen bool - withPacks bool - saveImage bool - experimentInventory bool - blockUpdates bool + worldState worldState + serverState serverState + settings worldSettings } -func NewWorldState(ctx context.Context, proxy *utils.ProxyContext, ServerName string, ui utils.UI) *WorldState { - w := &WorldState{ - ctx: ctx, - proxy: proxy, - mapUI: nil, - gui: ui, - bp: behaviourpack.New(ServerName), - ServerName: ServerName, +func NewWorldsServer(ctx context.Context, proxy *utils.ProxyContext, ServerName string, ui utils.UI) *worldsServer { + w := &worldsServer{ + ctx: ctx, + proxy: proxy, + mapUI: nil, + gui: ui, + bp: behaviourpack.New(ServerName), - chunks: make(map[protocol.ChunkPos]*chunk.Chunk), - blockNBT: make(map[protocol.SubChunkPos][]map[string]any), - openItemContainers: make(map[byte]*itemContainer), - entities: make(map[uint64]*entityState), - Dim: nil, - WorldName: "world", - PlayerPos: TPlayerPos{}, + serverState: serverState{ + ispre118: false, + worldCounter: 0, + ChunkRadius: 0, + + playerInventory: nil, + PlayerPos: TPlayerPos{}, + + Name: ServerName, + }, + + settings: worldSettings{}, } w.mapUI = NewMapUI(w) + w.Reset(w.CurrentName()) w.gui.Message(messages.Init, messages.InitPayload{ Handler: w.uiMessage, @@ -118,11 +133,10 @@ func init() { } type WorldCMD struct { - ServerAddress string - Packs bool - EnableVoid bool - SaveImage bool - ExperimentInventory bool + ServerAddress string + Packs bool + EnableVoid bool + SaveImage bool } func (*WorldCMD) Name() string { return "worlds" } @@ -133,7 +147,6 @@ func (c *WorldCMD) SetFlags(f *flag.FlagSet) { f.BoolVar(&c.Packs, "packs", false, locale.Loc("save_packs_with_world", nil)) f.BoolVar(&c.EnableVoid, "void", true, locale.Loc("enable_void", nil)) f.BoolVar(&c.SaveImage, "image", false, locale.Loc("save_image", nil)) - f.BoolVar(&c.ExperimentInventory, "inv", false, locale.Loc("test_block_inv", nil)) } func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error { @@ -147,11 +160,12 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error { return err } - w := NewWorldState(ctx, proxy, hostname, ui) - w.voidGen = c.EnableVoid - w.withPacks = c.Packs - w.saveImage = c.SaveImage - w.experimentInventory = c.ExperimentInventory + w := NewWorldsServer(ctx, proxy, hostname, ui) + w.settings = worldSettings{ + voidGen: c.EnableVoid, + withPacks: c.Packs, + saveImage: c.SaveImage, + } proxy.AlwaysGetPacks = true proxy.GameDataModifier = func(gd *minecraft.GameData) { @@ -172,7 +186,7 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error { // from server switch pk := pk.(type) { case *packet.ChunkRadiusUpdated: - w.ChunkRadius = int(pk.ChunkRadius) + w.serverState.ChunkRadius = int(pk.ChunkRadius) pk.ChunkRadius = 80 } pk = w.processItemPacketsServer(pk) @@ -196,7 +210,7 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error { return nil } -func (w *WorldState) uiMessage(name string, data interface{}) messages.MessageResponse { +func (w *worldsServer) uiMessage(name string, data interface{}) messages.MessageResponse { r := messages.MessageResponse{ Ok: false, Data: nil, @@ -212,24 +226,25 @@ func (w *WorldState) uiMessage(name string, data interface{}) messages.MessageRe return r } -func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) { - last := w.PlayerPos - w.PlayerPos = TPlayerPos{ +func (w *worldsServer) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) { + last := w.serverState.PlayerPos + current := TPlayerPos{ Position: Position, Pitch: Pitch, Yaw: Yaw, HeadYaw: HeadYaw, } + w.serverState.PlayerPos = current - if int(last.Position.X()) != int(w.PlayerPos.Position.X()) || int(last.Position.Z()) != int(w.PlayerPos.Position.Z()) { + if int(last.Position.X()) != int(current.Position.X()) || int(last.Position.Z()) != int(current.Position.Z()) { w.mapUI.SchedRedraw() } } -func (w *WorldState) setVoidGen(val bool, fromUI bool) bool { - w.voidGen = val +func (w *worldsServer) setVoidGen(val bool, fromUI bool) bool { + w.settings.voidGen = val var s string - if w.voidGen { + if w.settings.voidGen { s = locale.Loc("void_generator_true", nil) } else { s = locale.Loc("void_generator_false", nil) @@ -238,68 +253,79 @@ func (w *WorldState) setVoidGen(val bool, fromUI bool) bool { if !fromUI { w.gui.Message(messages.SetVoidGen, messages.SetVoidGenPayload{ - Value: w.voidGen, + Value: w.settings.voidGen, }) } return true } -func (w *WorldState) setWorldName(val string, fromUI bool) bool { - w.WorldName = val - w.proxy.SendMessage(locale.Loc("worldname_set", locale.Strmap{"Name": w.WorldName})) +func (w *worldsServer) setWorldName(val string, fromUI bool) bool { + w.worldState.Name = val + w.proxy.SendMessage(locale.Loc("worldname_set", locale.Strmap{"Name": w.worldState.Name})) if !fromUI { w.gui.Message(messages.SetWorldName, messages.SetWorldNamePayload{ - WorldName: w.WorldName, + WorldName: w.worldState.Name, }) } return true } -func (w *WorldState) Reset() { - w.chunks = make(map[protocol.ChunkPos]*chunk.Chunk) - w.entities = make(map[uint64]*entityState) - w.blockNBT = make(map[protocol.SubChunkPos][]map[string]any) - w.openItemContainers = make(map[byte]*itemContainer) - w.WorldName = fmt.Sprintf("world-%d", w.worldCounter) +func (w *worldsServer) CurrentName() string { + worldName := "world" + if w.serverState.worldCounter > 1 { + worldName = fmt.Sprintf("world-%d", w.serverState.worldCounter) + } + return worldName +} + +func (w *worldsServer) Reset(newName string) { + w.worldState = worldState{ + Dim: nil, + chunks: make(map[protocol.ChunkPos]*chunk.Chunk), + blockNBT: make(map[protocol.SubChunkPos][]map[string]any), + entities: make(map[uint64]*entityState), + openItemContainers: make(map[byte]*itemContainer), + Name: newName, + } w.mapUI.Reset() } // SaveAndReset writes the world to a folder, resets all the chunks -func (w *WorldState) SaveAndReset() { +func (w *worldsServer) SaveAndReset() { // cull empty chunks - keys := make([]protocol.ChunkPos, 0, len(w.chunks)) - for cp := range w.chunks { + keys := make([]protocol.ChunkPos, 0, len(w.worldState.chunks)) + for cp := range w.worldState.chunks { keys = append(keys, cp) } for _, cp := range keys { has_any := false - for _, sc := range w.chunks[cp].Sub() { + for _, sc := range w.worldState.chunks[cp].Sub() { has_any = !sc.Empty() if has_any { break } } if !has_any { - delete(w.chunks, cp) + delete(w.worldState.chunks, cp) } } - if len(w.chunks) == 0 { - w.Reset() + if len(w.worldState.chunks) == 0 { + w.Reset(w.CurrentName()) return } - logrus.Infof(locale.Loc("saving_world", locale.Strmap{"Name": w.WorldName, "Count": len(w.chunks)})) + logrus.Infof(locale.Loc("saving_world", locale.Strmap{"Name": w.worldState.Name, "Count": len(w.worldState.chunks)})) w.gui.Message(messages.SavingWorld, messages.SavingWorldPayload{ - Name: w.WorldName, - Chunks: len(w.chunks), + Name: w.worldState.Name, + Chunks: len(w.worldState.chunks), }) // open world - folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.ServerName, w.WorldName)) + folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.serverState.Name, w.worldState.Name)) os.RemoveAll(folder) os.MkdirAll(folder, 0o777) @@ -309,18 +335,18 @@ func (w *WorldState) SaveAndReset() { } // save chunk data - for cp, c := range w.chunks { - provider.SaveChunk((world.ChunkPos)(cp), c, w.Dim) + for cp, c := range w.worldState.chunks { + provider.SaveChunk((world.ChunkPos)(cp), c, w.worldState.Dim) } // save block nbt data blockNBT := make(map[world.ChunkPos][]map[string]any) - for scp, v := range w.blockNBT { // 3d to 2d + for scp, v := range w.worldState.blockNBT { // 3d to 2d cp := world.ChunkPos{scp.X(), scp.Z()} blockNBT[cp] = append(blockNBT[cp], v...) } for cp, v := range blockNBT { - err = provider.SaveBlockNBT(cp, v, w.Dim) + err = provider.SaveBlockNBT(cp, v, w.worldState.Dim) if err != nil { logrus.Error(err) } @@ -328,30 +354,30 @@ func (w *WorldState) SaveAndReset() { // save entities chunkEntities := make(map[world.ChunkPos][]world.Entity) - for _, es := range w.entities { + for _, es := range w.worldState.entities { cp := world.ChunkPos{int32(es.Position.X()) >> 4, int32(es.Position.Z()) >> 4} chunkEntities[cp] = append(chunkEntities[cp], es.ToServerEntity()) } for cp, v := range chunkEntities { - err = provider.SaveEntities(cp, v, w.Dim) + err = provider.SaveEntities(cp, v, w.worldState.Dim) if err != nil { logrus.Error(err) } } - playerPos := w.proxy.Server.GameData().PlayerPosition - spawnPos := cube.Pos{int(playerPos.X()), int(playerPos.Y()), int(playerPos.Z())} - err = provider.SaveLocalPlayerData(w.playerData()) if err != nil { logrus.Error(err) } + playerPos := w.proxy.Server.GameData().PlayerPosition + spawnPos := cube.Pos{int(playerPos.X()), int(playerPos.Y()), int(playerPos.Z())} + // write metadata s := provider.Settings() s.Spawn = spawnPos - s.Name = w.WorldName + s.Name = w.worldState.Name // set gamerules ld := provider.LevelDat() @@ -427,7 +453,7 @@ func (w *WorldState) SaveAndReset() { ld.RandomSeed = int64(gd.WorldSeed) // void world - if w.voidGen { + if w.settings.voidGen { ld.FlatWorldLayers = `{"biome_id":1,"block_layers":[{"block_data":0,"block_id":0,"count":1},{"block_data":0,"block_id":0,"count":2},{"block_data":0,"block_id":0,"count":1}],"encoding_version":3,"structure_options":null}` ld.Generator = 2 } @@ -446,7 +472,7 @@ func (w *WorldState) SaveAndReset() { logrus.Error(err) } - w.worldCounter += 1 + w.serverState.worldCounter += 1 type dep struct { PackID string `json:"pack_id"` @@ -467,7 +493,7 @@ func (w *WorldState) SaveAndReset() { // save behaviourpack if w.bp.HasContent() { - name := strings.ReplaceAll(w.ServerName, "./", "") + name := strings.ReplaceAll(w.serverState.Name, "./", "") name = strings.ReplaceAll(name, "/", "-") packFolder := path.Join(folder, "behavior_packs", name) os.MkdirAll(packFolder, 0o755) @@ -484,16 +510,16 @@ func (w *WorldState) SaveAndReset() { }}) // force resource packs for worlds with custom blocks - w.withPacks = true + w.settings.withPacks = true } // add resource packs - if w.withPacks { + if w.settings.withPacks { packs, err := utils.GetPacks(w.proxy.Server) if err != nil { logrus.Error(err) } else { - //var rdeps []dep + var rdeps []dep for k, p := range packs { if p.Encrypted() && !p.CanDecrypt() { logrus.Warnf("Cant add %s, it is encrypted", p.Name()) @@ -502,17 +528,14 @@ func (w *WorldState) SaveAndReset() { logrus.Infof(locale.Loc("adding_pack", locale.Strmap{"Name": k})) packFolder := path.Join(folder, "resource_packs", p.Name()) os.MkdirAll(packFolder, 0o755) - data := make([]byte, p.Len()) - p.ReadAt(data, 0) - utils.UnpackZip(bytes.NewReader(data), int64(len(data)), packFolder) + utils.UnpackZip(p, int64(p.Len()), packFolder) - /* - rdeps = append(rdeps, dep{ - PackID: p.Manifest().Header.UUID, - Version: p.Manifest().Header.Version, - }) - */ + rdeps = append(rdeps, dep{ + PackID: p.Manifest().Header.UUID, + Version: p.Manifest().Header.Version, + }) } + _ = rdeps /* if len(rdeps) > 0 { addPacksJSON("world_resource_packs.json", rdeps) @@ -521,7 +544,7 @@ func (w *WorldState) SaveAndReset() { } } - if w.saveImage { + if w.settings.saveImage { f, _ := os.Create(folder + ".png") png.Encode(f, w.mapUI.ToImage()) f.Close() @@ -532,25 +555,27 @@ func (w *WorldState) SaveAndReset() { // zip it filename := folder + ".mcworld" if err := utils.ZipFolder(filename, folder); err != nil { - fmt.Println(err) + logrus.Error(err) } logrus.Info(locale.Loc("saved", locale.Strmap{"Name": filename})) //os.RemoveAll(folder) - w.Reset() + w.Reset(w.CurrentName()) w.gui.Message(messages.SetUIState, messages.UIStateMain) } -func (w *WorldState) OnConnect(err error) bool { +func (w *worldsServer) OnConnect(err error) bool { w.gui.Message(messages.SetUIState, messages.UIStateMain) if err != nil { return false } gd := w.proxy.Server.GameData() - w.ChunkRadius = int(gd.ChunkRadius) + w.serverState.ChunkRadius = int(gd.ChunkRadius) + w.proxy.ClientWritePacket(&packet.ChunkRadiusUpdated{ + ChunkRadius: 80, + }) world.InsertCustomItems(gd.Items) - for _, ie := range gd.Items { w.bp.AddItem(ie) } @@ -576,18 +601,18 @@ func (w *WorldState) OnConnect(err error) bool { if len(gv) > 1 { var ver int ver, err = strconv.Atoi(gv[1]) - w.ispre118 = ver < 18 + w.serverState.ispre118 = ver < 18 } if err != nil || len(gv) <= 1 { logrus.Info(locale.Loc("guessing_version", nil)) } dimensionID := gd.Dimension - if w.ispre118 { + if w.serverState.ispre118 { logrus.Info(locale.Loc("using_under_118", nil)) dimensionID += 10 } - w.Dim = dimensionIDMap[uint8(dimensionID)] + w.worldState.Dim = dimensionIDMap[uint8(dimensionID)] } w.proxy.SendMessage(locale.Loc("use_setname", nil)) @@ -611,7 +636,7 @@ func (w *WorldState) OnConnect(err error) bool { w.proxy.AddCommand(utils.IngameCommand{ Exec: func(cmdline []string) bool { - return w.setVoidGen(!w.voidGen, false) + return w.setVoidGen(!w.settings.voidGen, false) }, Cmd: protocol.Command{ Name: "void", @@ -620,9 +645,5 @@ func (w *WorldState) OnConnect(err error) bool { }) w.mapUI.Start() - - w.proxy.ClientWritePacket(&packet.ChunkRadiusUpdated{ - ChunkRadius: 80, - }) return true } diff --git a/utils/packet_logger.go b/utils/packet_logger.go index 1b8241b..a49a0da 100644 --- a/utils/packet_logger.go +++ b/utils/packet_logger.go @@ -2,7 +2,6 @@ package utils import ( "bytes" - "encoding/json" "fmt" "io" "net" @@ -18,8 +17,6 @@ import ( "golang.org/x/exp/slices" ) -var pool = packet.NewPool() - var MutedPackets = []string{ "packet.UpdateBlock", "packet.MoveActorAbsolute", @@ -49,9 +46,8 @@ var MutedPackets = []string{ } var ( - ExtraVerbose []string - FLog io.Writer - dmpLock sync.Mutex + FLog io.Writer + dmpLock sync.Mutex ) func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s string) { @@ -63,11 +59,14 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri ii := reflect.Indirect(reflect.ValueOf(inputStruct)) typeName := reflect.TypeOf(inputStruct).String() + if typeName == "[]interface {}" { + typeName = "[]any" + } typeString := "" if withType { if slices.Contains([]string{"bool", "string"}, typeName) { } else { - typeString = typeName + " " + typeString = typeName } } @@ -84,7 +83,8 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri return } - if ii.Kind() == reflect.Struct { + switch ii.Kind() { + case reflect.Struct: if ii.NumField() == 0 { s += typeName + "{}" } else { @@ -93,30 +93,24 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri fieldType := ii.Type().Field(i) if fieldType.IsExported() { - field := ii.Field(i).Interface() - d := dmpStruct(level+1, field, true, false) - s += tBase + fmt.Sprintf("\t%s = %s\n", fieldType.Name, d) + s += fmt.Sprintf("%s\t%s: %s,\n", tBase, fieldType.Name, dmpStruct(level+1, ii.Field(i).Interface(), true, false)) } else { s += tBase + " " + fieldType.Name + " (unexported)" } } s += tBase + "}" } - } else if ii.Kind() == reflect.Slice { - var t reflect.Type - is_elem_struct := false - if ii.Len() > 0 { - e := ii.Index(0) - t = reflect.TypeOf(e.Interface()) - is_elem_struct = t.Kind() == reflect.Struct - } + case reflect.Slice: + s += typeName + "{" if ii.Len() > 1000 { - s += "[]" + s += "" } else if ii.Len() == 0 { - s += fmt.Sprintf("[0%s", typeName[1:]) } else { - s += fmt.Sprintf("[%d%s{", ii.Len(), typeString[1:]) + e := ii.Index(0) + t := reflect.TypeOf(e.Interface()) + is_elem_struct := t.Kind() == reflect.Struct + if is_elem_struct { s += "\n" } @@ -124,32 +118,55 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri if is_elem_struct { s += tBase + "\t" } - s += dmpStruct(level+1, ii.Index(i).Interface(), false, true) + s += dmpStruct(level+1, ii.Index(i).Interface(), false, true) + "," if is_elem_struct { s += "\n" } else { - s += " " + if i != ii.Len()-1 { + s += " " + } } } if is_elem_struct { s += tBase } - s += "]" } - } else if ii.Kind() == reflect.Map { - j, err := json.MarshalIndent(ii.Interface(), tBase, "\t") - if err != nil { - s += err.Error() + s += "}" + case reflect.Map: + it := reflect.TypeOf(inputStruct) + valType := it.Elem().String() + if valType == "interface {}" { + valType = "any" } - s += string(j) - } else { + keyType := it.Key().String() + + s += fmt.Sprintf("map[%s]%s{", keyType, valType) + if ii.Len() > 0 { + s += "\n" + } + + iter := ii.MapRange() + for iter.Next() { + k := iter.Key() + v := iter.Value() + s += fmt.Sprintf("%s\t%#v: %s,\n", tBase, k.Interface(), dmpStruct(level+1, v.Interface(), true, false)) + } + + if ii.Len() > 0 { + s += tBase + } + s += "}" + default: is_array := ii.Kind() == reflect.Array - if !isInList && !is_array { - s += typeString + add_type := !isInList && !is_array && len(typeString) > 0 + if add_type { + s += typeString + "(" } s += fmt.Sprintf("%#v", ii.Interface()) + if add_type { + s += ")" + } } - return s } @@ -163,17 +180,18 @@ func DumpStruct(data interface{}) { } var ClientAddr net.Addr +var pool = packet.NewPool() func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) { + if header.PacketID == packet.IDRequestNetworkSettings { + ClientAddr = src + } + var pk packet.Packet if pkFunc, ok := pool[header.PacketID]; ok { pk = pkFunc() } else { - pk = &packet.Unknown{PacketID: header.PacketID} - } - - if pk.ID() == packet.IDRequestNetworkSettings { - ClientAddr = src + pk = &packet.Unknown{PacketID: header.PacketID, Payload: payload} } defer func() { @@ -186,9 +204,8 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) { if FLog != nil { dmpLock.Lock() - defer dmpLock.Unlock() - FLog.Write([]byte(dmpStruct(0, pk, true, false))) - FLog.Write([]byte("\n\n\n")) + FLog.Write([]byte(dmpStruct(0, pk, true, false) + "\n\n\n")) + dmpLock.Unlock() } pkName := reflect.TypeOf(pk).String()[1:] @@ -217,8 +234,4 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) { } logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName) - - if slices.Contains(ExtraVerbose, pkName) { - logrus.Debugf("%+v", pk) - } } diff --git a/utils/utils.go b/utils/utils.go index bdd7ab6..9cf90c6 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -2,6 +2,7 @@ package utils import ( + "bufio" "bytes" "context" "crypto/aes" @@ -207,11 +208,6 @@ func InitExtraDebug(ctx context.Context) { logPlain, err := os.Create("packets.log") if err != nil { logrus.Error(err) - } else { - go func() { - <-ctx.Done() - logPlain.Close() - }() } // open gpg log @@ -219,24 +215,30 @@ func InitExtraDebug(ctx context.Context) { if err != nil { logrus.Error(err) } else { - go func() { - <-ctx.Done() - logCrypt.Close() - }() // encrypter for the log logCryptEnc, err = crypt.Encer("packets.log", logCrypt) if err != nil { logrus.Error(err) - } else { - go func() { - <-ctx.Done() - logCryptEnc.Close() - }() } } - FLog = io.MultiWriter(logPlain, logCryptEnc) + b := bufio.NewWriter(io.MultiWriter(logPlain, logCryptEnc)) + FLog = b if err != nil { logrus.Error(err) } + go func() { + <-ctx.Done() + b.Flush() + + if logPlain != nil { + logPlain.Close() + } + if logCrypt != nil { + logCrypt.Close() + } + if logCryptEnc != nil { + logCryptEnc.Close() + } + }() } diff --git a/utils/zip.go b/utils/zip.go index e33ee52..c771665 100644 --- a/utils/zip.go +++ b/utils/zip.go @@ -2,6 +2,7 @@ package utils import ( "archive/zip" + "compress/flate" "io" "io/fs" "os" @@ -36,6 +37,12 @@ func ZipFolder(filename, folder string) error { logrus.Fatal(err) } zw := zip.NewWriter(f) + + // Register a custom Deflate compressor. + zw.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) { + return flate.NewWriter(out, flate.NoCompression) + }) + err = filepath.WalkDir(folder, func(path string, d fs.DirEntry, err error) error { if !d.Type().IsDir() { rel := path[len(folder)+1:]