diff --git a/cmd/bedrocktool/main.go b/cmd/bedrocktool/main.go index 350159f..c9eb8c3 100644 --- a/cmd/bedrocktool/main.go +++ b/cmd/bedrocktool/main.go @@ -15,6 +15,7 @@ import ( "github.com/bedrock-tool/bedrocktool/locale" "github.com/bedrock-tool/bedrocktool/utils" "github.com/bedrock-tool/bedrocktool/utils/crypt" + "gopkg.in/square/go-jose.v2/json" _ "github.com/bedrock-tool/bedrocktool/subcommands" _ "github.com/bedrock-tool/bedrocktool/subcommands/skins" @@ -65,6 +66,7 @@ func main() { ctx, cancel := context.WithCancel(context.Background()) + flag.StringVar(&utils.RealmsEnv, "", "", "realms env") 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)) @@ -189,6 +191,38 @@ func (c *TransCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) return 0 } +type CreateCustomDataCMD struct { + path string +} + +func (*CreateCustomDataCMD) Name() string { return "create-customdata" } +func (*CreateCustomDataCMD) Synopsis() string { return "" } + +func (c *CreateCustomDataCMD) SetFlags(f *flag.FlagSet) { + f.StringVar(&c.path, "path", "customdata.json", "where to save") +} + +func (c *CreateCustomDataCMD) Usage() string { + return c.Name() + ": " + c.Synopsis() + "\n" +} + +func (c *CreateCustomDataCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { + var data utils.CustomClientData + fio, err := os.Create(c.path) + if err == nil { + defer fio.Close() + var bdata []byte + bdata, err = json.MarshalIndent(&data, "", "\t") + fio.Write(bdata) + } + if err != nil { + logrus.Error(err) + return 1 + } + return 0 +} + func init() { utils.RegisterCommand(&TransCMD{}) + utils.RegisterCommand(&CreateCustomDataCMD{}) } diff --git a/go.mod b/go.mod index 394d4b0..449a1ef 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/bedrock-tool/bedrocktool go 1.19 //replace github.com/sandertv/gophertunnel => ./gophertunnel -replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.27.2-1 +replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.27.2-2 //replace github.com/df-mc/dragonfly => ./dragonfly replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.9.2-1 @@ -29,6 +29,7 @@ require ( golang.org/x/image v0.3.0 golang.org/x/oauth2 v0.4.0 golang.org/x/text v0.6.0 + gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -54,5 +55,4 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inconshreveable/go-update.v0 v0.0.0-20150814200126-d8b0b1d421aa // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect ) diff --git a/go.sum b/go.sum index a094355..8ac2c50 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/olebeck/dragonfly v0.9.2-1 h1:/bYHMZ2yvwrLp2SQvsupbRimqDPGJ5utA2Oq857 github.com/olebeck/dragonfly v0.9.2-1/go.mod h1:hGGjGbLxpcn7nVTZOrk8kPfeGGntaMOqqcbuugZauyI= github.com/olebeck/gophertunnel v1.27.2-1 h1:p+q8XubWgnk37uhjO2e06+A4g7S91jyXbvkQlVL4Xb4= github.com/olebeck/gophertunnel v1.27.2-1/go.mod h1:hgVpDdaLDP/39Z/YqEU0WFi/DHRDHqvBs3XGqkB4tnU= +github.com/olebeck/gophertunnel v1.27.2-2 h1:ycI1ChA2L0ttr74Qkhy+0nGm01PUlHD0IklSj6+BAkI= +github.com/olebeck/gophertunnel v1.27.2-2/go.mod h1:hgVpDdaLDP/39Z/YqEU0WFi/DHRDHqvBs3XGqkB4tnU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/subcommands/capture.go b/subcommands/capture.go index aab7d61..814f27b 100644 --- a/subcommands/capture.go +++ b/subcommands/capture.go @@ -44,7 +44,8 @@ func dumpPacket(f io.WriteCloser, toServer bool, payload []byte) { } type CaptureCMD struct { - serverAddress string + serverAddress string + pathCustomUserData string } func (*CaptureCMD) Name() string { return "capture" } @@ -52,6 +53,7 @@ func (*CaptureCMD) Synopsis() string { return locale.Loc("capture_synopsis", nil func (c *CaptureCMD) SetFlags(f *flag.FlagSet) { f.StringVar(&c.serverAddress, "address", "", "remote server address") + f.StringVar(&c.pathCustomUserData, "userdata", "", locale.Loc("custom_user_data", nil)) } func (c *CaptureCMD) Usage() string { @@ -66,7 +68,6 @@ func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interfac } os.Mkdir("captures", 0o775) - fio, err := os.Create("captures/" + hostname + "-" + time.Now().Format("2006-01-02_15-04-05") + ".pcap2") if err != nil { logrus.Fatal(err) @@ -75,7 +76,10 @@ func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interfac defer fio.Close() utils.WriteReplayHeader(fio) - proxy := utils.NewProxy() + proxy, err := utils.NewProxy(c.pathCustomUserData) + if err != nil { + logrus.Fatal(err) + } proxy.PacketFunc = func(header packet.Header, payload []byte, src, dst net.Addr) { IsfromClient := src.String() == proxy.Client.LocalAddr().String() diff --git a/subcommands/chat_log.go b/subcommands/chat_log.go index 3aaa5ee..b0cf509 100644 --- a/subcommands/chat_log.go +++ b/subcommands/chat_log.go @@ -16,8 +16,9 @@ import ( ) type ChatLogCMD struct { - Address string - verbose bool + Address string + verbose bool + pathCustomUserData string } func (*ChatLogCMD) Name() string { return "chat-log" } @@ -26,6 +27,7 @@ func (*ChatLogCMD) Synopsis() string { return locale.Loc("chat_log_synopsis", ni func (c *ChatLogCMD) SetFlags(f *flag.FlagSet) { f.StringVar(&c.Address, "address", "", "remote server address") f.BoolVar(&c.verbose, "v", false, "verbose") + f.StringVar(&c.pathCustomUserData, "userdata", "", locale.Loc("custom_user_data", nil)) } func (c *ChatLogCMD) Usage() string { @@ -46,7 +48,10 @@ func (c *ChatLogCMD) Execute(ctx context.Context, flags *flag.FlagSet, _ ...inte } defer f.Close() - proxy := utils.NewProxy() + proxy, err := utils.NewProxy(c.pathCustomUserData) + if err != nil { + logrus.Fatal(err) + } proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool, _ time.Time) (packet.Packet, error) { if text, ok := pk.(*packet.Text); ok { logLine := text.Message diff --git a/subcommands/debug.go b/subcommands/debug.go index 22c07b7..31596a9 100644 --- a/subcommands/debug.go +++ b/subcommands/debug.go @@ -13,8 +13,9 @@ import ( ) type DebugProxyCMD struct { - Address string - filter string + Address string + filter string + pathCustomUserData string } func (*DebugProxyCMD) Name() string { return "debug-proxy" } @@ -23,6 +24,7 @@ func (*DebugProxyCMD) Synopsis() string { return locale.Loc("debug_proxy_synopsi func (c *DebugProxyCMD) SetFlags(f *flag.FlagSet) { f.StringVar(&c.Address, "address", "", locale.Loc("remote_address", nil)) f.StringVar(&c.filter, "filter", "", locale.Loc("packet_filter", nil)) + f.StringVar(&c.pathCustomUserData, "userdata", "", locale.Loc("custom_user_data", nil)) } func (c *DebugProxyCMD) Usage() string { @@ -53,7 +55,11 @@ func (c *DebugProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...inter } } - proxy := utils.NewProxy() + proxy, err := utils.NewProxy(c.pathCustomUserData) + if err != nil { + logrus.Error(err) + return 1 + } if err := proxy.Run(ctx, address); err != nil { logrus.Error(err) return 1 diff --git a/subcommands/skins/skins-proxy.go b/subcommands/skins/skins-proxy.go index 7ea0598..171df92 100644 --- a/subcommands/skins/skins-proxy.go +++ b/subcommands/skins/skins-proxy.go @@ -19,6 +19,7 @@ type SkinProxyCMD struct { server_address string filter string only_with_geometry bool + pathCustomUserData string } func (*SkinProxyCMD) Name() string { return "skins-proxy" } @@ -28,6 +29,7 @@ func (c *SkinProxyCMD) SetFlags(f *flag.FlagSet) { f.StringVar(&c.server_address, "address", "", locale.Loc("remote_address", nil)) f.StringVar(&c.filter, "filter", "", locale.Loc("name_prefix", nil)) f.BoolVar(&c.only_with_geometry, "only-geom", false, locale.Loc("only_with_geometry", nil)) + f.StringVar(&c.pathCustomUserData, "userdata", "", locale.Loc("custom_user_data", nil)) } func (c *SkinProxyCMD) Usage() string { @@ -41,7 +43,11 @@ func (c *SkinProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interf return 1 } - proxy := utils.NewProxy() + proxy, err := utils.NewProxy(c.pathCustomUserData) + if err != nil { + logrus.Error(err) + return 1 + } s := NewSkinsSession(proxy, hostname) s.OnlyIfHasGeometry = c.only_with_geometry diff --git a/subcommands/skins/skins.go b/subcommands/skins/skins.go index f760c81..7470442 100644 --- a/subcommands/skins/skins.go +++ b/subcommands/skins/skins.go @@ -143,7 +143,7 @@ func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{} return 1 } - proxy := utils.NewProxy() + proxy, _ := utils.NewProxy("") proxy.WithClient = false proxy.ConnectCB = func(proxy *utils.ProxyContext) { logrus.Info(locale.Loc("ctrl_c_to_exit", nil)) diff --git a/subcommands/world/map_item.go b/subcommands/world/map_item.go index 81391a8..2479bf5 100644 --- a/subcommands/world/map_item.go +++ b/subcommands/world/map_item.go @@ -8,6 +8,7 @@ import ( "os" "time" + "github.com/bedrock-tool/bedrocktool/locale" "github.com/bedrock-tool/bedrocktool/utils" "golang.design/x/lockfree" @@ -254,6 +255,13 @@ func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) { m.SchedRedraw() } +func (w *WorldState) ProcessAnimate(pk *packet.Animate) { + if pk.ActionType == packet.AnimateActionSwingArm { + w.ui.ChangeZoom() + w.proxy.SendPopup(locale.Loc("zoom_level", locale.Strmap{"Level": w.ui.zoomLevel})) + } +} + func (w *WorldState) processMapPacketsClient(pk packet.Packet, forward *bool) packet.Packet { switch pk := pk.(type) { case *packet.MovePlayer: diff --git a/subcommands/world/world.go b/subcommands/world/world.go index 742f019..a4b6e8f 100644 --- a/subcommands/world/world.go +++ b/subcommands/world/world.go @@ -60,14 +60,20 @@ type WorldState struct { ispre118 bool // settings - voidgen bool + voidGen bool withPacks bool saveImage bool experimentInventory bool } -func NewWorldState() *WorldState { +func NewWorldState(ctx context.Context, proxy *utils.ProxyContext, ServerName string) *WorldState { w := &WorldState{ + ctx: ctx, + proxy: proxy, + ui: nil, + bp: behaviourpack.New(ServerName), + ServerName: ServerName, + chunks: make(map[protocol.ChunkPos]*chunk.Chunk), blockNBT: make(map[protocol.SubChunkPos][]map[string]any), openItemContainers: make(map[byte]*itemContainer), @@ -111,6 +117,7 @@ type WorldCMD struct { enableVoid bool saveImage bool experimentInventory bool + pathCustomUserData string } func (*WorldCMD) Name() string { return "worlds" } @@ -122,6 +129,7 @@ func (c *WorldCMD) SetFlags(f *flag.FlagSet) { 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)) + f.StringVar(&c.pathCustomUserData, "userdata", "", locale.Loc("custom_user_data", nil)) } func (c *WorldCMD) Usage() string { @@ -135,16 +143,18 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ return 1 } - w := NewWorldState() - w.voidgen = c.enableVoid - w.ServerName = hostname + proxy, err := utils.NewProxy(c.pathCustomUserData) + if err != nil { + logrus.Error(err) + return 1 + } + + w := NewWorldState(ctx, proxy, hostname) + w.voidGen = c.enableVoid w.withPacks = c.packs w.saveImage = c.saveImage w.experimentInventory = c.experimentInventory - w.ctx = ctx - w.bp = behaviourpack.New(w.ServerName) - proxy := utils.NewProxy() proxy.AlwaysGetPacks = true proxy.ConnectCB = w.OnConnect proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool, _ time.Time) (packet.Packet, error) { @@ -167,7 +177,7 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ return pk, nil } - err = proxy.Run(ctx, serverAddress) + err = w.proxy.Run(ctx, serverAddress) if err != nil { logrus.Error(err) } else { @@ -176,13 +186,6 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ return 0 } -func (w *WorldState) ProcessAnimate(pk *packet.Animate) { - if pk.ActionType == packet.AnimateActionSwingArm { - w.ui.ChangeZoom() - w.proxy.SendPopup(locale.Loc("zoom_level", locale.Strmap{"Level": w.ui.zoomLevel})) - } -} - func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) { last := w.PlayerPos w.PlayerPos = TPlayerPos{ @@ -336,7 +339,7 @@ func (w *WorldState) SaveAndReset() { ld.RandomSeed = int64(gd.WorldSeed) // void world - if w.voidgen { + if w.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 } @@ -508,9 +511,9 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) { proxy.AddCommand(utils.IngameCommand{ Exec: func(cmdline []string) bool { - w.voidgen = !w.voidgen + w.voidGen = !w.voidGen var s string - if w.voidgen { + if w.voidGen { s = locale.Loc("void_generator_true", nil) } else { s = locale.Loc("void_generator_false", nil) diff --git a/utils/auth.go b/utils/auth.go index 5e07d9f..dec9c20 100644 --- a/utils/auth.go +++ b/utils/auth.go @@ -2,6 +2,7 @@ package utils import ( "encoding/json" + "fmt" "os" "github.com/bedrock-tool/bedrocktool/locale" @@ -33,10 +34,15 @@ func GetTokenSource() oauth2.TokenSource { return gTokenSrc } +var RealmsEnv string + var gRealmsAPI *realms.Client func GetRealmsAPI() *realms.Client { if gRealmsAPI == nil { + if RealmsEnv != "" { + realms.RealmsAPIBase = fmt.Sprintf("https://pocket-%s.realms.minecraft.net/", RealmsEnv) + } gRealmsAPI = realms.NewClient(GetTokenSource()) } return gRealmsAPI diff --git a/utils/images.go b/utils/images.go index a052cd9..dacc8b4 100644 --- a/utils/images.go +++ b/utils/images.go @@ -3,6 +3,8 @@ package utils import ( "image" "image/color" + "image/png" + "os" "reflect" "unsafe" ) @@ -14,6 +16,18 @@ func Img2rgba(img *image.RGBA) []color.RGBA { return *(*[]color.RGBA)(unsafe.Pointer(&header)) } +func loadPng(path string) (*image.RGBA, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + img, err := png.Decode(f) + if err != nil { + return nil, err + } + return (*image.RGBA)(img.(*image.NRGBA)), err +} + // LERP is a linear interpolation function func LERP(p1, p2, alpha float64) float64 { return (1-alpha)*p1 + alpha*p2 diff --git a/utils/proxy.go b/utils/proxy.go index 19a347d..03a0f07 100644 --- a/utils/proxy.go +++ b/utils/proxy.go @@ -2,9 +2,12 @@ package utils import ( "context" + "encoding/base64" + "encoding/json" "errors" "fmt" "net" + "os" "strings" "sync" "time" @@ -20,29 +23,24 @@ import ( var DisconnectReason = "Connection lost" -type dummyProto struct { - id int32 - ver string -} - -func (p dummyProto) ID() int32 { return p.id } -func (p dummyProto) Ver() string { return p.ver } -func (p dummyProto) Packets() packet.Pool { return packet.NewPool() } -func (p dummyProto) ConvertToLatest(pk packet.Packet, _ *minecraft.Conn) []packet.Packet { - return []packet.Packet{pk} -} - -func (p dummyProto) ConvertFromLatest(pk packet.Packet, _ *minecraft.Conn) []packet.Packet { - return []packet.Packet{pk} -} +type ( + PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr) + PacketCallback func(pk packet.Packet, proxy *ProxyContext, toServer bool, timeReceived time.Time) (packet.Packet, error) + ConnectCallback func(proxy *ProxyContext) + IngameCommand struct { + Exec func(cmdline []string) bool + Cmd protocol.Command + } +) type ProxyContext struct { - Server *minecraft.Conn - Client *minecraft.Conn - Listener *minecraft.Listener - commands map[string]IngameCommand - AlwaysGetPacks bool - WithClient bool + Server *minecraft.Conn + Client *minecraft.Conn + Listener *minecraft.Listener + commands map[string]IngameCommand + AlwaysGetPacks bool + WithClient bool + CustomClientData *login.ClientData // called for every packet PacketFunc PacketFunc @@ -52,11 +50,88 @@ type ProxyContext struct { PacketCB PacketCallback } -type ( - PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr) - PacketCallback func(pk packet.Packet, proxy *ProxyContext, toServer bool, timeReceived time.Time) (packet.Packet, error) - ConnectCallback func(proxy *ProxyContext) -) +func NewProxy(pathCustomData string) (*ProxyContext, error) { + p := &ProxyContext{ + commands: make(map[string]IngameCommand), + WithClient: true, + } + if pathCustomData != "" { + if err := p.LoadCustomUserData(pathCustomData); err != nil { + return nil, err + } + } + return p, nil +} + +func (p *ProxyContext) AddCommand(cmd IngameCommand) { + p.commands[cmd.Cmd.Name] = cmd +} + +type CustomClientData struct { + // skin things + CapeFilename string + SkinFilename string + SkinGeometryFilename string + PlayFabID string + PersonaSkin bool + PremiumSkin bool + TrustedSkin bool + ArmSize string + + // misc + IsEditorMode bool + LanguageCode string +} + +func (p *ProxyContext) LoadCustomUserData(path string) error { + f, err := os.Open(path) + if err != nil { + return err + } + var customData CustomClientData + err = json.NewDecoder(f).Decode(&customData) + if err != nil { + return err + } + + p.CustomClientData = &login.ClientData{ + PlayFabID: customData.PlayFabID, + PersonaSkin: customData.PersonaSkin, + PremiumSkin: customData.PremiumSkin, + TrustedSkin: customData.TrustedSkin, + ArmSize: customData.ArmSize, + } + + if customData.SkinFilename != "" { + img, err := loadPng(customData.SkinFilename) + if err != nil { + return err + } + p.CustomClientData.SkinData = base64.RawStdEncoding.EncodeToString(img.Pix) + p.CustomClientData.SkinImageWidth = img.Rect.Dx() + p.CustomClientData.SkinImageHeight = img.Rect.Dy() + } + + if customData.CapeFilename != "" { + img, err := loadPng(customData.CapeFilename) + if err != nil { + return err + } + p.CustomClientData.CapeData = base64.RawStdEncoding.EncodeToString(img.Pix) + p.CustomClientData.CapeImageWidth = img.Rect.Dx() + p.CustomClientData.CapeImageHeight = img.Rect.Dy() + } + + if customData.SkinGeometryFilename != "" { + data, err := os.ReadFile(customData.SkinGeometryFilename) + if err != nil { + return err + } + p.CustomClientData.SkinGeometry = base64.RawStdEncoding.EncodeToString(data) + } + + return nil +} func (p *ProxyContext) SendMessage(text string) { if p.Client != nil { @@ -76,15 +151,6 @@ func (p *ProxyContext) SendPopup(text string) { } } -type IngameCommand struct { - Exec func(cmdline []string) bool - Cmd protocol.Command -} - -func (p *ProxyContext) AddCommand(cmd IngameCommand) { - p.commands[cmd.Cmd.Name] = cmd -} - func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, proxy *ProxyContext, toServer bool, _ time.Time) (packet.Packet, error) { switch _pk := pk.(type) { case *packet.CommandRequest: @@ -146,13 +212,6 @@ func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool, packetCBs [ } } -func NewProxy() *ProxyContext { - return &ProxyContext{ - commands: make(map[string]IngameCommand), - WithClient: true, - } -} - var ClientAddr net.Addr func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error) { @@ -182,9 +241,6 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error p.Listener, err = minecraft.ListenConfig{ StatusProvider: _status, ResourcePacks: packs, - AcceptedProtocols: []minecraft.Protocol{ - dummyProto{id: 544, ver: "1.19.20"}, - }, }.Listen("raknet", ":19132") if err != nil { return @@ -208,6 +264,11 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error cd := p.Client.ClientData() cdp = &cd } + + if p.CustomClientData != nil { + cdp = p.CustomClientData + } + 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": serverAddress, "Err": err})) @@ -229,9 +290,9 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error } wg := sync.WaitGroup{} - cbs := []PacketCallback{ - p.CommandHandlerPacketCB, - } + + var cbs []PacketCallback + cbs = append(cbs, p.CommandHandlerPacketCB) if p.PacketCB != nil { cbs = append(cbs, p.PacketCB) } diff --git a/utils/replay.go b/utils/replay.go index eae7d8e..1030e61 100644 --- a/utils/replay.go +++ b/utils/replay.go @@ -63,7 +63,7 @@ func createReplayConnection(ctx context.Context, filename string, onConnect Conn f.Seek(-4, io.SeekCurrent) } - proxy := NewProxy() + proxy, _ := NewProxy("") proxy.Server = minecraft.NewConn() gameStarted := false diff --git a/utils/resourcepack-ace.go b/utils/resourcepack-ace.go index b94448b..707c3a6 100644 Binary files a/utils/resourcepack-ace.go and b/utils/resourcepack-ace.go differ