// package warbot -- бот для игры в wartank package warbot import ( "context" "fmt" "log" "strings" "time" "wartank/pkg/alias" . "wartank/pkg/kernel/kernel_types" "wartank/pkg/kernel/logger" "wartank/pkg/kernel/safe_bool" . "wartank/server/lev0/types" "wartank/server/serv_bots/warbot/angar" "wartank/server/serv_bots/warbot/stat_tank" "wartank/server/serv_bots/warbot/warbot_config" "wartank/server/serv_bots/warbot/warbot_net" ) // ВарБот -- бот для игры в вартанк type ВарБот struct { сервер ИСервер store ИХранилище стата ИТанкСтат errFinal error // Финальная ошибка работы, если была ангар ИАнгар сеть ИБотСеть еслиРаботает *safe_bool.БезопБул еслиАвтозапуск *safe_bool.БезопБул конфиг *warbot_config.ВарБотКонфиг // Конфиг бота для хранения в базе кнт context.Context // Контекст бота фтОтмена func() // Функция отменя контекста бота лог ИЛоггер } // ЗагрузитьВарБот -- загружает бота из базы func ЗагрузитьВарБот(сервер ИСервер, номер alias.БотНомер) *ВарБот { лог := logger.НовЛоггер("ВарБот") лог.Инфо("ЗагрузитьВарБот()\n") лог.Паника(сервер == nil, "ЗагрузитьВарБот(): ИСервер ==nil") лог.Паника(номер == 0, "ЗагрузитьВарБот(): номер пустой") стрНомер := fmt.Sprint(номер) log.Printf("ЗагрузитьВарБот(): номер=%q\n", стрНомер) store := сервер.Хранилище() binData, err := store.Получ("/bots/" + стрНомер) if err != nil { if !strings.Contains(err.Error(), "not found") { лог.Паника(true, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err) } лог.Паника(err != nil, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err) } конфиг := &warbot_config.ВарБотКонфиг{} конфиг.Unmarshal(binData) сам := создатьЯдроВарБот(сервер, конфиг) go сам.рестарт() _ = ИБот(сам) return сам } // Каждые два часа перезапускает себя func (сам *ВарБот) рестарт() { time.Sleep(time.Hour * 2) сам.сервер.Отменить() log.Printf("ВарБот.рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_) } // НовВарБот -- возвращает новый WarBot func НовВарБот(сервер ИСервер, номер alias.БотНомер, логин, пароль string, еслиАвто bool) *ВарБот { лог := logger.НовЛоггер("ВарБот") лог.Инфо("НовВарБот()\n") лог.Паника(сервер == nil, "НовВарБот(): ИСервер == nil") лог.Паника(логин == "", "НовВарБот(): логин пустой") лог.Паника(пароль == "", "НовВарБот(): пароль пустой") log.Printf("НовВарБот(): name=%q\n", логин) config := &warbot_config.ВарБотКонфиг{ ЕслиАвтозапуск_: еслиАвто, Логин_: логин, Пароль_: пароль, Номер_: номер, } сам := создатьЯдроВарБот(сервер, config) сам.сохр() _ = ИБот(сам) return сам } // Создаёт ядро бота func создатьЯдроВарБот(серв ИСервер, конфиг *warbot_config.ВарБотКонфиг) *ВарБот { лог := logger.НовЛоггер("ВарБот") лог.Инфо("создатьЯдроВарБот()\n") лог.Паника(серв == nil, "создатьЯдроВарБот(): ИСервер == nil") лог.Паника(конфиг == nil, "создатьЯдроВарБот(): ВарБотКонфиг==nil") ctx, fnCancel := context.WithCancel(серв.Контекст()) сам := &ВарБот{ сервер: серв, store: серв.Хранилище(), стата: stat_tank.НовТанкСтат(), еслиРаботает: safe_bool.НовБезопБул(), еслиАвтозапуск: safe_bool.НовБезопБул(), конфиг: конфиг, кнт: ctx, фтОтмена: fnCancel, лог: лог, } var err error // WarBotNet сам.сеть = warbot_net.НовВарБотСеть(сам) сам.ангар, err = angar.НовАнгар(сам) сам.лог.Паника(err != nil, "НовВарБот(): in make IAngar, err=\n\t%w", err) if сам.конфиг.ЕслиАвтозапуск_ { сам.еслиАвтозапуск.Уст() сам.Пуск() } return сам } // Сервер -- возвращает ссылку на объект сервера func (сам *ВарБот) Сервер() ИСервер { return сам.сервер } // ЕслиПуск -- возвращает признак, что бот подключен func (сам *ВарБот) ЕслиПуск() bool { return сам.еслиРаботает.Получ() } // Номер -- возвращает номер бота func (сам *ВарБот) Номер() alias.БотНомер { return сам.конфиг.Номер() } // Имя -- возвращает имя бота func (сам *ВарБот) Имя() string { return сам.конфиг.Логин() } // Пароль -- возвращает пароль бота func (сам *ВарБот) Пароль() string { return сам.конфиг.Пароль_ } // Пуск -- запускает бот в работу func (сам *ВарБот) Пуск() { if сам.еслиРаботает.Получ() { return } сам.ангар.Пуск() сам.еслиРаботает.Уст() } // Error -- возвращает финальную ошибку работы, если была func (сам *ВарБот) Error() error { return сам.errFinal } // Ангар -- возвращает ангар игры func (сам *ВарБот) Ангар() ИАнгар { return сам.ангар } // Стата -- возвращает статистику танка func (сам *ВарБот) Стата() ИТанкСтат { return сам.стата } // Сеть -- возвращает ссылку на свой сетевой клиент func (сам *ВарБот) Сеть() ИБотСеть { return сам.сеть } // АвтоИграЕсли -- возвращает признак автоматического запуска бота func (сам *ВарБот) АвтоИграЕсли() bool { return сам.еслиАвтозапуск.Получ() } // АвтоИграУст -- устанавливает признак автоматического запуска бота func (сам *ВарБот) АвтоИграУст() { log.Printf("WarBot.SetAutoGame()") сам.еслиАвтозапуск.Уст() сам.конфиг.ЕслиАвтозапуск_ = true сам.сохрКонфиг() } // АвтоИграСброс -- сбрасывает признак автоматического запуска бота func (сам *ВарБот) АвтоИграСброс() { log.Printf("WarBot.ResetAutoGame()") сам.еслиАвтозапуск.Уст() сам.конфиг.ЕслиАвтозапуск_ = false сам.сохрКонфиг() } // Сохраняет конфиг бота func (сам *ВарБот) сохрКонфиг() { log.Printf("ВарБот.сохрКонфиг()") strConf := сам.конфиг.Marshall() err := сам.store.Уст("/bots/"+сам.Имя(), strConf) if err != nil { log.Printf("ВарБот.сохрКонфиг(): err=\n\t%v\n", err) } } // Контекст -- возвращает контекст бота func (сам *ВарБот) Контекст() context.Context { return сам.кнт } // Закончить -- отменяет контекст бота func (сам *ВарБот) Закончить() { сам.фтОтмена() } // Сохраняет себя в базу func (сам *ВарБот) сохр() { стрНомер := fmt.Sprint(сам.Номер()) err := сам.store.Уст("/bots/"+стрНомер, сам.конфиг.Marshall()) сам.лог.Паника(err != nil, "ВарБот.сохр(): err=\n\t%v\n", err) }