Skip to content

Commit

Permalink
some more frame-rate related changes
Browse files Browse the repository at this point in the history
  • Loading branch information
markus-wa committed Jun 5, 2021
1 parent 167fe87 commit d92b1e8
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 17 deletions.
7 changes: 7 additions & 0 deletions pkg/demoinfocs/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,13 @@ type SayText2 struct {
IsChatAll bool // Seems to always be false, team chat might not be recorded
}

// TickRateInfoAvailable signals that the tick-rate information has been received via CSVCMsg_ServerInfo.
// This can be useful for corrupt demo headers where the tick-rate is missing in the beginning of the demo.
type TickRateInfoAvailable struct {
TickRate float64 // See Parser.TickRate()
TickTime time.Duration // See Parser.TickTime()
}

// ChatMessage signals a player generated chat message.
// Since team chat is generally not recorded IsChatAll will probably always be false.
// See SayText for admin / console messages and SayText2 for raw network package data.
Expand Down
4 changes: 4 additions & 0 deletions pkg/demoinfocs/net_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,8 @@ func (p *parser) handleSetConVar(setConVar *msg.CNETMsg_SetConVar) {
func (p *parser) handleServerInfo(srvInfo *msg.CSVCMsg_ServerInfo) {
// srvInfo.MapCrc might be interesting as well
p.tickInterval = srvInfo.TickInterval
p.eventDispatcher.Dispatch(events.TickRateInfoAvailable{
TickRate: p.TickRate(),
TickTime: p.TickTime(),
})
}
27 changes: 12 additions & 15 deletions pkg/demoinfocs/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,36 +177,32 @@ func legayTickTime(h common.DemoHeader) time.Duration {
// FrameRate returns the frame rate of the demo (frames / demo-ticks per second).
// Not necessarily the tick-rate the server ran on during the game.
//
// Returns frame rate based on GameState.IngameTick() if possible.
// Otherwise returns tick rate based on demo header or -1 if the header info isn't available.
// May also return 0 before parsing has started if DemoHeader.PlaybackTime or DemoHeader.PlaybackFrames are 0 (corrupt demo headers).
// Returns frame rate from DemoHeader if it's not corrupt.
// Otherwise returns frame rate based on the current frame, tick-rate and ingame-tick.
// May also return -1 before parsing has started.
func (p *parser) FrameRate() float64 {
if p.gameState.ingameTick > 0 && p.currentFrame > 0 && p.TickRate() > 0 {
return p.TickRate() / (float64(p.gameState.ingameTick) / float64(p.currentFrame))
if p.header != nil && p.header.PlaybackTime != 0 && p.header.PlaybackFrames != 0 {
return legacyFrameRate(*p.header)
}

if p.header != nil {
return legacyFrameRate(*p.header)
if p.gameState.ingameTick > 0 && p.currentFrame > 0 && p.TickRate() > 0 {
return float64(p.currentFrame) * p.TickRate() / float64(p.gameState.ingameTick)
}

return -1
}

func legacyFrameRate(h common.DemoHeader) float64 {
if h.PlaybackTime == 0 {
return 0
}

return float64(h.PlaybackFrames) / h.PlaybackTime.Seconds()
}

// FrameTime returns the time a frame / demo-tick takes in seconds.
//
// Returns frame rate based on GameState.IngameTick() if possible.
// Otherwise returns tick rate based on demo header or -1 if the header info isn't available.
// May also return 0 before parsing has started if DemoHeader.PlaybackTime or DemoHeader.PlaybackFrames are 0 (corrupt demo headers).
// Returns frame time from DemoHeader if it's not corrupt.
// Otherwise returns frame time based on the current frame, tick-rate and ingame-tick.
// May also return -1 before parsing has started.
func (p *parser) FrameTime() time.Duration {
if frameRate := p.FrameRate(); frameRate >= 0 {
if frameRate := p.FrameRate(); frameRate > 0 {
return time.Duration(float64(time.Second) / frameRate)
}

Expand Down Expand Up @@ -354,6 +350,7 @@ func NewParserWithConfig(demostream io.Reader, config ParserConfig) Parser {
p.grenadeModelIndices = make(map[int]common.EquipmentType)
p.gameEventHandler = newGameEventHandler(&p)
p.userMessageHandler = newUserMessageHandler(&p)
p.currentFrame = -1

dispatcherCfg := dp.Config{
PanicHandler: func(v interface{}) {
Expand Down
13 changes: 13 additions & 0 deletions pkg/demoinfocs/parser_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ type Parser interface {
// Returns tick time based on CSVCMsg_ServerInfo if possible.
// Otherwise returns tick time based on demo header or -1 if the header info isn't available.
TickTime() time.Duration
// FrameRate returns the frame rate of the demo (frames / demo-ticks per second).
// Not necessarily the tick-rate the server ran on during the game.
//
// Returns frame rate based on GameState.IngameTick() if possible.
// Otherwise returns tick rate based on demo header or -1 if the header info isn't available.
// May also return 0 before parsing has started if DemoHeader.PlaybackTime or DemoHeader.PlaybackFrames are 0 (corrupt demo headers).
FrameRate() float64
// FrameTime returns the time a frame / demo-tick takes in seconds.
//
// Returns frame rate based on GameState.IngameTick() if possible.
// Otherwise returns tick rate based on demo header or -1 if the header info isn't available.
// May also return 0 before parsing has started if DemoHeader.PlaybackTime or DemoHeader.PlaybackFrames are 0 (corrupt demo headers).
FrameTime() time.Duration
// Progress returns the parsing progress from 0 to 1.
// Where 0 means nothing has been parsed yet and 1 means the demo has been parsed to the end.
//
Expand Down
6 changes: 4 additions & 2 deletions pkg/demoinfocs/parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,10 @@ func (p *parser) parseFrame() bool {
panic(fmt.Sprintf("I haven't programmed that pathway yet (command %v unknown)", cmd))
}

// Queue up some post processing
p.msgQueue <- frameParsedToken
if cmd == dcPacket {
// Queue up some post processing, see parser.handleFrameParsed()
p.msgQueue <- &frameParsedTokenType{}
}

return true
}
Expand Down

0 comments on commit d92b1e8

Please sign in to comment.