From 3a5a13aa750024d1aa8f2b3f088dc88efe53338c Mon Sep 17 00:00:00 2001 From: olebeck <31539311+olebeck@users.noreply.github.com> Date: Sun, 29 Jan 2023 21:20:13 +0000 Subject: [PATCH] code formatting --- cmd/bedrocktool/main.go | 56 ++++++++-------- subcommands/capture.go | 29 ++++---- subcommands/debug.go | 2 +- subcommands/merge.go | 56 ++++++++-------- subcommands/update.go | 1 + subcommands/world/chunk.go | 32 ++++----- subcommands/world/chunk_render.go | 14 ++-- subcommands/world/chunk_test.go | 7 +- subcommands/world/entity.go | 68 +++++++++++++++---- subcommands/world/items.go | 18 ++--- subcommands/world/map_item.go | 70 +++++++++---------- subcommands/world/world.go | 107 ++++++++++++++---------------- utils/auth.go | 40 +++++------ utils/behaviourpack/bp.go | 4 +- utils/behaviourpack/entity.go | 2 +- utils/dns.go | 8 +-- utils/images.go | 18 ++--- utils/input.go | 16 ++--- utils/net.go | 2 +- utils/packet_logger.go | 70 +++++++++---------- utils/proxy.go | 28 ++++---- utils/realms.go | 8 +-- utils/replay.go | 24 +++---- utils/resourcepack-ace.go | Bin 6501 -> 6450 bytes utils/utils.go | 48 +++++++------- utils/zip.go | 18 ++--- 26 files changed, 394 insertions(+), 352 deletions(-) diff --git a/cmd/bedrocktool/main.go b/cmd/bedrocktool/main.go index 5136697..d6fc810 100644 --- a/cmd/bedrocktool/main.go +++ b/cmd/bedrocktool/main.go @@ -25,7 +25,7 @@ import ( ) func main() { - var extra_debug bool + var extraDebug bool defer func() { if err := recover(); err != nil { logrus.Errorf(locale.Loc("fatal_error", nil)) @@ -38,10 +38,10 @@ func main() { println("--END COPY HERE--") println("") println(locale.Loc("report_issue", nil)) - if extra_debug { + if extraDebug { println(locale.Loc("used_extra_debug_report", nil)) } - if utils.G_interactive { + if utils.GInteractive { input := bufio.NewScanner(os.Stdin) input.Scan() } @@ -65,11 +65,11 @@ func main() { ctx, cancel := context.WithCancel(context.Background()) - flag.BoolVar(&utils.G_debug, "debug", false, locale.Loc("debug_mode", nil)) - flag.BoolVar(&utils.G_preload_packs, "preload", false, locale.Loc("preload_packs", nil)) - flag.BoolVar(&extra_debug, "extra-debug", false, locale.Loc("extra_debug", nil)) + flag.BoolVar(&utils.GDebug, "debug", false, locale.Loc("debug_mode", nil)) + flag.BoolVar(&utils.GPreloadPacks, "preload", false, locale.Loc("preload_packs", nil)) + flag.BoolVar(&extraDebug, "extra-debug", false, locale.Loc("extra_debug", nil)) flag.String("lang", "", "lang") - enable_dns := flag.Bool("dns", false, locale.Loc("enable_dns", nil)) + enableDNS := flag.Bool("dns", false, locale.Loc("enable_dns", nil)) subcommands.Register(subcommands.HelpCommand(), "") subcommands.ImportantFlag("debug") @@ -89,52 +89,52 @@ func main() { } fmt.Println(locale.Loc("use_to_run_command", nil)) - cmd, cancelled := utils.User_input(ctx, locale.Loc("input_command", nil)) + cmd, cancelled := utils.UserInput(ctx, locale.Loc("input_command", nil)) if cancelled { return } _cmd := strings.Split(cmd, " ") os.Args = append(os.Args, _cmd...) - utils.G_interactive = true + utils.GInteractive = true } } } flag.Parse() - if *enable_dns { + if *enableDNS { utils.InitDNS() } - if extra_debug { - utils.G_debug = true + if extraDebug { + utils.GDebug = true - var log_plain, log_crypt_enc io.WriteCloser = nil, nil + var logPlain, logCryptEnc io.WriteCloser = nil, nil // open plain text log - log_plain, err = os.Create("packets.log") + logPlain, err = os.Create("packets.log") if err != nil { logrus.Error(err) } else { - defer log_plain.Close() + defer logPlain.Close() } // open gpg log - log_crypt, err := os.Create("packets.log.gpg") + logCrypt, err := os.Create("packets.log.gpg") if err != nil { logrus.Error(err) } else { - defer log_crypt.Close() + defer logCrypt.Close() // encrypter for the log - log_crypt_enc, err = crypt.Encer("packets.log", log_crypt) + logCryptEnc, err = crypt.Encer("packets.log", logCrypt) if err != nil { logrus.Error(err) } else { - defer log_crypt_enc.Close() + defer logCryptEnc.Close() } } - utils.F_Log = io.MultiWriter(log_plain, log_crypt_enc) + utils.FLog = io.MultiWriter(logPlain, logCryptEnc) if err != nil { logrus.Error(err) } @@ -151,7 +151,7 @@ func main() { subcommands.Execute(ctx) - if utils.G_interactive { + if utils.GInteractive { logrus.Info(locale.Loc("enter_to_exit", nil)) input := bufio.NewScanner(os.Stdin) input.Scan() @@ -175,17 +175,17 @@ func (c *TransCMD) Usage() string { func (c *TransCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { const ( - BLACK_FG = "\033[30m" - BOLD = "\033[1m" - BLUE = "\033[46m" - PINK = "\033[45m" - WHITE = "\033[47m" - RESET = "\033[0m" + BlackFg = "\033[30m" + Bold = "\033[1m" + Blue = "\033[46m" + Pink = "\033[45m" + White = "\033[47m" + Reset = "\033[0m" ) if c.auth { utils.GetTokenSource() } - fmt.Println(BLACK_FG + BOLD + BLUE + " Trans " + PINK + " Rights " + WHITE + " Are " + PINK + " Human " + BLUE + " Rights " + RESET) + fmt.Println(BlackFg + Bold + Blue + " Trans " + Pink + " Rights " + White + " Are " + Pink + " Human " + Blue + " Rights " + Reset) return 0 } diff --git a/subcommands/capture.go b/subcommands/capture.go index a38a4d1..75f972f 100644 --- a/subcommands/capture.go +++ b/subcommands/capture.go @@ -23,31 +23,34 @@ func init() { utils.RegisterCommand(&CaptureCMD{}) } -var dump_lock sync.Mutex +var dumpLock sync.Mutex -func dump_packet(f io.WriteCloser, toServer bool, payload []byte) { - dump_lock.Lock() - defer dump_lock.Unlock() +func dumpPacket(f io.WriteCloser, toServer bool, payload []byte) { + dumpLock.Lock() + defer dumpLock.Unlock() f.Write([]byte{0xAA, 0xAA, 0xAA, 0xAA}) - packet_size := uint32(len(payload)) - binary.Write(f, binary.LittleEndian, packet_size) + packetSize := uint32(len(payload)) + binary.Write(f, binary.LittleEndian, packetSize) binary.Write(f, binary.LittleEndian, toServer) - _, err := f.Write(payload) + n, err := f.Write(payload) if err != nil { logrus.Error(err) } + if n < int(packetSize) { + f.Write(make([]byte, int(packetSize)-n)) + } f.Write([]byte{0xBB, 0xBB, 0xBB, 0xBB}) } type CaptureCMD struct { - server_address string + serverAddress string } func (*CaptureCMD) Name() string { return "capture" } func (*CaptureCMD) Synopsis() string { return locale.Loc("capture_synopsis", nil) } -func (p *CaptureCMD) SetFlags(f *flag.FlagSet) { - f.StringVar(&p.server_address, "address", "", "remote server address") +func (c *CaptureCMD) SetFlags(f *flag.FlagSet) { + f.StringVar(&c.serverAddress, "address", "", "remote server address") } func (c *CaptureCMD) Usage() string { @@ -55,7 +58,7 @@ func (c *CaptureCMD) Usage() string { } func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - address, hostname, err := utils.ServerInput(ctx, c.server_address) + address, hostname, err := utils.ServerInput(ctx, c.serverAddress) if err != nil { logrus.Fatal(err) return 1 @@ -72,12 +75,12 @@ func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interfac proxy := utils.NewProxy() proxy.PacketFunc = func(header packet.Header, payload []byte, src, dst net.Addr) { - from_client := dst.String() == proxy.Server.RemoteAddr().String() + IsfromClient := dst.String() == proxy.Server.RemoteAddr().String() buf := bytes.NewBuffer(nil) header.Write(buf) buf.Write(payload) - dump_packet(fio, from_client, buf.Bytes()) + dumpPacket(fio, IsfromClient, buf.Bytes()) } err = proxy.Run(ctx, address) diff --git a/subcommands/debug.go b/subcommands/debug.go index b3426b0..22c07b7 100644 --- a/subcommands/debug.go +++ b/subcommands/debug.go @@ -36,7 +36,7 @@ func (c *DebugProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...inter return 1 } - utils.G_debug = true + utils.GDebug = true filters := strings.Split(c.filter, ",") if len(filters) > 0 { diff --git a/subcommands/merge.go b/subcommands/merge.go index 853ce21..fb9bd44 100644 --- a/subcommands/merge.go +++ b/subcommands/merge.go @@ -40,87 +40,87 @@ func (c *MergeCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ return 1 } c.worlds = f.Args() - out_name := c.worlds[0] + "-merged" + outName := c.worlds[0] + "-merged" - prov_out, err := mcdb.New(logrus.StandardLogger(), out_name, opt.DefaultCompression) + provOut, err := mcdb.New(logrus.StandardLogger(), outName, opt.DefaultCompression) if err != nil { logrus.Errorf(locale.Loc("failed_to_open_output", locale.Strmap{"Err": err})) return 1 } - for i, world_name := range c.worlds { + for i, worldName := range c.worlds { first := i == 0 - logrus.Infof(locale.Loc("adding_world", locale.Strmap{"World": world_name})) - s, err := os.Stat(world_name) + logrus.Infof(locale.Loc("adding_world", locale.Strmap{"World": worldName})) + s, err := os.Stat(worldName) if errors.Is(err, os.ErrNotExist) { - logrus.Fatalf(locale.Loc("not_found", locale.Strmap{"Name": world_name}), world_name) + logrus.Fatalf(locale.Loc("not_found", locale.Strmap{"Name": worldName}), worldName) } if !s.IsDir() { // if its a zip temporarily unpack it to read it - f, _ := os.Open(world_name) - world_name += "_unpack" - utils.UnpackZip(f, s.Size(), world_name) + f, _ := os.Open(worldName) + worldName += "_unpack" + utils.UnpackZip(f, s.Size(), worldName) } // merge it into the state - err = c.merge_worlds(prov_out, world_name, first) + err = c.mergeWorlds(provOut, worldName, first) if err != nil { - logrus.Errorf("%s %s", world_name, err) + logrus.Errorf("%s %s", worldName, err) return 1 } if !s.IsDir() { // remove temp folder again - os.RemoveAll(world_name) + os.RemoveAll(worldName) } } - if err = prov_out.Close(); err != nil { + if err = provOut.Close(); err != nil { logrus.Error(err) return 1 } time.Sleep(1 * time.Second) - if err := utils.ZipFolder(out_name+".mcworld", out_name); err != nil { + if err := utils.ZipFolder(outName+".mcworld", outName); err != nil { logrus.Infof("zipping: %s", err) return 1 } - os.RemoveAll(out_name) + os.RemoveAll(outName) return 0 } -func (c *MergeCMD) merge_worlds(prov_out *mcdb.Provider, folder string, first bool) error { - prov_in, err := mcdb.New(logrus.StandardLogger(), folder, opt.DefaultCompression) +func (c *MergeCMD) mergeWorlds(provOut *mcdb.Provider, folder string, first bool) error { + provIn, err := mcdb.New(logrus.StandardLogger(), folder, opt.DefaultCompression) if err != nil { return err } count := 0 - existing := prov_out.Chunks(c.legacy) - new := prov_in.Chunks(c.legacy) + existing := provOut.Chunks(c.legacy) + new := provIn.Chunks(c.legacy) for i := range new { if _, ok := existing[i]; !ok { d := i.D // chunks - ch, _, err := prov_in.LoadChunk(i.P, d) + ch, _, err := provIn.LoadChunk(i.P, d) if err != nil { return err } - if err := prov_out.SaveChunk(i.P, ch, i.D); err != nil { + if err := provOut.SaveChunk(i.P, ch, i.D); err != nil { return err } // blockNBT - n, err := prov_in.LoadBlockNBT(i.P, i.D) + n, err := provIn.LoadBlockNBT(i.P, i.D) if err != nil { return err } - if err := prov_out.SaveBlockNBT(i.P, n, i.D); err != nil { + if err := provOut.SaveBlockNBT(i.P, n, i.D); err != nil { return err } // entities - entities, err := prov_in.LoadEntities(i.P, i.D, entity.DefaultRegistry) + entities, err := provIn.LoadEntities(i.P, i.D, entity.DefaultRegistry) if err != nil { return err } - if err := prov_out.SaveEntities(i.P, entities, i.D); err != nil { + if err := provOut.SaveEntities(i.P, entities, i.D); err != nil { return err } count += 1 @@ -129,9 +129,9 @@ func (c *MergeCMD) merge_worlds(prov_out *mcdb.Provider, folder string, first bo if first { logrus.Debug("Applying Settings and level.dat") - prov_out.SaveSettings(prov_in.Settings()) - out_ld := prov_out.LevelDat() - copier.Copy(out_ld, prov_in.LevelDat()) + provOut.SaveSettings(provIn.Settings()) + outLd := provOut.LevelDat() + copier.Copy(outLd, provIn.LevelDat()) } logrus.Infof("Added: %d", count) return nil diff --git a/subcommands/update.go b/subcommands/update.go index c369bc6..1af4d3b 100644 --- a/subcommands/update.go +++ b/subcommands/update.go @@ -1,3 +1,4 @@ +// Package subcommands ... package subcommands import ( diff --git a/subcommands/world/chunk.go b/subcommands/world/chunk.go index 652e835..9c3314e 100644 --- a/subcommands/world/chunk.go +++ b/subcommands/world/chunk.go @@ -16,11 +16,11 @@ func (w *WorldState) processChangeDimension(pk *packet.ChangeDimension) { logrus.Info(locale.Loc("not_saving_empty", nil)) w.Reset() } - dim_id := pk.Dimension + dimensionID := pk.Dimension if w.ispre118 { - dim_id += 10 + dimensionID += 10 } - w.Dim = dimension_ids[uint8(dim_id)] + w.Dim = dimensionIDMap[uint8(dimensionID)] } func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) { @@ -58,40 +58,40 @@ func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) { Position: protocol.SubChunkPos{ pk.Position.X(), 0, pk.Position.Z(), }, - Offsets: Offset_table[:max], + Offsets: offsetTable[:max], }) } } func (w *WorldState) processSubChunk(pk *packet.SubChunk) { - pos_to_redraw := make(map[protocol.ChunkPos]bool) + posToRedraw := make(map[protocol.ChunkPos]bool) for _, sub := range pk.SubChunkEntries { var ( - abs_x = pk.Position[0] + int32(sub.Offset[0]) - abs_y = pk.Position[1] + int32(sub.Offset[1]) - abs_z = pk.Position[2] + int32(sub.Offset[2]) - subpos = protocol.SubChunkPos{abs_x, abs_y, abs_z} - pos = protocol.ChunkPos{abs_x, abs_z} + 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 := w.chunks[pos] - if ch == nil { + ch, ok := w.chunks[pos] + if !ok { logrus.Error(locale.Loc("subchunk_before_chunk", nil)) continue } - blockNBT, err := ch.ApplySubChunkEntry(uint8(abs_y), &sub) + blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub) if err != nil { logrus.Error(err) } if blockNBT != nil { - w.blockNBT[subpos] = blockNBT + w.blockNBT[subPos] = blockNBT } - pos_to_redraw[pos] = true + posToRedraw[pos] = true } // redraw the chunks - for pos := range pos_to_redraw { + for pos := range posToRedraw { w.ui.SetChunk(pos, w.chunks[pos]) } w.ui.SchedRedraw() diff --git a/subcommands/world/chunk_render.go b/subcommands/world/chunk_render.go index fa1265a..c1b22cb 100644 --- a/subcommands/world/chunk_render.go +++ b/subcommands/world/chunk_render.go @@ -50,18 +50,18 @@ func blockColorAt(c *chunk.Chunk, x uint8, y int16, z uint8) (blockColor color.R func chunkGetColorAt(c *chunk.Chunk, x uint8, y int16, z uint8) color.RGBA { p := cube.Pos{int(x), int(y), int(z)} - have_up := false + haveUp := false p.Side(cube.FaceUp).Neighbours(func(neighbour cube.Pos) { if neighbour.X() < 0 || neighbour.X() >= 16 || neighbour.Z() < 0 || neighbour.Z() >= 16 || neighbour.Y() > c.Range().Max() { return } - if !have_up { - block_rid := c.Block(uint8(neighbour[0]), int16(neighbour[1]), uint8(neighbour[2]), 0) - if block_rid > 0 { - b, found := world.BlockByRuntimeID(block_rid) + if !haveUp { + blockRid := c.Block(uint8(neighbour[0]), int16(neighbour[1]), uint8(neighbour[2]), 0) + if blockRid > 0 { + b, found := world.BlockByRuntimeID(blockRid) if found { if _, ok := b.(block.Air); !ok { - have_up = true + haveUp = true } } } @@ -70,7 +70,7 @@ func chunkGetColorAt(c *chunk.Chunk, x uint8, y int16, z uint8) color.RGBA { col := blockColorAt(c, x, y, z) - if have_up { + if haveUp { if col.R > 10 { col.R -= 10 } diff --git a/subcommands/world/chunk_test.go b/subcommands/world/chunk_test.go index 0e9252e..b846d3c 100644 --- a/subcommands/world/chunk_test.go +++ b/subcommands/world/chunk_test.go @@ -1,10 +1,11 @@ -package world +package world_test import ( "image/png" "os" "testing" + "github.com/bedrock-tool/bedrocktool/subcommands/world" "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/world/chunk" ) @@ -12,7 +13,7 @@ import ( func Test(t *testing.T) { data, _ := os.ReadFile("chunk.bin") ch, _, _ := chunk.NetworkDecode(33, data, 6, cube.Range{0, 255}, true, false) - i := Chunk2Img(ch) + i := world.Chunk2Img(ch) f, _ := os.Create("chunk.png") png.Encode(f, i) f.Close() @@ -33,6 +34,6 @@ func Benchmark_render_chunk(b *testing.B) { ch, _, _ := chunk.NetworkDecode(33, data, 6, cube.Range{0, 255}, true, false) for i := 0; i < b.N; i++ { - Chunk2Img(ch) + world.Chunk2Img(ch) } } diff --git a/subcommands/world/entity.go b/subcommands/world/entity.go index 2a22d88..266cb8f 100644 --- a/subcommands/world/entity.go +++ b/subcommands/world/entity.go @@ -5,12 +5,13 @@ import ( "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/world" "github.com/go-gl/mathgl/mgl32" + "github.com/sandertv/gophertunnel/minecraft/protocol" "github.com/sandertv/gophertunnel/minecraft/protocol/packet" ) type entityState struct { - RuntimeId uint64 - UniqueId int64 + RuntimeID uint64 + UniqueID int64 EntityType string Position mgl32.Vec3 @@ -18,12 +19,7 @@ type entityState struct { HeadYaw, BodyYaw float32 Velocity mgl32.Vec3 - Metadata map[uint32]any -} - -type serverEntity struct { - world.Entity - EntityType serverEntityType + Metadata protocol.EntityMetadata } type serverEntityType struct { @@ -36,16 +32,21 @@ func (t serverEntityType) EncodeEntity() string { return t.Encoded } +func (t serverEntityType) BBox(e world.Entity) cube.BBox { + return cube.Box(-0.5, 0, -0.5, 0.5, 1, 0.5) +} + func (t serverEntityType) DecodeNBT(m map[string]any) world.Entity { return nil // not implemented, and never should } -func (t serverEntityType) EncodeNBT(e *serverEntity) map[string]any { +func (t serverEntityType) EncodeNBT(e world.Entity) map[string]any { return t.NBT } -func (t serverEntityType) BBox(e world.Entity) cube.BBox { - return cube.Box(0, 0, 0, 1, 1, 1) +type serverEntity struct { + world.Entity + EntityType serverEntityType } func (e serverEntity) Type() world.EntityType { @@ -56,8 +57,8 @@ func (w *WorldState) processAddActor(pk *packet.AddActor) { e, ok := w.entities[pk.EntityRuntimeID] if !ok { e = &entityState{ - RuntimeId: pk.EntityRuntimeID, - UniqueId: pk.EntityUniqueID, + RuntimeID: pk.EntityRuntimeID, + UniqueID: pk.EntityUniqueID, EntityType: pk.EntityType, Metadata: make(map[uint32]any), } @@ -81,6 +82,47 @@ func (w *WorldState) processAddActor(pk *packet.AddActor) { } } +func entityMetadataToNBT(metadata protocol.EntityMetadata, nbt map[string]any) { + if variant, ok := metadata[protocol.EntityDataKeyVariant].(int32); ok { + block, ok := world.BlockByRuntimeID(uint32(variant)) + if ok { + nbt["name"], _ = block.EncodeBlock() + } + } + if name, ok := metadata[protocol.EntityDataKeyName].(string); ok { + nbt["CustomName"] = name + } + if ShowNameTag, ok := metadata[protocol.EntityDataKeyAlwaysShowNameTag].(uint8); ok { + if ShowNameTag != 0 { + nbt["CustomNameVisible"] = true + } else { + nbt["CustomNameVisible"] = false + } + } + if scale, ok := metadata[protocol.EntityDataKeyScale].(float32); ok { + nbt["Scale"] = scale + } +} + +func vec3float32(x mgl32.Vec3) []float32 { + return []float32{float32(x[0]), float32(x[1]), float32(x[2])} +} + +func (s *entityState) ToServerEntity() serverEntity { + e := serverEntity{ + EntityType: serverEntityType{ + Encoded: s.EntityType, + NBT: map[string]any{ + "Pos": vec3float32(s.Position), + "Rotation": []float32{s.Yaw, s.Pitch}, + "Motion": vec3float32(s.Velocity), + }, + }, + } + entityMetadataToNBT(s.Metadata, e.EntityType.NBT) + return e +} + func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet { switch pk := pk.(type) { case *packet.AddActor: diff --git a/subcommands/world/items.go b/subcommands/world/items.go index be2c1b6..27ed1d7 100644 --- a/subcommands/world/items.go +++ b/subcommands/world/items.go @@ -77,8 +77,8 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet { // put into subchunk nbts := w.blockNBT[cp] for i, v := range nbts { - nbt_pos := protocol.BlockPos{v["x"].(int32), v["y"].(int32), v["z"].(int32)} - if nbt_pos == pos { + NBTPos := protocol.BlockPos{v["x"].(int32), v["y"].(int32), v["z"].(int32)} + if NBTPos == pos { w.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv) } } @@ -102,32 +102,32 @@ func (w *WorldState) processItemPacketsClient(pk packet.Packet, forward *bool) p for _, isr := range pk.Requests { for _, sra := range isr.Actions { if sra, ok := sra.(*protocol.TakeStackRequestAction); ok { - if sra.Source.StackNetworkID == MAP_ITEM_PACKET.Content[0].StackNetworkID { + if sra.Source.StackNetworkID == MapItemPacket.Content[0].StackNetworkID { continue } } if sra, ok := sra.(*protocol.DropStackRequestAction); ok { - if sra.Source.StackNetworkID == MAP_ITEM_PACKET.Content[0].StackNetworkID { + if sra.Source.StackNetworkID == MapItemPacket.Content[0].StackNetworkID { continue } } if sra, ok := sra.(*protocol.DestroyStackRequestAction); ok { - if sra.Source.StackNetworkID == MAP_ITEM_PACKET.Content[0].StackNetworkID { + if sra.Source.StackNetworkID == MapItemPacket.Content[0].StackNetworkID { continue } } if sra, ok := sra.(*protocol.PlaceInContainerStackRequestAction); ok { - if sra.Source.StackNetworkID == MAP_ITEM_PACKET.Content[0].StackNetworkID { + if sra.Source.StackNetworkID == MapItemPacket.Content[0].StackNetworkID { continue } } if sra, ok := sra.(*protocol.TakeOutContainerStackRequestAction); ok { - if sra.Source.StackNetworkID == MAP_ITEM_PACKET.Content[0].StackNetworkID { + if sra.Source.StackNetworkID == MapItemPacket.Content[0].StackNetworkID { continue } } if sra, ok := sra.(*protocol.DestroyStackRequestAction); ok { - if sra.Source.StackNetworkID == MAP_ITEM_PACKET.Content[0].StackNetworkID { + if sra.Source.StackNetworkID == MapItemPacket.Content[0].StackNetworkID { continue } } @@ -136,7 +136,7 @@ func (w *WorldState) processItemPacketsClient(pk packet.Packet, forward *bool) p } pk.Requests = requests case *packet.MobEquipment: - if pk.NewItem.Stack.NBTData["map_uuid"] == int64(VIEW_MAP_ID) { + if pk.NewItem.Stack.NBTData["map_uuid"] == int64(ViewMapID) { *forward = false } } diff --git a/subcommands/world/map_item.go b/subcommands/world/map_item.go index d861daf..80e4e98 100644 --- a/subcommands/world/map_item.go +++ b/subcommands/world/map_item.go @@ -18,10 +18,10 @@ import ( "golang.org/x/image/bmp" ) -const VIEW_MAP_ID = 0x424242 +const ViewMapID = 0x424242 -// packet to tell the client that it has a map with id 0x424242 in the offhand -var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{ +// MapItemPacket tells the client that it has a map with id 0x424242 in the offhand +var MapItemPacket packet.InventoryContent = packet.InventoryContent{ WindowID: 119, Content: []protocol.ItemInstance{ { @@ -34,14 +34,14 @@ var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{ BlockRuntimeID: 0, Count: 1, NBTData: map[string]interface{}{ - "map_uuid": int64(VIEW_MAP_ID), + "map_uuid": int64(ViewMapID), }, }, }, }, } -func (m *MapUI) get_bounds() (min, max protocol.ChunkPos) { +func (m *MapUI) getBounds() (min, max protocol.ChunkPos) { // get the chunk coord bounds for _ch := range m.renderedChunks { if _ch.X() < min.X() { @@ -98,7 +98,7 @@ func (m *MapUI) Start() { if m.w.proxy.Client != nil { if err := m.w.proxy.Client.WritePacket(&packet.ClientBoundMapItemData{ - MapID: VIEW_MAP_ID, + MapID: ViewMapID, Width: 128, Height: 128, Pixels: utils.Img2rgba(m.img), @@ -118,7 +118,7 @@ func (m *MapUI) Start() { return } if m.w.proxy.Client != nil { - err := m.w.proxy.Client.WritePacket(&MAP_ITEM_PACKET) + err := m.w.proxy.Client.WritePacket(&MapItemPacket) if err != nil { logrus.Error(err) return @@ -154,7 +154,7 @@ func (m *MapUI) SchedRedraw() { m.needRedraw = true } -// draw chunk images to the map image +// Redraw draws chunk images to the map image func (m *MapUI) Redraw() { for { r, ok := m.renderQueue.Dequeue().(*RenderElem) @@ -164,7 +164,7 @@ func (m *MapUI) Redraw() { if r.ch != nil { m.renderedChunks[r.pos] = Chunk2Img(r.ch) } else { - m.renderedChunks[r.pos] = black_16x16 + m.renderedChunks[r.pos] = black16x16 } } @@ -174,30 +174,30 @@ func (m *MapUI) Redraw() { } // total_width := 32 * math.Ceil(float64(chunks_x)/32) - chunks_per_line := float64(128 / m.zoomLevel) - px_per_block := 128 / chunks_per_line / 16 // how many pixels per block - sz_chunk := int(math.Floor(px_per_block * 16)) + chunksPerLine := float64(128 / m.zoomLevel) + pxPerBlock := 128 / chunksPerLine / 16 // how many pixels per block + pxSizeChunk := int(math.Floor(pxPerBlock * 16)) for i := 0; i < len(m.img.Pix); i++ { // clear canvas m.img.Pix[i] = 0 } for _ch := range m.renderedChunks { - relative_middle_x := float64(_ch.X()*16 - middle.X()) - relative_middle_z := float64(_ch.Z()*16 - middle.Z()) - px_pos := image.Point{ // bottom left corner of the chunk on the map - X: int(math.Floor(relative_middle_x*px_per_block)) + 64, - Y: int(math.Floor(relative_middle_z*px_per_block)) + 64, + relativeMiddleX := float64(_ch.X()*16 - middle.X()) + relativeMiddleZ := float64(_ch.Z()*16 - middle.Z()) + px := image.Point{ // bottom left corner of the chunk on the map + X: int(math.Floor(relativeMiddleX*pxPerBlock)) + 64, + Y: int(math.Floor(relativeMiddleZ*pxPerBlock)) + 64, } - if !m.img.Rect.Intersect(image.Rect(px_pos.X, px_pos.Y, px_pos.X+sz_chunk, px_pos.Y+sz_chunk)).Empty() { - utils.Draw_img_scaled_pos(m.img, m.renderedChunks[_ch], px_pos, sz_chunk) + if !m.img.Rect.Intersect(image.Rect(px.X, px.Y, px.X+pxSizeChunk, px.Y+pxSizeChunk)).Empty() { + utils.DrawImgScaledPos(m.img, m.renderedChunks[_ch], px, pxSizeChunk) } } - draw_full := false + drawFull := false - if draw_full { + if drawFull { img2 := m.ToImage() buf := bytes.NewBuffer(nil) bmp.Encode(buf, img2) @@ -207,25 +207,25 @@ func (m *MapUI) Redraw() { func (m *MapUI) ToImage() *image.RGBA { // get the chunk coord bounds - min, max := m.get_bounds() - chunks_x := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate - chunks_y := int(max[1] - min[1] + 1) + min, max := m.getBounds() + chunksX := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate + chunksY := int(max[1] - min[1] + 1) - img2 := image.NewRGBA(image.Rect(0, 0, chunks_x*16, chunks_y*16)) + img2 := image.NewRGBA(image.Rect(0, 0, chunksX*16, chunksY*16)) - middle_block_x := chunks_x / 2 * 16 - middle_block_y := chunks_y / 2 * 16 + middleBlockX := chunksX / 2 * 16 + middleBlockY := chunksY / 2 * 16 for pos := range m.renderedChunks { - px_pos := image.Point{ - X: int(pos.X()*16) - middle_block_x + img2.Rect.Dx(), - Y: int(pos.Z()*16) - middle_block_y + img2.Rect.Dy(), + px := image.Point{ + X: int(pos.X()*16) - middleBlockX + img2.Rect.Dx(), + Y: int(pos.Z()*16) - middleBlockY + img2.Rect.Dy(), } draw.Draw(img2, image.Rect( - px_pos.X, - px_pos.Y, - px_pos.X+16, - px_pos.Y+16, + px.X, + px.Y, + px.X+16, + px.Y+16, ), m.renderedChunks[pos], image.Point{}, draw.Src) } return img2 @@ -243,7 +243,7 @@ func (w *WorldState) processMapPacketsClient(pk packet.Packet, forward *bool) pa case *packet.PlayerAuthInput: w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw) case *packet.MapInfoRequest: - if pk.MapID == VIEW_MAP_ID { + if pk.MapID == ViewMapID { w.ui.SchedRedraw() *forward = false } diff --git a/subcommands/world/world.go b/subcommands/world/world.go index 639a52e..a71dc54 100644 --- a/subcommands/world/world.go +++ b/subcommands/world/world.go @@ -1,3 +1,4 @@ +// Package world Bedrock World Downloader package world import ( @@ -40,29 +41,28 @@ type TPlayerPos struct { // the state used for drawing and saving type WorldState struct { - ctx context.Context - ispre118 bool - voidgen bool + ctx context.Context + proxy *utils.ProxyContext + ui *MapUI + bp *behaviourpack.BehaviourPack + + // save state chunks map[protocol.ChunkPos]*chunk.Chunk blockNBT map[protocol.SubChunkPos][]map[string]any openItemContainers map[byte]*itemContainer entities map[uint64]*entityState + Dim world.Dimension + PlayerPos TPlayerPos + worldCounter int + WorldName string + ServerName string + ispre118 bool - Dim world.Dimension - WorldName string - ServerName string - worldCounter int - bp *behaviourpack.BehaviourPack - + // settings + voidgen bool withPacks bool saveImage bool experimentInventory bool - - PlayerPos TPlayerPos - proxy *utils.ProxyContext - - // ui - ui *MapUI } func NewWorldState() *WorldState { @@ -79,7 +79,7 @@ func NewWorldState() *WorldState { return w } -var dimension_ids = map[uint8]world.Dimension{ +var dimensionIDMap = map[uint8]world.Dimension{ 0: world.Overworld, 1: world.Nether, 2: world.End, @@ -90,16 +90,16 @@ var dimension_ids = map[uint8]world.Dimension{ } var ( - black_16x16 = image.NewRGBA(image.Rect(0, 0, 16, 16)) - Offset_table [24]protocol.SubChunkOffset + black16x16 = image.NewRGBA(image.Rect(0, 0, 16, 16)) + offsetTable [24]protocol.SubChunkOffset ) func init() { - for i := range Offset_table { - Offset_table[i] = protocol.SubChunkOffset{0, int8(i), 0} + for i := range offsetTable { + offsetTable[i] = protocol.SubChunkOffset{0, int8(i), 0} } - for i := 3; i < len(black_16x16.Pix); i += 4 { - black_16x16.Pix[i] = 255 + for i := 3; i < len(black16x16.Pix); i += 4 { + black16x16.Pix[i] = 255 } utils.RegisterCommand(&WorldCMD{}) } @@ -115,12 +115,12 @@ type WorldCMD struct { func (*WorldCMD) Name() string { return "worlds" } func (*WorldCMD) Synopsis() string { return locale.Loc("world_synopsis", nil) } -func (p *WorldCMD) SetFlags(f *flag.FlagSet) { - f.StringVar(&p.Address, "address", "", locale.Loc("remote_address", nil)) - f.BoolVar(&p.packs, "packs", false, locale.Loc("save_packs_with_world", nil)) - f.BoolVar(&p.enableVoid, "void", true, locale.Loc("enable_void", nil)) - f.BoolVar(&p.saveImage, "image", false, locale.Loc("save_image", nil)) - f.BoolVar(&p.experimentInventory, "inv", false, locale.Loc("test_block_inv", nil)) +func (c *WorldCMD) SetFlags(f *flag.FlagSet) { + f.StringVar(&c.Address, "address", "", locale.Loc("remote_address", nil)) + 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) Usage() string { @@ -128,7 +128,7 @@ func (c *WorldCMD) Usage() string { } func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - server_address, hostname, err := utils.ServerInput(ctx, c.Address) + serverAddress, hostname, err := utils.ServerInput(ctx, c.Address) if err != nil { logrus.Error(err) return 1 @@ -147,7 +147,7 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ proxy.AlwaysGetPacks = true proxy.ConnectCB = w.OnConnect proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool) (packet.Packet, error) { - var forward bool = true + forward := true if toServer { // from client @@ -166,7 +166,7 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ return pk, nil } - err = proxy.Run(ctx, server_address) + err = proxy.Run(ctx, serverAddress) if err != nil { logrus.Error(err) } else { @@ -202,7 +202,7 @@ func (w *WorldState) Reset() { w.ui.Reset() } -// writes the world to a folder, resets all the chunks +// SaveAndReset writes the world to a folder, resets all the chunks func (w *WorldState) SaveAndReset() { if len(w.chunks) == 0 { w.Reset() @@ -241,12 +241,7 @@ func (w *WorldState) SaveAndReset() { chunkEntities := make(map[world.ChunkPos][]world.Entity) for _, es := range w.entities { cp := world.ChunkPos{int32(es.Position.X()) >> 4, int32(es.Position.Z()) >> 4} - - chunkEntities[cp] = append(chunkEntities[cp], serverEntity{ - EntityType: serverEntityType{ - Encoded: es.EntityType, - }, - }) + chunkEntities[cp] = append(chunkEntities[cp], es.ToServerEntity()) } for cp, v := range chunkEntities { @@ -359,10 +354,10 @@ func (w *WorldState) SaveAndReset() { w.worldCounter += 1 type dep struct { - PackId string `json:"pack_id"` + PackID string `json:"pack_id"` Version [3]int `json:"version"` } - add_packs_json := func(name string, deps []dep) { + addPacksJSON := func(name string, deps []dep) { f, err := os.Create(path.Join(folder, name)) if err != nil { logrus.Error(err) @@ -378,17 +373,17 @@ func (w *WorldState) SaveAndReset() { // save behaviourpack if w.bp.HasContent() { name := strings.ReplaceAll(w.ServerName, "/", "-") + "_blocks" - pack_folder := path.Join(folder, "behavior_packs", name) - os.MkdirAll(pack_folder, 0o755) + packFolder := path.Join(folder, "behavior_packs", name) + os.MkdirAll(packFolder, 0o755) for _, p := range w.proxy.Server.ResourcePacks() { p := utils.PackFromBase(p) w.bp.CheckAddLink(p) } - w.bp.Save(pack_folder) - add_packs_json("world_behavior_packs.json", []dep{{ - PackId: w.bp.Manifest.Header.UUID, + w.bp.Save(packFolder) + addPacksJSON("world_behavior_packs.json", []dep{{ + PackID: w.bp.Manifest.Header.UUID, Version: w.bp.Manifest.Header.Version, }}) @@ -405,18 +400,18 @@ func (w *WorldState) SaveAndReset() { var rdeps []dep for k, p := range packs { logrus.Infof(locale.Loc("adding_pack", locale.Strmap{"Name": k})) - pack_folder := path.Join(folder, "resource_packs", p.Name()) - os.MkdirAll(pack_folder, 0o755) + 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)), pack_folder) + utils.UnpackZip(bytes.NewReader(data), int64(len(data)), packFolder) rdeps = append(rdeps, dep{ - PackId: p.Manifest().Header.Name, + PackID: p.Manifest().Header.Name, Version: p.Manifest().Header.Version, }) } - add_packs_json("world_resource_packs.json", rdeps) + addPacksJSON("world_resource_packs.json", rdeps) } } @@ -446,10 +441,10 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) { w.bp.AddItem(ie) } - map_item_id, _ := world.ItemRidByName("minecraft:filled_map") - MAP_ITEM_PACKET.Content[0].Stack.ItemType.NetworkID = map_item_id + mapItemID, _ := world.ItemRidByName("minecraft:filled_map") + MapItemPacket.Content[0].Stack.ItemType.NetworkID = mapItemID if gd.ServerAuthoritativeInventory { - MAP_ITEM_PACKET.Content[0].StackNetworkID = 0xffff + rand.Int31n(0xfff) + MapItemPacket.Content[0].StackNetworkID = 0xffff + rand.Int31n(0xfff) } if len(gd.CustomBlocks) > 0 { @@ -473,12 +468,12 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) { logrus.Info(locale.Loc("guessing_version", nil)) } - dim_id := gd.Dimension + dimensionID := gd.Dimension if w.ispre118 { logrus.Info(locale.Loc("using_under_118", nil)) - dim_id += 10 + dimensionID += 10 } - w.Dim = dimension_ids[uint8(dim_id)] + w.Dim = dimensionIDMap[uint8(dimensionID)] } w.proxy.SendMessage(locale.Loc("use_setname", nil)) diff --git a/utils/auth.go b/utils/auth.go index 72da815..5e07d9f 100644 --- a/utils/auth.go +++ b/utils/auth.go @@ -11,49 +11,49 @@ import ( "golang.org/x/oauth2" ) -const TOKEN_FILE = "token.json" +const TokenFile = "token.json" -var G_token_src oauth2.TokenSource +var gTokenSrc oauth2.TokenSource func GetTokenSource() oauth2.TokenSource { - if G_token_src != nil { - return G_token_src + if gTokenSrc != nil { + return gTokenSrc } - token := get_token() - G_token_src = auth.RefreshTokenSource(&token) - new_token, err := G_token_src.Token() + token := getToken() + gTokenSrc = auth.RefreshTokenSource(&token) + newToken, err := gTokenSrc.Token() if err != nil { panic(err) } if !token.Valid() { logrus.Info(locale.Loc("refreshed_token", nil)) - write_token(new_token) + writeToken(newToken) } - return G_token_src + return gTokenSrc } -var G_realms_api *realms.Client +var gRealmsAPI *realms.Client -func GetRealmsApi() *realms.Client { - if G_realms_api == nil { - G_realms_api = realms.NewClient(GetTokenSource()) +func GetRealmsAPI() *realms.Client { + if gRealmsAPI == nil { + gRealmsAPI = realms.NewClient(GetTokenSource()) } - return G_realms_api + return gRealmsAPI } -func write_token(token *oauth2.Token) { +func writeToken(token *oauth2.Token) { buf, err := json.Marshal(token) if err != nil { panic(err) } - os.WriteFile(TOKEN_FILE, buf, 0o755) + os.WriteFile(TokenFile, buf, 0o755) } -func get_token() oauth2.Token { +func getToken() oauth2.Token { var token oauth2.Token - if _, err := os.Stat(TOKEN_FILE); err == nil { - f, err := os.Open(TOKEN_FILE) + if _, err := os.Stat(TokenFile); err == nil { + f, err := os.Open(TokenFile) if err != nil { panic(err) } @@ -66,7 +66,7 @@ func get_token() oauth2.Token { if err != nil { panic(err) } - write_token(_token) + writeToken(_token) token = *_token } return token diff --git a/utils/behaviourpack/bp.go b/utils/behaviourpack/bp.go index 72ef9d5..2769c35 100644 --- a/utils/behaviourpack/bp.go +++ b/utils/behaviourpack/bp.go @@ -28,14 +28,14 @@ func New(name string) *BehaviourPack { Header: resource.Header{ Name: "pack.name", Description: "pack.description", - UUID: utils.Rand_seeded_uuid(name + "_datapack"), + UUID: utils.RandSeededUUID(name + "_datapack"), Version: [3]int{1, 0, 0}, MinimumGameVersion: [3]int{1, 19, 50}, }, Modules: []resource.Module{ { Type: "data", - UUID: utils.Rand_seeded_uuid(name + "_data_module"), + UUID: utils.RandSeededUUID(name + "_data_module"), Version: [3]int{1, 0, 0}, }, }, diff --git a/utils/behaviourpack/entity.go b/utils/behaviourpack/entity.go index 0601f26..042b415 100644 --- a/utils/behaviourpack/entity.go +++ b/utils/behaviourpack/entity.go @@ -13,7 +13,7 @@ type minecraftClientEntity struct { Description clientEntityDescription `json:"description"` ComponentGroups map[string]any `json:"component_groups"` Components map[string]any `json:"components"` - Events map[string]any `json:"events"` + Events map[string]any `json:"events,omitempty"` } type entityBehaviour struct { diff --git a/utils/dns.go b/utils/dns.go index feb11dd..fb20bb0 100644 --- a/utils/dns.go +++ b/utils/dns.go @@ -9,7 +9,7 @@ import ( "github.com/sirupsen/logrus" ) -var override_dns = map[string]bool{ +var overrideDNS = map[string]bool{ "geo.hivebedrock.network.": true, } @@ -24,15 +24,15 @@ func (d *DNSServer) answerQuery(remote net.Addr, req *dns.Msg) (reply *dns.Msg) case dns.TypeA: logrus.Infof("Query for %s", q.Name) - if override_dns[q.Name] { + if overrideDNS[q.Name] { host, _, _ := net.SplitHostPort(remote.String()) - remote_ip := net.ParseIP(host) + remoteIP := net.ParseIP(host) addrs, _ := net.InterfaceAddrs() var ip string for _, addr := range addrs { if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { - if ipnet.Contains(remote_ip) { + if ipnet.Contains(remoteIP) { ip = ipnet.IP.String() } } diff --git a/utils/images.go b/utils/images.go index b4277c0..08c4df0 100644 --- a/utils/images.go +++ b/utils/images.go @@ -35,17 +35,17 @@ func BlendColors(c1, c2 color.RGBA) (ret color.RGBA) { return ret } -// Draw_img_scaled_pos draws src onto dst at bottom_left, scaled to size -func Draw_img_scaled_pos(dst *image.RGBA, src *image.RGBA, bottom_left image.Point, size_scaled int) { +// DrawImgScaledPos draws src onto dst at bottomLeft, scaled to size +func DrawImgScaledPos(dst *image.RGBA, src *image.RGBA, bottomLeft image.Point, sizeScaled int) { sbx := src.Bounds().Dx() - ratio := int(float64(sbx) / float64(size_scaled)) + ratio := int(float64(sbx) / float64(sizeScaled)) - for x_out := bottom_left.X; x_out < bottom_left.X+size_scaled; x_out++ { - for y_out := bottom_left.Y; y_out < bottom_left.Y+size_scaled; y_out++ { - x_in := (x_out - bottom_left.X) * ratio - y_in := (y_out - bottom_left.Y) * ratio - c := src.At(x_in, y_in) - dst.Set(x_out, y_out, c) + for xOut := bottomLeft.X; xOut < bottomLeft.X+sizeScaled; xOut++ { + for yOut := bottomLeft.Y; yOut < bottomLeft.Y+sizeScaled; yOut++ { + xIn := (xOut - bottomLeft.X) * ratio + yIn := (yOut - bottomLeft.Y) * ratio + c := src.At(xIn, yIn) + dst.Set(xOut, yOut, c) } } } diff --git a/utils/input.go b/utils/input.go index 1e49118..9b751c0 100644 --- a/utils/input.go +++ b/utils/input.go @@ -13,7 +13,7 @@ import ( "github.com/sirupsen/logrus" ) -func User_input(ctx context.Context, q string) (string, bool) { +func UserInput(ctx context.Context, q string) (string, bool) { c := make(chan string) go func() { fmt.Print(q) @@ -32,7 +32,7 @@ func User_input(ctx context.Context, q string) (string, bool) { } } -func server_url_to_name(server string) string { +func serverURLToName(server string) string { host, _, err := net.SplitHostPort(server) if err != nil { logrus.Fatalf(locale.Loc("invalid_server", locale.Strmap{"Err": err.Error()})) @@ -43,19 +43,19 @@ func server_url_to_name(server string) string { func ServerInput(ctx context.Context, server string) (address, name string, err error) { if server == "" { // no arg provided, interactive input var cancelled bool - server, cancelled = User_input(ctx, locale.Loc("enter_server", nil)) + server, cancelled = UserInput(ctx, locale.Loc("enter_server", nil)) if cancelled { return "", "", context.Canceled } } if strings.HasPrefix(server, "realm:") { // for realms use api to get ip address - realm_info := strings.Split(server, ":") + realmInfo := strings.Split(server, ":") id := "" - if len(realm_info) == 3 { - id = realm_info[2] + if len(realmInfo) == 3 { + id = realmInfo[2] } - name, address, err = get_realm(ctx, realm_info[1], id) + name, address, err = getRealm(ctx, realmInfo[1], id) if err != nil { return "", "", err } @@ -71,7 +71,7 @@ func ServerInput(ctx context.Context, server string) (address, name string, err if len(strings.Split(address, ":")) == 1 { address += ":19132" } - name = server_url_to_name(address) + name = serverURLToName(address) } return address, name, nil diff --git a/utils/net.go b/utils/net.go index 8a0c142..4622344 100644 --- a/utils/net.go +++ b/utils/net.go @@ -17,7 +17,7 @@ var PrivateIPNetworks = []net.IPNet{ }, } -// check if ip is private +// IPPrivate checks if ip is private func IPPrivate(ip net.IP) bool { for _, ipNet := range PrivateIPNetworks { if ipNet.Contains(ip) { diff --git a/utils/packet_logger.go b/utils/packet_logger.go index c9bfc8e..6999a92 100644 --- a/utils/packet_logger.go +++ b/utils/packet_logger.go @@ -48,17 +48,19 @@ var MutedPackets = []string{ "packet.PlaySound", } -var ExtraVerbose []string -var F_Log io.Writer -var dmp_lock sync.Mutex +var ( + ExtraVerbose []string + FLog io.Writer + dmpLock sync.Mutex +) -func dmp_struct(level int, in any, w_type bool) (s string) { - t_base := strings.Repeat("\t", level) +func dmpStruct(level int, in any, wType bool) (s string) { + tBase := strings.Repeat("\t", level) ii := reflect.Indirect(reflect.ValueOf(in)) - if w_type { - type_name := reflect.TypeOf(in).String() - s += type_name + " " + if wType { + typeName := reflect.TypeOf(in).String() + s += typeName + " " } else { s += "\t" } @@ -68,13 +70,13 @@ func dmp_struct(level int, in any, w_type bool) (s string) { for i := 0; i < ii.NumField(); i++ { field := ii.Type().Field(i) if field.IsExported() { - d := dmp_struct(level+1, ii.Field(i).Interface(), true) - s += t_base + fmt.Sprintf("\t%s = %s\n", field.Name, d) + d := dmpStruct(level+1, ii.Field(i).Interface(), true) + s += tBase + fmt.Sprintf("\t%s = %s\n", field.Name, d) } else { - s += t_base + "\t" + field.Name + " (unexported)" + s += tBase + "\t" + field.Name + " (unexported)" } } - s += t_base + "}\n" + s += tBase + "}\n" } else if ii.Kind() == reflect.Slice { var t reflect.Type if ii.Len() > 0 { @@ -86,15 +88,15 @@ func dmp_struct(level int, in any, w_type bool) (s string) { } else if ii.Len() == 0 || t.Kind() == reflect.Struct { s += "\t[\n" for i := 0; i < ii.Len(); i++ { - s += t_base - s += dmp_struct(level+1, ii.Index(i).Interface(), false) + s += tBase + s += dmpStruct(level+1, ii.Index(i).Interface(), false) } - s += t_base + "]\n" + s += tBase + "]\n" } else { s += fmt.Sprintf("%#v", ii.Interface()) } } else if ii.Kind() == reflect.Map { - j, err := json.MarshalIndent(ii.Interface(), t_base, "\t") + j, err := json.MarshalIndent(ii.Interface(), tBase, "\t") if err != nil { s += err.Error() } @@ -122,15 +124,15 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) { pk.Unmarshal(protocol.NewReader(bytes.NewBuffer(payload), 0)) - if F_Log != nil { - dmp_lock.Lock() - defer dmp_lock.Unlock() - F_Log.Write([]byte(dmp_struct(0, pk, true))) - F_Log.Write([]byte("\n\n")) + if FLog != nil { + dmpLock.Lock() + defer dmpLock.Unlock() + FLog.Write([]byte(dmpStruct(0, pk, true))) + FLog.Write([]byte("\n\n")) } - pk_name := reflect.TypeOf(pk).String()[1:] - if slices.Contains(MutedPackets, pk_name) { + pkName := reflect.TypeOf(pk).String()[1:] + if slices.Contains(MutedPackets, pkName) { return } @@ -139,24 +141,24 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) { logrus.Infof(locale.Loc("disconnect", locale.Strmap{"Pk": pk})) } - dir_S2C := color.GreenString("S") + "->" + color.CyanString("C") - dir_C2S := color.CyanString("C") + "->" + color.GreenString("S") - var dir string = dir_S2C + dirS2C := color.GreenString("S") + "->" + color.CyanString("C") + dirC2S := color.CyanString("C") + "->" + color.GreenString("S") + var dir string = dirS2C - if Client_addr != nil { - if src == Client_addr { - dir = dir_C2S + if ClientAddr != nil { + if src == ClientAddr { + dir = dirC2S } } else { - src_addr, _, _ := net.SplitHostPort(src.String()) - if IPPrivate(net.ParseIP(src_addr)) { - dir = dir_C2S + srcAddr, _, _ := net.SplitHostPort(src.String()) + if IPPrivate(net.ParseIP(srcAddr)) { + dir = dirS2C } } - logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pk_name) + logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName) - if slices.Contains(ExtraVerbose, pk_name) { + if slices.Contains(ExtraVerbose, pkName) { logrus.Debugf("%+v", pk) } } diff --git a/utils/proxy.go b/utils/proxy.go index 3a7a855..bed5785 100644 --- a/utils/proxy.go +++ b/utils/proxy.go @@ -17,7 +17,7 @@ import ( "github.com/sirupsen/logrus" ) -var G_disconnect_reason = "Connection lost" +var DisconnectReason = "Connection lost" type dummyProto struct { id int32 @@ -137,7 +137,7 @@ func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool, packetCBs [ if pk != nil && c2 != nil { if err := c2.WritePacket(pk); err != nil { if disconnect, ok := errors.Unwrap(err).(minecraft.DisconnectError); ok { - G_disconnect_reason = disconnect.Error() + DisconnectReason = disconnect.Error() } return err } @@ -152,14 +152,14 @@ func NewProxy() *ProxyContext { } } -var Client_addr net.Addr +var ClientAddr net.Addr -func (p *ProxyContext) Run(ctx context.Context, server_address string) (err error) { - if strings.HasSuffix(server_address, ".pcap") { +func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error) { + if strings.HasSuffix(serverAddress, ".pcap") { return fmt.Errorf(locale.Loc("not_supported_anymore", nil)) } - if strings.HasSuffix(server_address, ".pcap2") { - return create_replay_connection(ctx, server_address, p.ConnectCB, p.PacketCB) + if strings.HasSuffix(serverAddress, ".pcap2") { + return createReplayConnection(ctx, serverAddress, p.ConnectCB, p.PacketCB) } GetTokenSource() // ask for login before listening @@ -167,12 +167,12 @@ func (p *ProxyContext) Run(ctx context.Context, server_address string) (err erro var cdp *login.ClientData = nil if p.WithClient { var packs []*resource.Pack - if G_preload_packs { + if GPreloadPacks { logrus.Info(locale.Loc("preloading_packs", nil)) var serverConn *minecraft.Conn - serverConn, err = connectServer(ctx, server_address, nil, true, nil) + serverConn, err = connectServer(ctx, serverAddress, nil, true, nil) if err != nil { - err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": server_address, "Err": err})) + err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": serverAddress, "Err": err})) return } serverConn.Close() @@ -210,20 +210,20 @@ func (p *ProxyContext) Run(ctx context.Context, server_address string) (err erro cd := p.Client.ClientData() cdp = &cd } - p.Server, err = connectServer(ctx, server_address, cdp, p.AlwaysGetPacks, p.PacketFunc) + p.Server, err = connectServer(ctx, serverAddress, cdp, p.AlwaysGetPacks, p.PacketFunc) if err != nil { - err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": server_address, "Err": err})) + err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": serverAddress, "Err": err})) return } // spawn and start the game - if err = spawn_conn(ctx, p.Client, p.Server); err != nil { + if err = spawnConn(ctx, p.Client, p.Server); err != nil { err = fmt.Errorf(locale.Loc("failed_to_spawn", locale.Strmap{"Err": err})) return } defer p.Server.Close() if p.Listener != nil { - defer p.Listener.Disconnect(p.Client, G_disconnect_reason) + defer p.Listener.Disconnect(p.Client, DisconnectReason) } if p.ConnectCB != nil { diff --git a/utils/realms.go b/utils/realms.go index 652d5e1..3e47d2a 100644 --- a/utils/realms.go +++ b/utils/realms.go @@ -11,13 +11,13 @@ import ( "github.com/sirupsen/logrus" ) -func get_realm(ctx context.Context, realm_name, id string) (name string, address string, err error) { - realms, err := GetRealmsApi().Realms(ctx) +func getRealm(ctx context.Context, realmName, id string) (name string, address string, err error) { + realms, err := GetRealmsAPI().Realms(ctx) if err != nil { return "", "", err } for _, realm := range realms { - if strings.HasPrefix(realm.Name, realm_name) { + if strings.HasPrefix(realm.Name, realmName) { if id != "" && id != fmt.Sprint(id) { continue } @@ -43,7 +43,7 @@ func (c *RealmListCMD) Usage() string { } func (c *RealmListCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - realms, err := GetRealmsApi().Realms(ctx) + realms, err := GetRealmsAPI().Realms(ctx) if err != nil { logrus.Error(err) return 1 diff --git a/utils/replay.go b/utils/replay.go index 1f64813..33aa660 100644 --- a/utils/replay.go +++ b/utils/replay.go @@ -14,7 +14,7 @@ import ( "github.com/sirupsen/logrus" ) -func create_replay_connection(ctx context.Context, filename string, onConnect ConnectCallback, packetCB PacketCallback) error { +func createReplayConnection(ctx context.Context, filename string, onConnect ConnectCallback, packetCB PacketCallback) error { logrus.Infof("Reading replay %s", filename) f, err := os.Open(filename) @@ -33,12 +33,12 @@ func create_replay_connection(ctx context.Context, filename string, onConnect Co proxy := NewProxy() proxy.Server = minecraft.NewConn() - game_started := false + gameStarted := false i := 0 for { i += 1 var magic uint32 = 0 - var packet_length uint32 = 0 + var packetLength uint32 = 0 var toServer bool = false offset, _ := f.Seek(0, io.SeekCurrent) @@ -51,15 +51,15 @@ func create_replay_connection(ctx context.Context, filename string, onConnect Co if magic != 0xAAAAAAAA { logrus.Fatal("Wrong Magic") } - binary.Read(f, binary.LittleEndian, &packet_length) + binary.Read(f, binary.LittleEndian, &packetLength) binary.Read(f, binary.LittleEndian, &toServer) - payload := make([]byte, packet_length) + payload := make([]byte, packetLength) n, err := f.Read(payload) if err != nil { logrus.Error(err) return nil } - if n != int(packet_length) { + if n != int(packetLength) { logrus.Errorf("Truncated %d", i) return nil } @@ -70,11 +70,11 @@ func create_replay_connection(ctx context.Context, filename string, onConnect Co logrus.Fatal("Wrong Magic2") } - pk_data, err := minecraft.ParseData(payload, proxy.Server) + pkData, err := minecraft.ParseData(payload, proxy.Server) if err != nil { return err } - pks, err := pk_data.Decode(proxy.Server) + pks, err := pkData.Decode(proxy.Server) if err != nil { logrus.Error(err) continue @@ -85,11 +85,11 @@ func create_replay_connection(ctx context.Context, filename string, onConnect Co b := protocol.NewWriter(f, 0) pk.Marshal(b) - if G_debug { - PacketLogger(packet.Header{PacketID: pk.ID()}, f.Bytes(), &net.UDPAddr{}, &net.UDPAddr{}) + if GDebug { + PacketLogger(packet.Header{PacketID: pk.ID()}, f.Bytes(), &net.UDPAddr{}, &net.UDPAddr{}) } - if game_started { + if gameStarted { if packetCB != nil { packetCB(pk, proxy, toServer) } @@ -125,7 +125,7 @@ func create_replay_connection(ctx context.Context, filename string, onConnect Co ChatRestrictionLevel: pk.ChatRestrictionLevel, DisablePlayerInteractions: pk.DisablePlayerInteractions, }) - game_started = true + gameStarted = true if onConnect != nil { onConnect(proxy) } diff --git a/utils/resourcepack-ace.go b/utils/resourcepack-ace.go index 8ac7749e0ccae331e6e8b380bbc2744435d99df5..b94448bd988bc89ed186c754a5606a1d72c53f7e 100644 GIT binary patch literal 6450 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 M=f_f@CdQgNWHn2c2><{9 literal 6501 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