warbot.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // package warbot -- бот для игры в wartank
  2. package warbot
  3. import (
  4. "context"
  5. "fmt"
  6. "log"
  7. "strings"
  8. "time"
  9. "wartank/pkg/alias"
  10. . "wartank/pkg/kernel/kernel_types"
  11. "wartank/pkg/kernel/logger"
  12. "wartank/pkg/kernel/safe_bool"
  13. . "wartank/server/lev0/types"
  14. "wartank/server/serv_bots/warbot/angar"
  15. "wartank/server/serv_bots/warbot/stat_tank"
  16. "wartank/server/serv_bots/warbot/warbot_config"
  17. "wartank/server/serv_bots/warbot/warbot_net"
  18. )
  19. // ВарБот -- бот для игры в вартанк
  20. type ВарБот struct {
  21. сервер ИСервер
  22. store ИХранилище
  23. стата ИТанкСтат
  24. errFinal error // Финальная ошибка работы, если была
  25. ангар ИАнгар
  26. сеть ИБотСеть
  27. еслиРаботает *safe_bool.БезопБул
  28. еслиАвтозапуск *safe_bool.БезопБул
  29. конфиг *warbot_config.ВарБотКонфиг // Конфиг бота для хранения в базе
  30. кнт context.Context // Контекст бота
  31. фтОтмена func() // Функция отменя контекста бота
  32. лог ИЛоггер
  33. }
  34. // ЗагрузитьВарБот -- загружает бота из базы
  35. func ЗагрузитьВарБот(сервер ИСервер, номер alias.БотНомер) *ВарБот {
  36. лог := logger.НовЛоггер("ВарБот")
  37. лог.Инфо("ЗагрузитьВарБот()\n")
  38. лог.Паника(сервер == nil, "ЗагрузитьВарБот(): ИСервер ==nil")
  39. лог.Паника(номер == 0, "ЗагрузитьВарБот(): номер пустой")
  40. стрНомер := fmt.Sprint(номер)
  41. log.Printf("ЗагрузитьВарБот(): номер=%q\n", стрНомер)
  42. store := сервер.Хранилище()
  43. binData, err := store.Получ("/bots/" + стрНомер)
  44. if err != nil {
  45. if !strings.Contains(err.Error(), "not found") {
  46. лог.Паника(true, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err)
  47. }
  48. лог.Паника(err != nil, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err)
  49. }
  50. конфиг := &warbot_config.ВарБотКонфиг{}
  51. конфиг.Unmarshal(binData)
  52. сам := создатьЯдроВарБот(сервер, конфиг)
  53. go сам.рестарт()
  54. _ = ИБот(сам)
  55. return сам
  56. }
  57. // Каждые два часа перезапускает себя
  58. func (сам *ВарБот) рестарт() {
  59. time.Sleep(time.Hour * 2)
  60. сам.сервер.Отменить()
  61. log.Printf("ВарБот.рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_)
  62. }
  63. // НовВарБот -- возвращает новый WarBot
  64. func НовВарБот(сервер ИСервер, номер alias.БотНомер, логин, пароль string, еслиАвто bool) *ВарБот {
  65. лог := logger.НовЛоггер("ВарБот")
  66. лог.Инфо("НовВарБот()\n")
  67. лог.Паника(сервер == nil, "НовВарБот(): ИСервер == nil")
  68. лог.Паника(логин == "", "НовВарБот(): логин пустой")
  69. лог.Паника(пароль == "", "НовВарБот(): пароль пустой")
  70. log.Printf("НовВарБот(): name=%q\n", логин)
  71. config := &warbot_config.ВарБотКонфиг{
  72. ЕслиАвтозапуск_: еслиАвто,
  73. Логин_: логин,
  74. Пароль_: пароль,
  75. Номер_: номер,
  76. }
  77. сам := создатьЯдроВарБот(сервер, config)
  78. сам.сохр()
  79. _ = ИБот(сам)
  80. return сам
  81. }
  82. // Создаёт ядро бота
  83. func создатьЯдроВарБот(серв ИСервер, конфиг *warbot_config.ВарБотКонфиг) *ВарБот {
  84. лог := logger.НовЛоггер("ВарБот")
  85. лог.Инфо("создатьЯдроВарБот()\n")
  86. лог.Паника(серв == nil, "создатьЯдроВарБот(): ИСервер == nil")
  87. лог.Паника(конфиг == nil, "создатьЯдроВарБот(): ВарБотКонфиг==nil")
  88. ctx, fnCancel := context.WithCancel(серв.Контекст())
  89. сам := &ВарБот{
  90. сервер: серв,
  91. store: серв.Хранилище(),
  92. стата: stat_tank.НовТанкСтат(),
  93. еслиРаботает: safe_bool.НовБезопБул(),
  94. еслиАвтозапуск: safe_bool.НовБезопБул(),
  95. конфиг: конфиг,
  96. кнт: ctx,
  97. фтОтмена: fnCancel,
  98. лог: лог,
  99. }
  100. var err error
  101. // WarBotNet
  102. сам.сеть = warbot_net.НовВарБотСеть(сам)
  103. сам.ангар, err = angar.НовАнгар(сам)
  104. сам.лог.Паника(err != nil, "НовВарБот(): in make IAngar, err=\n\t%w", err)
  105. if сам.конфиг.ЕслиАвтозапуск_ {
  106. сам.еслиАвтозапуск.Уст()
  107. сам.Пуск()
  108. }
  109. return сам
  110. }
  111. // Сервер -- возвращает ссылку на объект сервера
  112. func (сам *ВарБот) Сервер() ИСервер {
  113. return сам.сервер
  114. }
  115. // ЕслиПуск -- возвращает признак, что бот подключен
  116. func (сам *ВарБот) ЕслиПуск() bool {
  117. return сам.еслиРаботает.Получ()
  118. }
  119. // Номер -- возвращает номер бота
  120. func (сам *ВарБот) Номер() alias.БотНомер {
  121. return сам.конфиг.Номер()
  122. }
  123. // Имя -- возвращает имя бота
  124. func (сам *ВарБот) Имя() string {
  125. return сам.конфиг.Логин()
  126. }
  127. // Пароль -- возвращает пароль бота
  128. func (сам *ВарБот) Пароль() string {
  129. return сам.конфиг.Пароль_
  130. }
  131. // Пуск -- запускает бот в работу
  132. func (сам *ВарБот) Пуск() {
  133. if сам.еслиРаботает.Получ() {
  134. return
  135. }
  136. сам.ангар.Пуск()
  137. сам.еслиРаботает.Уст()
  138. }
  139. // Error -- возвращает финальную ошибку работы, если была
  140. func (сам *ВарБот) Error() error {
  141. return сам.errFinal
  142. }
  143. // Ангар -- возвращает ангар игры
  144. func (сам *ВарБот) Ангар() ИАнгар {
  145. return сам.ангар
  146. }
  147. // Стата -- возвращает статистику танка
  148. func (сам *ВарБот) Стата() ИТанкСтат {
  149. return сам.стата
  150. }
  151. // Сеть -- возвращает ссылку на свой сетевой клиент
  152. func (сам *ВарБот) Сеть() ИБотСеть {
  153. return сам.сеть
  154. }
  155. // АвтоИграЕсли -- возвращает признак автоматического запуска бота
  156. func (сам *ВарБот) АвтоИграЕсли() bool {
  157. return сам.еслиАвтозапуск.Получ()
  158. }
  159. // АвтоИграУст -- устанавливает признак автоматического запуска бота
  160. func (сам *ВарБот) АвтоИграУст() {
  161. log.Printf("WarBot.SetAutoGame()")
  162. сам.еслиАвтозапуск.Уст()
  163. сам.конфиг.ЕслиАвтозапуск_ = true
  164. сам.сохрКонфиг()
  165. }
  166. // АвтоИграСброс -- сбрасывает признак автоматического запуска бота
  167. func (сам *ВарБот) АвтоИграСброс() {
  168. log.Printf("WarBot.ResetAutoGame()")
  169. сам.еслиАвтозапуск.Уст()
  170. сам.конфиг.ЕслиАвтозапуск_ = false
  171. сам.сохрКонфиг()
  172. }
  173. // Сохраняет конфиг бота
  174. func (сам *ВарБот) сохрКонфиг() {
  175. log.Printf("ВарБот.сохрКонфиг()")
  176. strConf := сам.конфиг.Marshall()
  177. err := сам.store.Уст("/bots/"+сам.Имя(), strConf)
  178. if err != nil {
  179. log.Printf("ВарБот.сохрКонфиг(): err=\n\t%v\n", err)
  180. }
  181. }
  182. // Контекст -- возвращает контекст бота
  183. func (сам *ВарБот) Контекст() context.Context {
  184. return сам.кнт
  185. }
  186. // Закончить -- отменяет контекст бота
  187. func (сам *ВарБот) Закончить() {
  188. сам.фтОтмена()
  189. }
  190. // Сохраняет себя в базу
  191. func (сам *ВарБот) сохр() {
  192. стрНомер := fmt.Sprint(сам.Номер())
  193. err := сам.store.Уст("/bots/"+стрНомер, сам.конфиг.Marshall())
  194. сам.лог.Паника(err != nil, "ВарБот.сохр(): err=\n\t%v\n", err)
  195. }