Introdução
Eu tenho mexido com o sistema espectador para LoL na esperança de eventualmente extrair dados dos fluxos e construir um conjunto de dados para análise. Entendo que já existem algumas APIs e técnicas não oficiais, mas estou procurando por eventos de jogos realmente específicos (mortes de campeões, mortes de torres, compras de itens, mortes de máfias da selva, coordenações de campeões para eventos particulares, etc.).
O que eu descobri até agora
Quando você começa a assistir a um jogo (em NA), seu cliente se conecta ao seguinte host:
spectator.na.lol.riotgames.com:8088
Presumo que este host seja suportado pelo Amazon AWS ou similar. De qualquer forma, a próxima coisa que acontece é que o cliente envia uma solicitação de versão para o servidor spectate:
GET / modo observador / descanso / consumidor / versão
Isso retorna qualquer que seja a versão atual do servidor espectador. Ex: '1.80.54'
Em seguida, o cliente envia uma solicitação para os metadados do jogo:
GET / modo de observador / rest / consumer / getGameMetaData / NA1 / [gameid] / [some random nonce] / token
Isso retorna metadados sobre o jogo. Um exemplo desses dados: http://pastebin.com/3N4qs0hx
O cliente agora conhece os parâmetros pelos quais a sessão do espectador deve progredir. Ele tenta localizar o último bloco de dados chamando:
GET / modo de observador / rest / consumer / getLastChunkInfo / NA1 / [gameid] / 30000 / token
Amostra desses dados: http://pastebin.com/Cj7dEAr9
Depois que os blocos de dados são identificados, eles são solicitados:
GET / modo de observador / rest / consumer / getGameDataChunk / NA1 / [gameid] / [token #] / token
Amostra dos dados de um token (binário convertido em hexadecimal): http: // pastebin.com / GyqPRP5J
O jogo alterna entre chamar getLastChunkInfo e getGameDataChunk à medida que os dados se tornam disponíveis no fluxo de reprodução. Também existe uma chamada que ocorre após a captura de cerca de 5 pedaços para o seguinte:
GET / modo de observador / rest / consumer / getKeyFrame / NA1 / [gameid] / [somechunkid] / token
Acredito que essa chamada ocorre apenas na inicialização do replay e sempre que o usuário procurar um horário diferente.
Eu sei que o jogo usa criptografia em algum nível. Acredito que seja o Blowfish ECB, com a chave real especificada na linha de comando. Tentei descriptografar esses tokens usando a chave da sessão, mas eles ainda parecem bastante aleatórios.
Editar 23/03/2013
- Eu determinei que os tokens provavelmente não são criptografados modificando o argumento da linha de comando que contém a chave e reiniciando o jogo a partir do depurador (ele carregou a reprodução corretamente).
Os tokens parecem estar compactados. Há uma chamada para uma sub-rotina que, se retornar um número inteiro diferente de zero, disparará o seguinte:
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"); }
Após a investigação do sub_B71120, localizei uma chamada que eventualmente entra em uma função bastante grande. Esta função contém seqüências de caracteres como:
- "verificação incorreta de cabeçalho"
- "método de compressão desconhecido"
- "tamanho de janela inválido"
Uma rápida pesquisa no Google dessas seqüências revela o seguinte: http://www.opensource.apple.com/source/zlib/zlib-22/zlib/inflate.c
Também encontrei a referência de string "1.2.3" em uma chamada de função imediatamente antes da chamada para o método inflate.c, bem como outra referência "inflate 1.2.3 Copyright 1995-2005 Mark Adler". Definitivamente, parece que eles estão usando o Zlib versão 1.2.3 para descompactar os tokens. Eu simplesmente não consigo fazê-los descomprimir, independentemente do deslocamento do arquivo em que começo.
Minhas perguntas)
Alguém sabe como esses 'tokens' podem ser formatados ou se há algum tipo de compactação / criptografia de que não conheço? Suspeito que eles sejam uma forma compactada ou compactada dos pacotes Ethernet usados durante a reprodução ao vivo, que são simplesmente reproduzidos internamente no cliente.
Como alternativa, alguém pode pensar em algum outro método pelo qual raspar esses dados sem executar o cliente do jogo real? Lembre-se de que eu gostaria de coletar dados de vários fluxos simultaneamente.