Formato de stream do League of Legends Spectator

12

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.


fonte
1
O jeito que eu pensei em fazer isso foi pegar o maior número possível de arquivos de reprodução do LOLReplay possível e processá-los. Acho que existe um arquivo aberto no qual as pessoas podem fazer upload de seus próprios jogos, e acho que o novo modo de espectador permite que o cliente Replay obtenha mais informações do que antes.
26713 Robert S.
Quais outras APIs e técnicas existem? Por que você acha que há criptografia? Encontrei isso no GetGameMetaData: "encryptionKey": "" e "decodedEncryptionKey": ""
Nathan Goings
Como FYI para as pessoas que continuam abordando essa questão em vários fóruns de LoL, vendo meu nome no post em "editado por" e me enviando um e-mail para perguntar sobre o tópico ... Não sei nada sobre LoL ou o formato de seus fluxos. Por favor, não me escreva sobre isso.

Respostas:

4

Pesquisei a mesma coisa e achei este repositório extremamente útil. O arquivo decrypt.rb descriptografa pedaços e quadros-chave.

Editar: confira este tópico do reddit também.

tyscorp
fonte
Excelente. O primeiro link responde à minha pergunta com precisão. O segundo link também é realmente útil. Muito obrigado!