Skip to content

How do I get the game start time (00:00) from a Dota 2 .dem file? #176

@D2hugging

Description

@D2hugging

Hi, everyone! I want to use the Dota client console command demo_gototick to precisely position the replay to just before the teamfight start time. The teamfight start time is relative to the game clock at 00:00, but .dem files include BP time, game preparation countdown (90s), and even pauses. I'm parsing .dem files using Go's Manta library with the following code:
package main

import (
    "fmt"
    "log"
    "os"



    "github.com/dotabuff/manta"
    "github.com/dotabuff/manta/dota"
)



const (
    DOTA_GAMERULES_STATE_GAME_IN_PROGRESS = 5
)



func main() {
    if len(os.Args) < 2 {
        fmt.Println("Usage: go run main.go <demo.dem>")
        return
    }



    f, err := os.Open(os.Args[1])
    if err != nil {
        log.Fatalf("can't open file: %v", err)
    }
    defer f.Close()



    p, err := manta.NewStreamParser(f)
    if err != nil {
        log.Fatalf("can't create parser: %v", err)
    }



    found := false



    // GamerulesStateChanged callback
    p.Callbacks.OnCDOTAUserMsg_GamerulesStateChanged(
        func(m *dota.CDOTAUserMsg_GamerulesStateChanged) error {



            state := m.GetState()
            tick := p.NetTick
            
            log.Printf("[GamerulesStateChanged] state=%d tick=%d", state, tick)



            if !found && state == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS {
                log.Println("========================================")
                log.Println("get  GAME_IN_PROGRESS(00:00)")
                log.Printf("Absolute Tick: %d", tick)
                
                log.Printf("Demo time: %.3f s", float64(tick)/30.0)
                log.Println("========================================")



                found = true
                p.Stop()
            }
            return nil
        },
    )


    log.Println("begin to parse demo, waiting for GAME_IN_PROGRESS (00:00)")
    err = p.Start()



    if err != nil && err.Error() != "stop" && err.Error() != "stopped" {
        log.Fatalf("failed to parse: %v", err)
    }



    if !found {
        log.Println("Not found GAME_IN_PROGRESS")
    }
}

go run ./main.go ./8598826514_1751608472.dem
After running the above code, the output is as follows:

2026/01/08 21:52:31 begin to parse demo, waiting for GAME_IN_PROGRESS (00:00)
2026/01/08 21:52:31 [GamerulesStateChanged] state=2 tick=486
2026/01/08 21:52:31 [GamerulesStateChanged] state=12 tick=486
2026/01/08 21:52:31 [GamerulesStateChanged] state=9 tick=486
2026/01/08 21:52:31 [GamerulesStateChanged] state=3 tick=3131
2026/01/08 21:52:31 [GamerulesStateChanged] state=8 tick=4031
2026/01/08 21:52:31 [GamerulesStateChanged] state=4 tick=4514
2026/01/08 21:52:31 [GamerulesStateChanged] state=10 tick=4514
2026/01/08 21:52:31 [GamerulesStateChanged] state=5 tick=7214
2026/01/08 21:52:31 ========================================
2026/01/08 21:52:31 get GAME_IN_PROGRESS(00:00)
2026/01/08 21:52:31 Absolute Tick: 7214
2026/01/08 21:52:31 Demo time: 240.467 s
2026/01/08 21:52:31 ========================================

Match ID 8598826514 enters GAME_IN_PROGRESS state at tick 7214 according to the logs. I expected demo_gototick 7214 to precisely position at game start (00:00), but testing shows it actually jumps to around the pre-game countdown (01:30). Is there an issue with my code, or did I misunderstand the GAME_IN_PROGRESS state timing? Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions