Почему и зачем: длинная и необязательная преамбула
Хорошо, что опыта игрового модостроительства у меня было немного — так, пару кастомных прицелов для Deer Hunter 2005 и «нелицензионный» недоклиент
с сопутствущим «взломом» протокола последнего. Ещё лучше, что ни разу не приходилось с головой погружаться в сколь-нибудь трудоёмкую и длительную отладку и дизассемблирование. То есть, с IDA и OllyDBG я поверхностно знаком, но не как с ежедневными рабочими инструментами.
В WOT играю с начала 2022 года. Не запоем, а, скорее, набегами — по 5-6 боёв вечером. Было время 2 года назад, наш клан состоял в Красном Альянсе, ходил на глобалку по ночам, выполнял какие-то тактические задачи на европейском ТВД, устраивал тренировки и спарринги, вовсю бурлили внутриигровые политические страсти, отпочковывались учебные кланы. Сейчас всего этого уже нет, и наш золотой ёжик превратился в табличку над «Домом Ветеранов».
Впадать в ересь сравнения танков с другими MMO не буду, так как хорошо знаком только с танками. Тем более не знаком ни с одним другим проектом, использующим BigWorld, поэтому искренне верю WarGaming’у на слово, что существуют и (не)тривиально (не)преодолеваются различные техномагические ограничения движка — на размер карты, на максимальную скорость юнита, на численность команд и прочее.
Оставаясь в рамках внутренней критики, я также понимаю, что, с точки зрения целевой аудитории танков вообще, и их активного игрового коммьюнити в частности, каждое нововведение из очередного патча, безусловно, гораздо более востребовано и обосновано, сколь бы малым оно ни было.
Итак, я уверен, что в обозримом будущем никаких планов по введению полноценного режима спектатора в WOT нет и не будет. Под полноценным режимом спектатора я понимаю множественные подключения игроков в сеанс боя изначально как невзаимодействующих на игру «привидений»-наблюдателей, а не на технике.
Это тот самый режим, из-за отсутствия которого комментаторы на чемпионатах WOT вынуждены заходить в бой 15-м танком, убиваемым своими на базе. Это тот самый режим, из-за которого появились моды «командирского zoom» и «кинематографической камеры» — по сути, просто костыли.
А нужен такой режим затем, чтобы командир роты занимался командованием, а не скакал впереди на лихом танке по-чапаевски, чтобы он видел ситуацию на карте в целом непрерывно, а не отвлекался на неё в пылу нападения из засады. В идеале, командиру даже не нужны красоты трёхмерного мира — достаточно одной большой карты на весь монитор с игровой ситуацией в реальном времени — HP, повреждениями модулей, членов экипажа, направлениями стволов и прицелов союзной техники, засвеченных в каждый момент вражеских юнитов и прочей вспомогательной информации.
WOT предоставляет широкие возможности модостроительства, но такая идея выходит за рамки классического «заменить пару swf-файлов на свои». Потребуется перехват и разбор самого игрового протокола для того, чтобы иметь возможность передать на командирский планшет своё видение игровой ситуации.
Что же там внутри?
Здесь матёрые гуру реверс-инжиниринга, в духе
подумают: «ага, ну теперь можно написать на питонеэзотерическом языке вот такой скриптплагин для олькииды, который будет делать с этими данными всё что хочешь и даже за пивом сбегает». Но мы пойдём другим путём. Я хочу сразу ориентироваться на то, что ещё до того, как дело дойдёт до разработки командирского планшета, то есть даже для самого полноценного разбора протокола WOT мне понадобятся помощники и тестировщики, далёкие от мира программирования. Им нужен будет простой инструмент с понятным интерфейсом, выдающий легко читаемые данные.
Так что предвидя скептические ухмылки, я засел за Lazarus и набросал в нём специализированный win32-отладчик, основной функцией которого является поставить два INT3-брекпоинта в нужных местах и по их срабатыванию вытаскивать данные по адресу и длине буфера, лежащим на стеке по известным смещениям.
А вот так он себя ведёт уже находясь в ангаре.
Какие выводы можно сделать, даже не смотря на пояснения к пакетам, которые я поленился убрать для этих скриншотов? Сразу несколько.
Во-первых, видно, что все пакеты начинаются либо с 0x48, либо с 0x58, либо с 0x78; какой-нибудь закономерности на этот счёт я ещё не уловил, кроме того, что пакеты с уже известной функцией свой значащий байт не меняют.
Во-вторых, почти в каждом пакете есть один или несколько счётчиков сообщений; например, в keep-alive и ответах на них этим занимается третий и четвёртый байт в заголовке, кроме того сам пакет содержит ещё счётчик сообщений общий (включая keep-alive) и какой-то специфический (считающий пакеты без учёта количества keep-alive); всё это имеет отношение к контролю доставки пакетов, который пришлось прикрутить к UDP, вероятно, для оценки потерь и пересылки BLOBов (об этом позже).
Размеры всех пакетов выравнены по границам 8 байт, что ненавязчиво указывает нам на размер блока всё того же BlowFish; пока я до этого догадался, прошло немало времени в попытках обьяснить странную «контрольную сумму» в конце, да ещё и переменной длины. В конце концов, получив в этом паддинге вместо простого мусора слово «Flags» я, наконец, прозрел.
Ну и в лучших хакерских традициях, в конце каждого пакета находится сигнатура мёртвой говядины; кто бы мог подумать где мы её найдём 🙂
После получения Session ID от сервера приезжает пакет, содержащий номер игрока в неожиданно текстовом формате (792067). А вот пакет, который начинается на 0x78 0x00 на первом скриншоте — особо интересен. Сочетание сигнатуры 0x80 0x20 вкупе с тем, что перед каждым строковым литералом в нём стоит 0x55 и байт длины строки, а после каждого 0x71 находится возрастающий номер, должно насторожить опытных питонщиков — это же, чёрт побери, Python Pickle со своим запихиванием всего подряд в мемо! Вот он такой:
Dct[15]:(xmpp_host = wot-ru.loc captchaKey = 6Lc8GcASAAAAAKffZdxeZZvOvmSTNXbZvsy6CgBR voipDomain = www.wotp.vivox.com file_server = Dct[6]:(clan_emblems_small = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/clans/emblems/%d/emblem_32x32.png) clan_emblems_big = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/clans/emblems/%d/emblem_64x64.png) rare_achievements_images_big = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/achievements/medals/180x180/%d.png) clan_emblems = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/clans/emblems/%d/emblem_64x64_tank.png) rare_achievements_images = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/achievements/medals/67x71/%d.png) rare_achievements_texts = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/achievements/medals/medals_%s.xml)) newbieBattlesCount = 100 roaming = Lst[4]:(1,1,Lst[3]:(Lst[4]:(1,1,499999999,RU),Lst[4]:(2,500000000,999999999,EU),Lst[4]:(3,1000000000,1499999999,NA)),Lst[0]:()) xmpp_enabled = True jdCutouts = 0 xmpp_port = 5222 isTutorialEnabled = True wallet = Lst[2]:(True,True) xmpp_connections = Lst[1]:(Lst[2]:(xmppcs.worldoftanks.net,5222)) xmpp_resource = wot regional_settings = Dct[2]:(starting_day_of_a_new_week = 0 starting_time_of_a_new_day = 0) reCaptchaParser = )
В следующей части, если она заинтересует уважаемых обитателей Хабра, я расскажу о том, как в протоколе WOT передаются файлы, размеры которых намного больше реалистичного размера UDP пакета и MTU. И о том, что эти файлы оказывается сжатыми zlib’ом а внутри у них всё тот же Python Pickle с разными неожиданными вещами.
Спасибо за внимание!
UPD. Свежие новости! По агентурным данным из самого сердца КВГ, мой лёгкий намёк на потенциал коммерческого использования командирского планшета поднял «небольшой бугурт» (дословно), в результате чего кровавые модераторы в полнейшей панике наконец заметили и слили в мусорник тему проекта на официальном форуме танков, а мне было доверительным шёпотом посоветовано замылить данные своего аккаунта на скриншотах.
Я, имярек, находясь в здравом уме и трезвой памяти, торжественно клянусь, что разработка эта имеет исключительно академический характер, клянусь никогда в жизни не покупать компанию WarGaming.net за несметные миллиарды, вырученные от продажи ещё даже не существующей разработки либо иным способом покушаться на финансовое благополучие любимой фирмы! Аминь.
UPD2.
Выбор танков для игры
- Танки должны автоматически ремонтироваться и пополняться снарядами
- В данной версии движение и выцеливание средствами САУ не реализовано
Настройка движения (вероятности)
- Разговорчики — вероятность того, что бот будет писать в чат
- Поворот на ходу — вероятность смены направления движения на случайное значение во время движения прямо
- Остановка на ходу — вероятность смены направления движения на случайное значение во время движения прямо
Опции поведения
- Остановка при наведении — танк будет останавливаться при нацеливании
- Искать цели — танк будет крутить башней в поисках вражеской цели
- Стрелять по целям — при сведении на цели танк будет стрелять
Запуск всегда начинается с ангара!
Для экстренной остановки скрипта нажмите END на клавиатуре (глобальная горячая клавиша).
Для выхода из режима управления танка ботом, не завершая скрипт сделайте окно с игрой неактивной.
От автора
Скрипт бота писался исключительно из естествоиспытательских и образовательных целей.
Проект призван реализовать алгоритм, максимально приближающий поведение бота в игре, к
поведению полноценного полезного члена команды.