вступление
Я возился с системой зрителей для LoL в надежде в конечном итоге собрать данные из потоков и создать из них набор данных для анализа. Я понимаю, что уже есть некоторые неофициальные API и методы, но я ищу действительно специфические игровые события (убийства чемпионов, убийства турелей, покупки предметов, убийства мобов в джунглях, команды чемпионов для определенных событий и т. Д.).
Что я понял до сих пор
Когда вы начинаете наблюдать за игрой (в NA), ваш клиент подключается к следующему хосту:
spectator.na.lol.riotgames.com:8088
Я предполагаю, что этот хост поддерживается Amazon AWS или аналогичным. В любом случае, следующее, что происходит, - клиент отправляет запрос версии на сервер наблюдений:
GET / режим наблюдателя / отдых / потребитель / версия
Это возвращает независимо от текущей версии сервера зрителя. Например: 1.80.54
Далее клиент отправляет запрос на метаданные игры:
GET / режим наблюдателя / отдых / потребитель / getGameMetaData / NA1 / [gameid] / [некоторый случайный nonce] / токен
Это возвращает метаданные об игре. Пример этих данных: http://pastebin.com/3N4qs0hx
Теперь клиент знает параметры, по которым должен происходить сеанс зрителя. Он пытается найти последний блок данных, вызвав:
GET / режим наблюдателя / отдых / потребитель / getLastChunkInfo / NA1 / [gameid] / 30000 / токен
Образец этих данных: http://pastebin.com/Cj7dEAr9
Как только порции данных были идентифицированы, они запрашиваются:
GET / режим наблюдателя / отдых / потребитель / getGameDataChunk / NA1 / [gameid] / [token #] / token
Пример данных токена (двоичный код, преобразованный в шестнадцатеричный формат): http: // pastebin.com / GyqPRP5J
Игра проходит между вызовами getLastChunkInfo и getGameDataChunk, когда данные становятся доступными из потока воспроизведения. Существует также вызов, который происходит после того, как примерно 5 блоков перехвачены следующим:
GET / режим наблюдателя / отдых / потребитель / getKeyFrame / NA1 / [gameid] / [somechunkid] / token
Я считаю, что этот вызов происходит только при запуске воспроизведения и всякий раз, когда пользователь ищет другое время.
Я знаю, что игра использует шифрование на каком-то уровне. Я считаю, что это Blowfish ECB с фактическим ключом, указанным в командной строке. Я попытался расшифровать эти токены с помощью ключа сеанса, но они все еще выглядят довольно случайными.
Изменить 23.03.2013
- Я определил, что токены, скорее всего, не зашифрованы, изменив аргумент командной строки, содержащий ключ, и перезапустив игру из отладчика (он правильно загрузил воспроизведение).
Жетоны кажутся сжатыми. Есть вызов подпрограммы, которая, если возвращает ненулевое целое число, вызовет следующее:
if ( sub_B71120(v21, v15, (int *)&Size, *(_DWORD *)(v6 + 108)) ) { sub_BAD700( (int)"!\"Error Decompressing data chunk.\"", (int)"D:\\jenkins\\workspace\\Code-CI-Releases-Public\\code\\HeroWars_clientServer\\Sources\\ReplaySystem\\ReplayServerConnection.cpp", 6, (int)"Riot::Replay::ReplayServerConnection::GetChunk", (int)"Assert occurred, game may crash."); sub_9BB750("ReplayServerConnection GetChunk error. Error decompressing chunk data. Error: %d\n"); }
После исследования sub_B71120 я обнаружил вызов, который в итоге входит в довольно большую функцию. Эта функция содержит строки вроде:
- "неверная проверка заголовка"
- «неизвестный метод сжатия»
- "неверный размер окна"
Быстрый поиск в Google этих строк показывает следующее: http://www.opensource.apple.com/source/zlib/zlib-22/zlib/inflate.c
Я также нашел ссылку на строку «1.2.3» в вызове функции непосредственно перед вызовом метода inflate.c, а также другую ссылку «inflate 1.2.3 Copyright 1995-2005 Mark Adler». Похоже, что они используют Zlib версии 1.2.3 для распаковки токенов. Я просто не могу заставить их распаковать, независимо от того, с какого файла я начинаю смещение.
Мои вопросы)
Кто-нибудь знает, как эти «токены» могут быть отформатированы или есть какой-то тип сжатия / шифрования, о котором я не знаю? У меня есть подозрение, что они представляют собой сжатую или упакованную форму пакетов Ethernet, используемых во время живого воспроизведения, которые просто воспроизводятся внутри клиента.
В качестве альтернативы, может кто-нибудь придумать какой-то другой метод, с помощью которого можно очистить эти данные без запуска реального игрового клиента? Имейте в виду, я хотел бы получить данные из многих потоков одновременно.