package mc import ( "errors" "fmt" "log" "strings" "tg-mc/conf" "time" "github.com/Tnze/go-mc/bot" "github.com/Tnze/go-mc/bot/basic" "github.com/Tnze/go-mc/bot/msg" "github.com/Tnze/go-mc/bot/playerlist" "github.com/Tnze/go-mc/bot/screen" "github.com/Tnze/go-mc/chat" "github.com/Tnze/go-mc/data/item" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) func Run() error { conf.Client = bot.NewClient() conf.Client.Auth.Name = conf.GetBotSettings().MCBotName client := conf.Client conf.Player = basic.NewPlayer(client, basic.DefaultSettings, basic.EventsListener{ GameStart: onGameStart, Disconnect: onDisconnect, HealthChange: onHealthChange, Death: onDeath, }) conf.PlayerList = playerlist.New(client) conf.ChatHandler = msg.New(client, conf.Player, conf.PlayerList, msg.EventsHandler{ SystemChat: onSystemMsg, PlayerChatMessage: onPlayerMsg, DisguisedChat: onDisguisedMsg, }) conf.ScreenManager = screen.NewManager(client, screen.EventsListener{ Open: nil, SetSlot: onScreenSlotChange, Close: nil, }) err := client.JoinServer( conf.GetBotSettings().MCServer, ) if err != nil { log.Fatal(err) } log.Println("Login success") var perr bot.PacketHandlerError for { if err = client.HandleGame(); err == nil { return errors.New("handle game error") } if errors.As(err, &perr) { return err } else { return err } } } func SendMsg(msg string) error { if err := conf.ChatHandler.SendMessage(msg); err != nil { return err } return nil } func onSystemMsg(msg chat.Message, overlay bool) error { log.Printf("System: %v", msg) m := tgbotapi.NewMessage(conf.GetBotSettings().GroupID, fmt.Sprintf("%v", msg)) conf.Bot.Send(m) return nil } func onPlayerMsg(msg chat.Message, validated bool) error { log.Printf("Player: %s", msg) s := strings.Split(msg.String(), " ") if len(s) > 1 { if s[0] != fmt.Sprintf("<%v>", conf.GetBotSettings().MCBotName) { m := tgbotapi.NewMessage(conf.GetBotSettings().GroupID, fmt.Sprintf("%v", msg)) conf.Bot.Send(m) } } return nil } func onDisguisedMsg(msg chat.Message) error { log.Printf("Disguised: %v", msg) m := tgbotapi.NewMessage(conf.GetBotSettings().GroupID, fmt.Sprintf("%v", msg)) conf.Bot.Send(m) return nil } func onDeath() error { log.Println("Died and Respawned") // If we exclude Respawn(...) then the player won't press the "Respawn" button upon death go func() { time.Sleep(time.Second * 5) err := conf.Player.Respawn() if err != nil { log.Print(err) } }() return nil } func onGameStart() error { log.Println("Game start") if err := conf.ChatHandler.SendMessage("Hello, world"); err != nil { return err } return nil // if err isn't nil, HandleGame() will return it. } func onScreenSlotChange(id, index int) error { if id == -2 { log.Printf("Slot: inventory: %v", conf.ScreenManager.Inventory.Slots[index]) } else if id == -1 && index == -1 { log.Printf("Slot: cursor: %v", conf.ScreenManager.Cursor) } else { container, ok := conf.ScreenManager.Screens[id] if ok { // Currently, only inventory container is supported switch container.(type) { case *screen.Inventory: slot := container.(*screen.Inventory).Slots[index] itemInfo := item.ByID[item.ID(slot.ID)] log.Printf("Slot: Screen[%d].Slot[%d]: [%v] * %d | NBT: %v", id, index, itemInfo, slot.Count, slot.NBT) } } } return nil } func onHealthChange(health float32, foodLevel int32, foodSaturation float32) error { log.Printf("Health: %.2f, FoodLevel: %d, FoodSaturation: %.2f", health, foodLevel, foodSaturation) return nil } type DisconnectErr struct { Reason chat.Message } func (d DisconnectErr) Error() string { return "disconnect: " + d.Reason.String() } func onDisconnect(reason chat.Message) error { // return an error value so that we can stop main loop return DisconnectErr{Reason: reason} }