ReplayDojo
Dota 2
Para desarrolladores

Qué contiene un archivo de repetición de Dota 2

El formato .dem de Dota 2 para desarrolladores: descarga, compresión, entidades, registro de combate y parsers para leer los datos de una repetición.

Actualizado · 8 min de lectura

Un mapa que se transforma en una cuadrícula de puntos de muestreo con un trazo amarillo

Si abres un archivo .dem, no encontrarás fotogramas. Contiene los mensajes de red que envió el servidor durante la partida. Leerlo implica reproducir ese flujo de mensajes en un modelo de las entidades del juego. Eso hace el cliente cuando ves una repetición y eso hace un parser cuando lo que necesitas son los datos. Esta guía recoge lo que aprendimos al construir el proceso de ReplayDojo, que convierte un ID de partida en una repetición 3D en el navegador.

Cómo obtener el archivo

Valve sirve las repeticiones desde sus clústeres de servidores mediante una URL formada por tres valores, con el formato que aparece abajo.

El ID de la partida es público. El clúster y el salt no aparecen en la información que ve el jugador. Lo habitual es obtenerlos del endpoint de partidas de OpenDota, que devuelve un campo replay_url listo para usar en las partidas que conoce. Cuando OpenDota no está disponible, una URL completa de Valve pegada por el usuario contiene todo lo necesario; por eso nuestro importador también las acepta directamente como alternativa. La URL deja de funcionar cuando Valve elimina la repetición, normalmente una o dos semanas después de la partida.

http://replay<cluster>.valve.net/570/<match_id>_<replay_salt>.dem.bz2

Qué contiene un .dem

El archivo es una secuencia de mensajes precedidos por su longitud; la mayoría usa Protocol Buffers. Dos tipos contienen casi todos los datos útiles.

Entidades de paquetes (packet entities): actualizaciones codificadas por diferencias de cada entidad sincronizada por red, incluidos héroes, creeps, edificios, wards, objetos y los recursos de jugador y equipo que guardan oro, patrimonio neto, últimos golpes y otros datos similares. Los esquemas, llamados send tables, están incluidos al principio del archivo. Por eso un parser creado después puede seguir decodificando una repetición de un parche antiguo.

Registro de combate (combat log): una entrada por cada instancia de daño, curación, uso de habilidad u objeto, modificador, muerte o cambio de oro o experiencia, con atacante, objetivo y la fuente que causó el efecto (inflictor). De aquí se obtienen las bajas, las asistencias y quién mató a Roshan.

También contiene eventos del juego, chat y mensajes de usuario como los pings y el resumen de fin de partida. Una repetición no contiene movimientos del mouse, posiciones de cámara ni otros datos que se quedaron en la computadora del jugador.

Parsers

Casi seguro te conviene usar un decodificador de entidades existente. Estas son las opciones de código abierto que conocemos bien.

manta (Go), mantenido por Dotabuff. Es rápido y de bajo nivel: registras callbacks para los mensajes y los cambios de entidades. Lo usamos para obtener posiciones, estados y datos de los héroes en cada muestra.

clarity (Java). Es una opción madura y maneja bien el registro de combate. Las repeticiones del parche 7.40 en adelante necesitan clarity 4.0.1 o una versión posterior.

También hay parsers en Rust y Python. Antes de basarte en uno, revisa cuándo se actualizó por última vez, porque cada parche grande puede cambiar los esquemas de entidades o los tipos de mensajes.

De las entidades a las posiciones

La posición de un héroe se divide entre un índice de celda y un desplazamiento dentro de esa celda. Necesitas ambos para reconstruir sus coordenadas en el mundo. Las actualizaciones de entidades llegan de forma irregular: un héroe quieto no envía nada y uno en plena pelea se actualiza en cada tick. Para la reproducción, volvemos a muestrear cada unidad a una frecuencia fija de 15 muestras por segundo y guardamos la posición, la orientación y el estado de animación como fotogramas clave en un archivo binario compacto. Las estadísticas que cambian más despacio, como el oro, los objetos, las habilidades y los tiempos de recarga, se guardan en JSON con muestras cada dos segundos. Una partida de 45 minutos termina ocupando unos pocos megabytes, que el navegador carga en uno o dos segundos.

Después se calculan una sola vez las bajas, las torres, Roshan y las peleas, y se reúnen en un único índice de eventos. El registro de bajas, la línea de tiempo, el marcador y la cámara consultan ese mismo índice para mostrar cifras coherentes.

Problemas con los que nos encontramos

El tiempo de juego no es el tiempo de la repetición. El archivo empieza en la sala, mucho antes del cuerno, y los ticks siguen avanzando durante las pausas. Cuenta desde el tick de inicio de la partida y resta las pausas; de lo contrario, todos los relojes quedarán desfasados por varios minutos.

No toda muerte cuenta como una baja. Las muertes con Aegis o Reincarnation reviven al héroe unos segundos después en el mismo lugar. Las denegaciones son muertes causadas por un compañero de equipo. Si cuentas cualquiera de estos casos como una baja, tus cifras no coincidirán con el marcador.

Bajas atribuidas a invocaciones y creeps: el marcador se las acredita al héroe, pero el registro de combate nombra a la unidad que dio el golpe. Cruza esos datos con los contadores de bajas de los jugadores.

Nombres internos: las entidades usan nombres del motor anteriores a cambios de nombre. npc_dota_hero_furion es Nature’s Prophet, windrunner es Windranger y los nombres de clase de los objetos no siempre coinciden con sus claves. Mantén una tabla de alias.

Pega el ID de una partida de Dota 2 y mira la repetición en 3D, gratis en tu navegador.

Abrir partida

Más guías