rework ui code to allow writing uis for subcommands
This commit is contained in:
parent
5565301f11
commit
c9850772d5
|
@ -5,7 +5,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
@ -13,31 +12,30 @@ import (
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils/crypt"
|
|
||||||
"gopkg.in/square/go-jose.v2/json"
|
"gopkg.in/square/go-jose.v2/json"
|
||||||
|
|
||||||
_ "github.com/bedrock-tool/bedrocktool/subcommands"
|
_ "github.com/bedrock-tool/bedrocktool/subcommands"
|
||||||
_ "github.com/bedrock-tool/bedrocktool/subcommands/skins"
|
_ "github.com/bedrock-tool/bedrocktool/subcommands/skins"
|
||||||
_ "github.com/bedrock-tool/bedrocktool/subcommands/world"
|
_ "github.com/bedrock-tool/bedrocktool/subcommands/world"
|
||||||
_ "github.com/bedrock-tool/bedrocktool/ui/gui"
|
_ "github.com/bedrock-tool/bedrocktool/ui"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CLI struct {
|
type CLI struct {
|
||||||
utils.UI
|
utils.BaseUI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CLI) Init() {
|
func (c *CLI) Init() bool {
|
||||||
|
utils.SetCurrentUI(c)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CLI) SetOptions(context.Context) bool {
|
func (c *CLI) Start(ctx context.Context) error {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
return false
|
utils.InitDNS()
|
||||||
}
|
utils.InitExtraDebug()
|
||||||
|
|
||||||
func (c *CLI) Execute(ctx context.Context) error {
|
|
||||||
subcommands.Execute(ctx)
|
subcommands.Execute(ctx)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -105,53 +103,6 @@ func main() {
|
||||||
ui = &CLI{}
|
ui = &CLI{}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Init()
|
|
||||||
if ui.SetOptions(ctx) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Err() != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if utils.Options.EnableDNS {
|
|
||||||
utils.InitDNS()
|
|
||||||
}
|
|
||||||
|
|
||||||
if utils.Options.ExtraDebug {
|
|
||||||
utils.Options.Debug = true
|
|
||||||
|
|
||||||
var logPlain, logCryptEnc io.WriteCloser = nil, nil
|
|
||||||
|
|
||||||
// open plain text log
|
|
||||||
logPlain, err = os.Create("packets.log")
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
} else {
|
|
||||||
defer logPlain.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// open gpg log
|
|
||||||
logCrypt, err := os.Create("packets.log.gpg")
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
} else {
|
|
||||||
defer logCrypt.Close()
|
|
||||||
// encrypter for the log
|
|
||||||
logCryptEnc, err = crypt.Encer("packets.log", logCrypt)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
} else {
|
|
||||||
defer logCryptEnc.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.FLog = io.MultiWriter(logPlain, logCryptEnc)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// exit cleanup
|
// exit cleanup
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
@ -161,12 +112,13 @@ func main() {
|
||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ui.Execute(ctx)
|
if !ui.Init() {
|
||||||
|
logrus.Error("Failed to init UI!")
|
||||||
if utils.Options.IsInteractive {
|
return
|
||||||
logrus.Info(locale.Loc("enter_to_exit", nil))
|
}
|
||||||
input := bufio.NewScanner(os.Stdin)
|
err = ui.Start(ctx)
|
||||||
input.Scan()
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,16 +128,10 @@ type TransCMD struct {
|
||||||
|
|
||||||
func (*TransCMD) Name() string { return "trans" }
|
func (*TransCMD) Name() string { return "trans" }
|
||||||
func (*TransCMD) Synopsis() string { return "" }
|
func (*TransCMD) Synopsis() string { return "" }
|
||||||
|
|
||||||
func (c *TransCMD) SetFlags(f *flag.FlagSet) {
|
func (c *TransCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.BoolVar(&c.auth, "auth", false, locale.Loc("should_login_xbox", nil))
|
f.BoolVar(&c.auth, "auth", false, locale.Loc("should_login_xbox", nil))
|
||||||
}
|
}
|
||||||
|
func (c *TransCMD) Execute(_ context.Context, ui utils.UI) error {
|
||||||
func (c *TransCMD) Usage() string {
|
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TransCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
const (
|
const (
|
||||||
BlackFg = "\033[30m"
|
BlackFg = "\033[30m"
|
||||||
Bold = "\033[1m"
|
Bold = "\033[1m"
|
||||||
|
@ -198,7 +144,7 @@ func (c *TransCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
|
||||||
utils.GetTokenSource()
|
utils.GetTokenSource()
|
||||||
}
|
}
|
||||||
fmt.Println(BlackFg + 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateCustomDataCMD struct {
|
type CreateCustomDataCMD struct {
|
||||||
|
@ -212,11 +158,7 @@ func (c *CreateCustomDataCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.StringVar(&c.path, "path", "customdata.json", "where to save")
|
f.StringVar(&c.path, "path", "customdata.json", "where to save")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CreateCustomDataCMD) Usage() string {
|
func (c *CreateCustomDataCMD) Execute(_ context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CreateCustomDataCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
var data utils.CustomClientData
|
var data utils.CustomClientData
|
||||||
fio, err := os.Create(c.path)
|
fio, err := os.Create(c.path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -226,10 +168,9 @@ func (c *CreateCustomDataCMD) Execute(_ context.Context, f *flag.FlagSet, _ ...i
|
||||||
fio.Write(bdata)
|
fio.Write(bdata)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -49,27 +48,20 @@ type CaptureCMD struct {
|
||||||
|
|
||||||
func (*CaptureCMD) Name() string { return "capture" }
|
func (*CaptureCMD) Name() string { return "capture" }
|
||||||
func (*CaptureCMD) Synopsis() string { return locale.Loc("capture_synopsis", nil) }
|
func (*CaptureCMD) Synopsis() string { return locale.Loc("capture_synopsis", nil) }
|
||||||
|
|
||||||
func (c *CaptureCMD) SetFlags(f *flag.FlagSet) {
|
func (c *CaptureCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.StringVar(&c.ServerAddress, "address", "", "remote server address")
|
f.StringVar(&c.ServerAddress, "address", "", "remote server address")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CaptureCMD) Usage() string {
|
func (c *CaptureCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + locale.Loc("server_address_help", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Mkdir("captures", 0o775)
|
os.Mkdir("captures", 0o775)
|
||||||
fio, err := os.Create("captures/" + hostname + "-" + time.Now().Format("2006-01-02_15-04-05") + ".pcap2")
|
fio, err := os.Create("captures/" + hostname + "-" + time.Now().Format("2006-01-02_15-04-05") + ".pcap2")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
defer fio.Close()
|
defer fio.Close()
|
||||||
utils.WriteReplayHeader(fio)
|
utils.WriteReplayHeader(fio)
|
||||||
|
@ -90,8 +82,7 @@ func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interfac
|
||||||
err = proxy.Run(ctx, address)
|
err = proxy.Run(ctx, address)
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -22,33 +21,27 @@ type ChatLogCMD struct {
|
||||||
|
|
||||||
func (*ChatLogCMD) Name() string { return "chat-log" }
|
func (*ChatLogCMD) Name() string { return "chat-log" }
|
||||||
func (*ChatLogCMD) Synopsis() string { return locale.Loc("chat_log_synopsis", nil) }
|
func (*ChatLogCMD) Synopsis() string { return locale.Loc("chat_log_synopsis", nil) }
|
||||||
|
|
||||||
func (c *ChatLogCMD) SetFlags(f *flag.FlagSet) {
|
func (c *ChatLogCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.StringVar(&c.ServerAddress, "address", "", "remote server address")
|
f.StringVar(&c.ServerAddress, "address", "", "remote server address")
|
||||||
f.BoolVar(&c.Verbose, "v", false, "verbose")
|
f.BoolVar(&c.Verbose, "v", false, "verbose")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChatLogCMD) Usage() string {
|
func (c *ChatLogCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + locale.Loc("server_address_help", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChatLogCMD) Execute(ctx context.Context, flags *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := fmt.Sprintf("%s_%s_chat.log", hostname, time.Now().Format("2006-01-02_15-04-05_Z07"))
|
filename := fmt.Sprintf("%s_%s_chat.log", hostname, time.Now().Format("2006-01-02_15-04-05_Z07"))
|
||||||
f, err := os.Create(filename)
|
f, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
proxy, err := utils.NewProxy()
|
proxy, err := utils.NewProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool, _ time.Time) (packet.Packet, error) {
|
proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool, _ time.Time) (packet.Packet, error) {
|
||||||
if text, ok := pk.(*packet.Text); ok {
|
if text, ok := pk.(*packet.Text); ok {
|
||||||
|
@ -66,12 +59,8 @@ func (c *ChatLogCMD) Execute(ctx context.Context, flags *flag.FlagSet, _ ...inte
|
||||||
return pk, nil
|
return pk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := proxy.Run(ctx, address); err != nil {
|
err = proxy.Run(ctx, address)
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -7,9 +7,6 @@ import (
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DebugProxyCMD struct {
|
type DebugProxyCMD struct {
|
||||||
|
@ -19,21 +16,15 @@ type DebugProxyCMD struct {
|
||||||
|
|
||||||
func (*DebugProxyCMD) Name() string { return "debug-proxy" }
|
func (*DebugProxyCMD) Name() string { return "debug-proxy" }
|
||||||
func (*DebugProxyCMD) Synopsis() string { return locale.Loc("debug_proxy_synopsis", nil) }
|
func (*DebugProxyCMD) Synopsis() string { return locale.Loc("debug_proxy_synopsis", nil) }
|
||||||
|
|
||||||
func (c *DebugProxyCMD) SetFlags(f *flag.FlagSet) {
|
func (c *DebugProxyCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.StringVar(&c.ServerAddress, "address", "", locale.Loc("remote_address", nil))
|
f.StringVar(&c.ServerAddress, "address", "", locale.Loc("remote_address", nil))
|
||||||
f.StringVar(&c.Filter, "filter", "", locale.Loc("packet_filter", nil))
|
f.StringVar(&c.Filter, "filter", "", locale.Loc("packet_filter", nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DebugProxyCMD) Usage() string {
|
func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + locale.Loc("server_address_help", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *DebugProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
address, _, err := utils.ServerInput(ctx, c.ServerAddress)
|
address, _, err := utils.ServerInput(ctx, c.ServerAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.Options.Debug = true
|
utils.Options.Debug = true
|
||||||
|
@ -55,14 +46,10 @@ func (c *DebugProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...inter
|
||||||
|
|
||||||
proxy, err := utils.NewProxy()
|
proxy, err := utils.NewProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
if err := proxy.Run(ctx, address); err != nil {
|
err = proxy.Run(ctx, address)
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//go:build false
|
||||||
|
|
||||||
package subcommands
|
package subcommands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -9,12 +9,8 @@ import (
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
resourcepackd "github.com/bedrock-tool/bedrocktool/subcommands/resourcepack-d"
|
resourcepackd "github.com/bedrock-tool/bedrocktool/subcommands/resourcepack-d"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// decrypt using cfb with segmentsize = 1
|
|
||||||
|
|
||||||
type ResourcePackCMD struct {
|
type ResourcePackCMD struct {
|
||||||
ServerAddress string
|
ServerAddress string
|
||||||
SaveEncrypted bool
|
SaveEncrypted bool
|
||||||
|
@ -30,17 +26,8 @@ func (c *ResourcePackCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.BoolVar(&c.OnlyKeys, "only-keys", false, locale.Loc("only_keys", nil))
|
f.BoolVar(&c.OnlyKeys, "only-keys", false, locale.Loc("only_keys", nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ResourcePackCMD) Usage() string {
|
func (c *ResourcePackCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + locale.Loc("server_address_help", nil)
|
return resourcepackd.Execute_cmd(ctx, c.ServerAddress, c.OnlyKeys, c.SaveEncrypted)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ResourcePackCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
err := resourcepackd.Execute_cmd(ctx, c.ServerAddress, c.OnlyKeys, c.SaveEncrypted)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -4,11 +4,10 @@ package subcommands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResourcePackCMD struct {
|
type ResourcePackCMD struct {
|
||||||
|
@ -17,18 +16,11 @@ type ResourcePackCMD struct {
|
||||||
OnlyKeys bool
|
OnlyKeys bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*ResourcePackCMD) Name() string { return "packs" }
|
func (*ResourcePackCMD) Name() string { return "packs" }
|
||||||
func (*ResourcePackCMD) Synopsis() string { return "NOT COMPILED" }
|
func (*ResourcePackCMD) Synopsis() string { return "NOT COMPILED" }
|
||||||
|
func (*ResourcePackCMD) SetFlags(f *flag.FlagSet) {}
|
||||||
func (c *ResourcePackCMD) SetFlags(f *flag.FlagSet) {}
|
func (*ResourcePackCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
|
return errors.New("not compiled")
|
||||||
func (c *ResourcePackCMD) Usage() string {
|
|
||||||
return c.Name() + ": " + c.Synopsis()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ResourcePackCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
logrus.Error("not compiled")
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
@ -124,15 +123,10 @@ func (c *SkinCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.BoolVar(&c.NoProxy, "no-proxy", false, "use headless version")
|
f.BoolVar(&c.NoProxy, "no-proxy", false, "use headless version")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SkinCMD) Usage() string {
|
func (c *SkinCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + locale.Loc("server_address_help", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy, _ := utils.NewProxy()
|
proxy, _ := utils.NewProxy()
|
||||||
|
@ -158,10 +152,7 @@ func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = proxy.Run(ctx, address)
|
err = proxy.Run(ctx, address)
|
||||||
if err != nil {
|
return err
|
||||||
logrus.Error(err)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -8,40 +8,31 @@ import (
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpdateCMD struct{}
|
type UpdateCMD struct{}
|
||||||
|
|
||||||
func (*UpdateCMD) Name() string { return "update" }
|
func (*UpdateCMD) Name() string { return "update" }
|
||||||
func (*UpdateCMD) Synopsis() string { return locale.Loc("update_synopsis", nil) }
|
func (*UpdateCMD) Synopsis() string { return locale.Loc("update_synopsis", nil) }
|
||||||
|
|
||||||
func (c *UpdateCMD) SetFlags(f *flag.FlagSet) {}
|
func (c *UpdateCMD) SetFlags(f *flag.FlagSet) {}
|
||||||
|
|
||||||
func (c *UpdateCMD) Usage() string {
|
func (c *UpdateCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UpdateCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
newVersion, err := utils.Updater.UpdateAvailable()
|
newVersion, err := utils.Updater.UpdateAvailable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
if newVersion == "" {
|
if newVersion == "" {
|
||||||
logrus.Info(locale.Loc("no_update", nil))
|
logrus.Info(locale.Loc("no_update", nil))
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
logrus.Infof(locale.Loc("updating", locale.Strmap{"Version": newVersion}))
|
logrus.Infof(locale.Loc("updating", locale.Strmap{"Version": newVersion}))
|
||||||
|
|
||||||
if err := utils.Updater.Update(); err != nil {
|
if err := utils.Updater.Update(); err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Infof(locale.Loc("updated", nil))
|
logrus.Infof(locale.Loc("updated", nil))
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -60,9 +60,9 @@ func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) {
|
||||||
w.chunks[pk.Position] = ch
|
w.chunks[pk.Position] = ch
|
||||||
|
|
||||||
if pk.SubChunkRequestMode == protocol.SubChunkRequestModeLegacy {
|
if pk.SubChunkRequestMode == protocol.SubChunkRequestModeLegacy {
|
||||||
w.ui.SetChunk(pk.Position, ch)
|
w.mapUI.SetChunk(pk.Position, ch)
|
||||||
} else {
|
} else {
|
||||||
w.ui.SetChunk(pk.Position, nil)
|
w.mapUI.SetChunk(pk.Position, nil)
|
||||||
// request all the subchunks
|
// request all the subchunks
|
||||||
|
|
||||||
max := w.Dim.Range().Height() / 16
|
max := w.Dim.Range().Height() / 16
|
||||||
|
@ -109,9 +109,9 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) {
|
||||||
|
|
||||||
// redraw the chunks
|
// redraw the chunks
|
||||||
for pos := range posToRedraw {
|
for pos := range posToRedraw {
|
||||||
w.ui.SetChunk(pos, w.chunks[pos])
|
w.mapUI.SetChunk(pos, w.chunks[pos])
|
||||||
}
|
}
|
||||||
w.ui.SchedRedraw()
|
w.mapUI.SchedRedraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet {
|
func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet {
|
||||||
|
|
|
@ -43,7 +43,7 @@ var MapItemPacket packet.InventoryContent = packet.InventoryContent{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapUI) getBounds() (min, max protocol.ChunkPos) {
|
func (m *MapUI) GetBounds() (min, max protocol.ChunkPos) {
|
||||||
// get the chunk coord bounds
|
// get the chunk coord bounds
|
||||||
i := 0
|
i := 0
|
||||||
for _ch := range m.renderedChunks {
|
for _ch := range m.renderedChunks {
|
||||||
|
@ -75,6 +75,7 @@ type MapUI struct {
|
||||||
renderQueue *lockfree.Queue
|
renderQueue *lockfree.Queue
|
||||||
renderedChunks map[protocol.ChunkPos]*image.RGBA // prerendered chunks
|
renderedChunks map[protocol.ChunkPos]*image.RGBA // prerendered chunks
|
||||||
needRedraw bool // when the map has updated this is true
|
needRedraw bool // when the map has updated this is true
|
||||||
|
showOnGui bool
|
||||||
|
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
w *WorldState
|
w *WorldState
|
||||||
|
@ -93,6 +94,21 @@ func NewMapUI(w *WorldState) *MapUI {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapUI) Start() {
|
func (m *MapUI) Start() {
|
||||||
|
r := m.w.gui.Message("init_map", struct {
|
||||||
|
GetTiles func() map[protocol.ChunkPos]*image.RGBA
|
||||||
|
GetBounds func() (min, max protocol.ChunkPos)
|
||||||
|
}{
|
||||||
|
GetTiles: func() map[protocol.ChunkPos]*image.RGBA {
|
||||||
|
return m.renderedChunks
|
||||||
|
},
|
||||||
|
GetBounds: func() (min, max protocol.ChunkPos) {
|
||||||
|
return m.GetBounds()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if r.Ok {
|
||||||
|
m.showOnGui = true
|
||||||
|
}
|
||||||
|
|
||||||
// init map
|
// init map
|
||||||
if m.w.proxy.Client != nil {
|
if m.w.proxy.Client != nil {
|
||||||
if err := m.w.proxy.Client.WritePacket(&packet.ClientBoundMapItemData{
|
if err := m.w.proxy.Client.WritePacket(&packet.ClientBoundMapItemData{
|
||||||
|
@ -224,11 +240,15 @@ func (m *MapUI) Redraw() {
|
||||||
bmp.Encode(buf, img2)
|
bmp.Encode(buf, img2)
|
||||||
os.WriteFile("test.bmp", buf.Bytes(), 0o777)
|
os.WriteFile("test.bmp", buf.Bytes(), 0o777)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.showOnGui {
|
||||||
|
m.w.gui.Message("update_map", nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapUI) ToImage() *image.RGBA {
|
func (m *MapUI) ToImage() *image.RGBA {
|
||||||
// get the chunk coord bounds
|
// get the chunk coord bounds
|
||||||
min, max := m.getBounds()
|
min, max := m.GetBounds()
|
||||||
chunksX := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate
|
chunksX := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate
|
||||||
chunksY := int(max[1] - min[1] + 1)
|
chunksY := int(max[1] - min[1] + 1)
|
||||||
|
|
||||||
|
@ -254,8 +274,8 @@ func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) {
|
||||||
|
|
||||||
func (w *WorldState) ProcessAnimate(pk *packet.Animate) {
|
func (w *WorldState) ProcessAnimate(pk *packet.Animate) {
|
||||||
if pk.ActionType == packet.AnimateActionSwingArm {
|
if pk.ActionType == packet.AnimateActionSwingArm {
|
||||||
w.ui.ChangeZoom()
|
w.mapUI.ChangeZoom()
|
||||||
w.proxy.SendPopup(locale.Loc("zoom_level", locale.Strmap{"Level": w.ui.zoomLevel}))
|
w.proxy.SendPopup(locale.Loc("zoom_level", locale.Strmap{"Level": w.mapUI.zoomLevel}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +287,7 @@ func (w *WorldState) processMapPacketsClient(pk packet.Packet, forward *bool) pa
|
||||||
w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw)
|
w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw)
|
||||||
case *packet.MapInfoRequest:
|
case *packet.MapInfoRequest:
|
||||||
if pk.MapID == ViewMapID {
|
if pk.MapID == ViewMapID {
|
||||||
w.ui.SchedRedraw()
|
w.mapUI.SchedRedraw()
|
||||||
*forward = false
|
*forward = false
|
||||||
}
|
}
|
||||||
case *packet.Animate:
|
case *packet.Animate:
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// Package world Bedrock World Downloader
|
|
||||||
package world
|
package world
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -26,7 +25,6 @@ import (
|
||||||
"github.com/df-mc/dragonfly/server/world/mcdb"
|
"github.com/df-mc/dragonfly/server/world/mcdb"
|
||||||
"github.com/df-mc/goleveldb/leveldb/opt"
|
"github.com/df-mc/goleveldb/leveldb/opt"
|
||||||
"github.com/go-gl/mathgl/mgl32"
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -44,7 +42,8 @@ type TPlayerPos struct {
|
||||||
type WorldState struct {
|
type WorldState struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
proxy *utils.ProxyContext
|
proxy *utils.ProxyContext
|
||||||
ui *MapUI
|
mapUI *MapUI
|
||||||
|
gui utils.UI
|
||||||
bp *behaviourpack.BehaviourPack
|
bp *behaviourpack.BehaviourPack
|
||||||
|
|
||||||
// save state
|
// save state
|
||||||
|
@ -66,11 +65,12 @@ type WorldState struct {
|
||||||
experimentInventory bool
|
experimentInventory bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorldState(ctx context.Context, proxy *utils.ProxyContext, ServerName string) *WorldState {
|
func NewWorldState(ctx context.Context, proxy *utils.ProxyContext, ServerName string, ui utils.UI) *WorldState {
|
||||||
w := &WorldState{
|
w := &WorldState{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
proxy: proxy,
|
proxy: proxy,
|
||||||
ui: nil,
|
mapUI: nil,
|
||||||
|
gui: ui,
|
||||||
bp: behaviourpack.New(ServerName),
|
bp: behaviourpack.New(ServerName),
|
||||||
ServerName: ServerName,
|
ServerName: ServerName,
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ func NewWorldState(ctx context.Context, proxy *utils.ProxyContext, ServerName st
|
||||||
WorldName: "world",
|
WorldName: "world",
|
||||||
PlayerPos: TPlayerPos{},
|
PlayerPos: TPlayerPos{},
|
||||||
}
|
}
|
||||||
w.ui = NewMapUI(w)
|
w.mapUI = NewMapUI(w)
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,24 +130,18 @@ func (c *WorldCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.BoolVar(&c.ExperimentInventory, "inv", false, locale.Loc("test_block_inv", nil))
|
f.BoolVar(&c.ExperimentInventory, "inv", false, locale.Loc("test_block_inv", nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WorldCMD) Usage() string {
|
func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + locale.Loc("server_address_help", nil)
|
serverAddress, hostname, err := ui.ServerInput(ctx, c.ServerAddress)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
|
||||||
serverAddress, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy, err := utils.NewProxy()
|
proxy, err := utils.NewProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w := NewWorldState(ctx, proxy, hostname)
|
w := NewWorldState(ctx, proxy, hostname, ui)
|
||||||
w.voidGen = c.EnableVoid
|
w.voidGen = c.EnableVoid
|
||||||
w.withPacks = c.Packs
|
w.withPacks = c.Packs
|
||||||
w.saveImage = c.SaveImage
|
w.saveImage = c.SaveImage
|
||||||
|
@ -177,11 +171,10 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
|
||||||
|
|
||||||
err = w.proxy.Run(ctx, serverAddress)
|
err = w.proxy.Run(ctx, serverAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
} else {
|
|
||||||
w.SaveAndReset()
|
|
||||||
}
|
}
|
||||||
return 0
|
w.SaveAndReset()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) {
|
func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) {
|
||||||
|
@ -194,14 +187,14 @@ func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float
|
||||||
}
|
}
|
||||||
|
|
||||||
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(w.PlayerPos.Position.X()) || int(last.Position.Z()) != int(w.PlayerPos.Position.Z()) {
|
||||||
w.ui.SchedRedraw()
|
w.mapUI.SchedRedraw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldState) Reset() {
|
func (w *WorldState) Reset() {
|
||||||
w.chunks = make(map[protocol.ChunkPos]*chunk.Chunk)
|
w.chunks = make(map[protocol.ChunkPos]*chunk.Chunk)
|
||||||
w.WorldName = fmt.Sprintf("world-%d", w.worldCounter)
|
w.WorldName = fmt.Sprintf("world-%d", w.worldCounter)
|
||||||
w.ui.Reset()
|
w.mapUI.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveAndReset writes the world to a folder, resets all the chunks
|
// SaveAndReset writes the world to a folder, resets all the chunks
|
||||||
|
@ -421,7 +414,7 @@ func (w *WorldState) SaveAndReset() {
|
||||||
|
|
||||||
if w.saveImage {
|
if w.saveImage {
|
||||||
f, _ := os.Create(folder + ".png")
|
f, _ := os.Create(folder + ".png")
|
||||||
png.Encode(f, w.ui.ToImage())
|
png.Encode(f, w.mapUI.ToImage())
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,7 +478,7 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext, err error) bool {
|
||||||
|
|
||||||
w.proxy.SendMessage(locale.Loc("use_setname", nil))
|
w.proxy.SendMessage(locale.Loc("use_setname", nil))
|
||||||
|
|
||||||
w.ui.Start()
|
w.mapUI.Start()
|
||||||
|
|
||||||
proxy.AddCommand(utils.IngameCommand{
|
proxy.AddCommand(utils.IngameCommand{
|
||||||
Exec: func(cmdline []string) bool {
|
Exec: func(cmdline []string) bool {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
//go:build gui || android || true
|
//go:build gui || android
|
||||||
|
|
||||||
package gui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"fyne.io/fyne/v2/app"
|
"fyne.io/fyne/v2/app"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"github.com/bedrock-tool/bedrocktool/subcommands"
|
"github.com/bedrock-tool/bedrocktool/subcommands"
|
||||||
"github.com/bedrock-tool/bedrocktool/subcommands/skins"
|
"github.com/bedrock-tool/bedrocktool/subcommands/skins"
|
||||||
"github.com/bedrock-tool/bedrocktool/subcommands/world"
|
"github.com/bedrock-tool/bedrocktool/subcommands/world"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/ui/gui"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,12 +88,16 @@ var settings = map[string]func(utils.Command) *widget.Form{
|
||||||
}
|
}
|
||||||
|
|
||||||
type GUI struct {
|
type GUI struct {
|
||||||
utils.UI
|
utils.BaseUI
|
||||||
|
|
||||||
selected binding.String
|
commandUI gui.CommandUI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GUI) SetOptions(ctx context.Context) bool {
|
func (g *GUI) Init() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GUI) Start(ctx context.Context) error {
|
||||||
a := app.New()
|
a := app.New()
|
||||||
w := a.NewWindow("Bedrocktool")
|
w := a.NewWindow("Bedrocktool")
|
||||||
|
|
||||||
|
@ -120,11 +126,10 @@ func (g *GUI) SetOptions(ctx context.Context) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g.selected = binding.NewString()
|
selected := binding.NewString()
|
||||||
|
|
||||||
forms_box := container.NewVBox()
|
forms_box := container.NewVBox()
|
||||||
|
start_button := widget.NewButton("Start", nil)
|
||||||
var quit = true
|
l := sync.Mutex{}
|
||||||
|
|
||||||
w.SetContent(container.NewVBox(
|
w.SetContent(container.NewVBox(
|
||||||
widget.NewRichTextFromMarkdown("## Settings"),
|
widget.NewRichTextFromMarkdown("## Settings"),
|
||||||
|
@ -138,46 +143,58 @@ func (g *GUI) SetOptions(ctx context.Context) bool {
|
||||||
),
|
),
|
||||||
widget.NewRichTextFromMarkdown("# Commands"),
|
widget.NewRichTextFromMarkdown("# Commands"),
|
||||||
widget.NewSelect(entries, func(s string) {
|
widget.NewSelect(entries, func(s string) {
|
||||||
g.selected.Set(s)
|
l.Lock()
|
||||||
quit = false
|
selected.Set(s)
|
||||||
|
forms_box.RemoveAll()
|
||||||
|
forms_box.Add(forms[s])
|
||||||
|
l.Unlock()
|
||||||
}),
|
}),
|
||||||
forms_box,
|
forms_box,
|
||||||
widget.NewButton("Start", func() {
|
start_button,
|
||||||
w.Close()
|
|
||||||
}),
|
|
||||||
))
|
))
|
||||||
|
|
||||||
for _, f := range forms {
|
start_button.OnTapped = func() {
|
||||||
forms_box.Add(f)
|
sub, _ := selected.Get()
|
||||||
}
|
cmd := utils.ValidCMDs[sub]
|
||||||
g.selected.AddListener(binding.NewDataListener(func() {
|
|
||||||
v, _ := g.selected.Get()
|
u := gui.CommandUIs[sub]
|
||||||
for n, f := range forms {
|
if u != nil {
|
||||||
if n == v {
|
g.commandUI = u
|
||||||
f.Show()
|
w.SetContent(u.Layout())
|
||||||
} else {
|
|
||||||
f.Hide()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
|
||||||
|
utils.InitDNS()
|
||||||
|
utils.InitExtraDebug()
|
||||||
|
|
||||||
|
go cmd.Execute(ctx, g)
|
||||||
|
}
|
||||||
|
|
||||||
w.ShowAndRun()
|
w.ShowAndRun()
|
||||||
return quit
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GUI) Init() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GUI) Execute(ctx context.Context) error {
|
|
||||||
sub, err := g.selected.Get()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmd := utils.ValidCMDs[sub]
|
|
||||||
cmd.Execute(ctx, nil)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GUI) Message(name string, data interface{}) utils.MessageResponse {
|
||||||
|
h := g.commandUI.Handler()
|
||||||
|
if h != nil {
|
||||||
|
r := h(name, data)
|
||||||
|
if r.Ok {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r := utils.MessageResponse{
|
||||||
|
Ok: false,
|
||||||
|
Data: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "can_show_images":
|
||||||
|
r.Ok = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
utils.MakeGui = func() utils.UI {
|
utils.MakeGui = func() utils.UI {
|
||||||
return &GUI{}
|
return &GUI{}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/draw"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/canvas"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mapWidget struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
|
||||||
|
GetTiles func() map[protocol.ChunkPos]*image.RGBA
|
||||||
|
GetBounds func() (min, max protocol.ChunkPos)
|
||||||
|
|
||||||
|
pixels image.Image
|
||||||
|
w, h int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mapWidget) MinSize() fyne.Size {
|
||||||
|
return fyne.NewSize(128, 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mapWidget) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
c := container.NewMax(canvas.NewRaster(m.draw))
|
||||||
|
return widget.NewSimpleRenderer(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mapWidget) draw(w, h int) image.Image {
|
||||||
|
if m.w != w || m.h != h {
|
||||||
|
m.pixels = image.NewNRGBA(image.Rect(0, 0, w, h))
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.GetBounds == nil {
|
||||||
|
return m.pixels
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
_ = max
|
||||||
|
|
||||||
|
for pos, tile := range m.GetTiles() {
|
||||||
|
px := image.Pt(
|
||||||
|
int((pos[0]-min[0])*16),
|
||||||
|
int((pos[1]-min[1])*16),
|
||||||
|
)
|
||||||
|
draw.Draw(m.pixels.(*image.NRGBA), image.Rect(
|
||||||
|
px.X, px.Y,
|
||||||
|
px.X+16, px.Y+16,
|
||||||
|
), tile, image.Pt(0, 0), draw.Src)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.pixels
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
package gui
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HandlerFunc func(name string, data interface{}) utils.MessageResponse
|
||||||
|
|
||||||
|
type CommandUI interface {
|
||||||
|
Layout() fyne.CanvasObject
|
||||||
|
Handler() HandlerFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
var CommandUIs = map[string]CommandUI{}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type worldsUI struct {
|
||||||
|
mapElement *mapWidget
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *worldsUI) Layout() fyne.CanvasObject {
|
||||||
|
w.mapElement = &mapWidget{}
|
||||||
|
return container.NewVBox(
|
||||||
|
widget.NewRichTextFromMarkdown("# worlds Ui!"),
|
||||||
|
w.mapElement,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *worldsUI) handler(name string, data interface{}) utils.MessageResponse {
|
||||||
|
r := utils.MessageResponse{
|
||||||
|
Ok: false,
|
||||||
|
Data: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "init_map":
|
||||||
|
init_map := data.(struct {
|
||||||
|
GetTiles func() map[protocol.ChunkPos]*image.RGBA
|
||||||
|
GetBounds func() (min, max protocol.ChunkPos)
|
||||||
|
})
|
||||||
|
w.mapElement.GetBounds = init_map.GetBounds
|
||||||
|
w.mapElement.GetTiles = init_map.GetTiles
|
||||||
|
r.Ok = true
|
||||||
|
case "update_map":
|
||||||
|
w.mapElement.Refresh()
|
||||||
|
r.Ok = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *worldsUI) Handler() HandlerFunc {
|
||||||
|
return w.handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
CommandUIs["worlds"] = &worldsUI{}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package ui
|
|
@ -1,16 +1,42 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ValidCMDs = make(map[string]Command, 0)
|
var ValidCMDs = make(map[string]Command, 0)
|
||||||
|
|
||||||
type Command interface {
|
type Command interface {
|
||||||
|
Name() string
|
||||||
|
Synopsis() string
|
||||||
|
SetFlags(f *flag.FlagSet)
|
||||||
|
Execute(ctx context.Context, ui UI) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmdWrap struct {
|
||||||
subcommands.Command
|
subcommands.Command
|
||||||
|
|
||||||
|
cmd Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmdWrap) Name() string { return c.cmd.Name() }
|
||||||
|
func (c *cmdWrap) Synopsis() string { return c.cmd.Synopsis() }
|
||||||
|
func (c *cmdWrap) SetFlags(f *flag.FlagSet) { c.cmd.SetFlags(f) }
|
||||||
|
func (c *cmdWrap) Usage() string { return c.Name() + ": " + c.Synopsis() }
|
||||||
|
func (c *cmdWrap) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||||
|
err := c.cmd.Execute(ctx, currentUI)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterCommand(sub Command) {
|
func RegisterCommand(sub Command) {
|
||||||
subcommands.Register(sub, "")
|
subcommands.Register(&cmdWrap{cmd: sub}, "")
|
||||||
ValidCMDs[sub.Name()] = sub
|
ValidCMDs[sub.Name()] = sub
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,9 @@ func (d *DNSServer) handler(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitDNS() {
|
func InitDNS() {
|
||||||
|
if !Options.EnableDNS {
|
||||||
|
return
|
||||||
|
}
|
||||||
d := DNSServer{}
|
d := DNSServer{}
|
||||||
dns.HandleFunc(".", d.handler)
|
dns.HandleFunc(".", d.handler)
|
||||||
|
|
||||||
|
|
63
utils/iui.go
63
utils/iui.go
|
@ -1,6 +1,7 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -9,25 +10,56 @@ import (
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UI interface {
|
type MessageResponse struct {
|
||||||
Init()
|
Ok bool
|
||||||
SetOptions(context.Context) bool
|
Data interface{}
|
||||||
Execute(context.Context) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type InteractiveCLI struct {
|
type UI interface {
|
||||||
|
Init() bool
|
||||||
|
Start(context.Context) error
|
||||||
|
Message(name string, data interface{}) MessageResponse
|
||||||
|
ServerInput(context.Context, string) (string, string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseUI struct {
|
||||||
UI
|
UI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *InteractiveCLI) Init() {
|
func (u *BaseUI) Message(name string, data interface{}) MessageResponse {
|
||||||
|
return MessageResponse{
|
||||||
|
Ok: false,
|
||||||
|
Data: nil,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *InteractiveCLI) SetOptions(ctx context.Context) bool {
|
func (u *BaseUI) ServerInput(ctx context.Context, server string) (string, string, error) {
|
||||||
|
address, name, err := ServerInput(ctx, server)
|
||||||
|
return address, name, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentUI UI
|
||||||
|
|
||||||
|
func SetCurrentUI(ui UI) {
|
||||||
|
currentUI = ui
|
||||||
|
}
|
||||||
|
|
||||||
|
type InteractiveCLI struct {
|
||||||
|
BaseUI
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *InteractiveCLI) Init() bool {
|
||||||
|
currentUI = c
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *InteractiveCLI) Start(ctx context.Context) error {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return true
|
return nil
|
||||||
default:
|
default:
|
||||||
fmt.Println(locale.Loc("available_commands", nil))
|
fmt.Println(locale.Loc("available_commands", nil))
|
||||||
for name, cmd := range ValidCMDs {
|
for name, cmd := range ValidCMDs {
|
||||||
|
@ -37,18 +69,23 @@ func (c *InteractiveCLI) SetOptions(ctx context.Context) bool {
|
||||||
|
|
||||||
cmd, cancelled := UserInput(ctx, locale.Loc("input_command", nil))
|
cmd, cancelled := UserInput(ctx, locale.Loc("input_command", nil))
|
||||||
if cancelled {
|
if cancelled {
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
_cmd := strings.Split(cmd, " ")
|
_cmd := strings.Split(cmd, " ")
|
||||||
os.Args = append(os.Args, _cmd...)
|
os.Args = append(os.Args, _cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *InteractiveCLI) Execute(ctx context.Context) error {
|
InitDNS()
|
||||||
|
InitExtraDebug()
|
||||||
|
|
||||||
subcommands.Execute(ctx)
|
subcommands.Execute(ctx)
|
||||||
|
|
||||||
|
if Options.IsInteractive {
|
||||||
|
logrus.Info(locale.Loc("enter_to_exit", nil))
|
||||||
|
input := bufio.NewScanner(os.Stdin)
|
||||||
|
input.Scan()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/google/subcommands"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getRealm(ctx context.Context, realmName, id string) (name string, address string, err error) {
|
func getRealm(ctx context.Context, realmName, id string) (name string, address string, err error) {
|
||||||
|
@ -34,25 +32,18 @@ func getRealm(ctx context.Context, realmName, id string) (name string, address s
|
||||||
|
|
||||||
type RealmListCMD struct{}
|
type RealmListCMD struct{}
|
||||||
|
|
||||||
func (*RealmListCMD) Name() string { return "list-realms" }
|
func (*RealmListCMD) Name() string { return "list-realms" }
|
||||||
func (*RealmListCMD) Synopsis() string { return locale.Loc("list_realms_synopsis", nil) }
|
func (*RealmListCMD) Synopsis() string { return locale.Loc("list_realms_synopsis", nil) }
|
||||||
|
|
||||||
func (c *RealmListCMD) SetFlags(f *flag.FlagSet) {}
|
func (c *RealmListCMD) SetFlags(f *flag.FlagSet) {}
|
||||||
|
func (c *RealmListCMD) Execute(ctx context.Context, ui UI) error {
|
||||||
func (c *RealmListCMD) Usage() string {
|
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
logrus.Error(err)
|
return err
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
for _, realm := range realms {
|
for _, realm := range realms {
|
||||||
fmt.Println(locale.Loc("realm_list_line", locale.Strmap{"Name": realm.Name, "Id": realm.ID}))
|
fmt.Println(locale.Loc("realm_list_line", locale.Strmap{"Name": realm.Name, "Id": realm.ID}))
|
||||||
}
|
}
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -16,6 +17,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils/crypt"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/sandertv/gophertunnel/minecraft"
|
"github.com/sandertv/gophertunnel/minecraft"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -195,3 +197,40 @@ func CfbDecrypt(data []byte, key []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InitExtraDebug() {
|
||||||
|
if !Options.ExtraDebug {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Options.Debug = true
|
||||||
|
|
||||||
|
var logPlain, logCryptEnc io.WriteCloser = nil, nil
|
||||||
|
|
||||||
|
// open plain text log
|
||||||
|
logPlain, err := os.Create("packets.log")
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
} else {
|
||||||
|
defer logPlain.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// open gpg log
|
||||||
|
logCrypt, err := os.Create("packets.log.gpg")
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
} else {
|
||||||
|
defer logCrypt.Close()
|
||||||
|
// encrypter for the log
|
||||||
|
logCryptEnc, err = crypt.Encer("packets.log", logCrypt)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
} else {
|
||||||
|
defer logCryptEnc.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLog = io.MultiWriter(logPlain, logCryptEnc)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue