Formato de transmisión de League of Legends Spectator

12

Introducción

He estado jugando con el sistema de espectadores para LoL con la esperanza de eventualmente extraer datos de las transmisiones y construir un conjunto de datos con ellos para su análisis. Entiendo que ya hay algunas API y técnicas no oficiales, pero estoy buscando eventos de juego realmente específicos (asesinatos de campeones, asesinatos de torretas, compras de artículos, asesinatos de la mafia de la jungla, coordinaciones de campeones para eventos particulares, etc.).

Lo que he descubierto hasta ahora

Cuando comienzas a ver un juego (en NA), tu cliente se conecta al siguiente host:

spectator.na.lol.riotgames.com:8088

Supongo que este host está respaldado por Amazon AWS o similar. De todos modos, lo siguiente que sucede es que el cliente envía una solicitud de versión al servidor de espectate:

GET / observador-modo / descanso / consumidor / versión

Esto devuelve cualquiera que sea la versión actual del servidor espectador. Ej: '1.80.54'

A continuación, el cliente envía una solicitud de metadatos del juego:

GET / observer-mode / rest / consumer / getGameMetaData / NA1 / [gameid] / [some nonce aleatorio] / token

Esto devuelve metadatos sobre el juego. Un ejemplo de estos datos: http://pastebin.com/3N4qs0hx

El cliente ahora conoce los parámetros por los cuales la sesión de espectadores debería progresar. Intenta localizar el último fragmento de datos llamando a:

GET / observer-mode / rest / consumer / getLastChunkInfo / NA1 / [gameid] / 30000 / token

Muestra de estos datos: http://pastebin.com/Cj7dEAr9

Una vez que se han identificado los fragmentos de datos, se solicitan:

GET / observer-mode / rest / consumer / getGameDataChunk / NA1 / [gameid] / [token #] / token

Muestra de datos de un token (binario convertido a hexadecimal): http: // pastebin.com / GyqPRP5J

El juego cambia entre las llamadas getLastChunkInfo y getGameDataChunk a medida que los datos están disponibles desde la secuencia de reproducción. También hay una llamada que se produce después de que se toman alrededor de 5 fragmentos de lo siguiente:

GET / observer-mode / rest / consumer / getKeyFrame / NA1 / [gameid] / [somechunkid] / token

Creo que esta llamada solo ocurre en el inicio de la reproducción y siempre que el usuario busque un momento diferente.

Sé que el juego usa encriptación en algún nivel. Creo que es Blowfish ECB, con la clave real especificada en la línea de comando. Intenté descifrar estos tokens usando la clave de la sesión, pero todavía se ven bastante al azar.

Editar 23/03/2013

  • He determinado que los tokens probablemente no estén encriptados modificando el argumento de la línea de comando que contiene la clave y reiniciando el juego desde el depurador (cargó la reproducción correctamente).
  • Las fichas parecen estar comprimidas. Hay una llamada a una subrutina que, si devuelve un entero distinto de cero, activará lo siguiente:

    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");
    }
    
  • Tras la investigación de sub_B71120, he localizado una llamada que finalmente entra en una función bastante grande. Esta función contiene cadenas como:

    • "verificación de encabezado incorrecta"
    • "método de compresión desconocido"
    • "tamaño de ventana no válido"
  • Una búsqueda rápida en Google de estas cadenas revela lo siguiente: http://www.opensource.apple.com/source/zlib/zlib-22/zlib/inflate.c

  • También he encontrado la referencia de cadena "1.2.3" en una llamada de función justo antes de la llamada al método inflate.c, así como otra referencia "inflar 1.2.3 Copyright 1995-2005 Mark Adler". Definitivamente parece que están usando Zlib versión 1.2.3 para la descompresión de los tokens. Simplemente no puedo hacer que se descompriman sin importar en qué desplazamiento de archivo empiezo.

Mis preguntas)

¿Alguien sabe cómo se pueden formatear estos 'tokens' o si hay algún tipo de compresión / cifrado que desconozco? Tengo la sospecha de que son una forma comprimida o empaquetada de los paquetes de Ethernet utilizados durante la reproducción en vivo que simplemente se reproducen internamente en el cliente.

Alternativamente, ¿alguien puede pensar en algún otro método para raspar estos datos sin ejecutar el cliente del juego real? Tenga en cuenta que me gustaría obtener datos de muchas transmisiones simultáneamente.


fuente
1
La forma en que pensé en hacerlo fue tomar tantos archivos de repetición de LOLReplay como sea posible y simplemente procesarlos. Creo que hay un archivo abierto donde las personas pueden cargar sus propios juegos, y creo que el nuevo modo espectador permite que el cliente Replay obtenga más información que antes.
Robert S.
¿Qué otras API y técnicas hay? ¿Por qué crees que hay cifrado? Encontré esto en GetGameMetaData: "encryptionKey": "" y "decodedEncryptionKey": ""
Nathan Goings
Como información para las personas que siguen llegando a esta pregunta desde varios foros de LoL, al ver mi nombre en la publicación bajo "editado por" y enviarme un correo electrónico para preguntar sobre el tema ... No sé nada sobre LoL o el formato de sus secuencias. Por favor no me envíe un correo electrónico al respecto.

Respuestas:

4

He estado investigando lo mismo y este repositorio me pareció extremadamente útil. El archivo decrypt.rb descifra fragmentos y fotogramas clave.

Editar: echa un vistazo a este hilo de reddit también.

tyscorp
fuente
Excelente. El primer enlace responde a mi pregunta con precisión. El segundo enlace también es realmente útil. ¡Gracias una tonelada!