11package demoinfocs
22
33import (
4+ _ "embed"
45 "fmt"
56 "io"
67 "runtime/debug"
@@ -66,22 +67,23 @@ Prints out '{A/B} site went BOOM!' when a bomb explodes.
6667type parser struct {
6768 // Important fields
6869
69- bitReader * bit.BitReader
70- stParser sendTableParser
71- additionalNetMessageCreators map [int ]NetMessageCreator // Map of net-message-IDs to NetMessageCreators (for parsing custom net-messages)
72- msgQueue chan any // Queue of net-messages
73- msgDispatcher * dp.Dispatcher // Net-message dispatcher
74- gameEventHandler gameEventHandler
75- userMessageHandler userMessageHandler
76- eventDispatcher * dp.Dispatcher
77- currentFrame int // Demo-frame, not ingame-tick
78- tickInterval float32 // Duration between ticks in seconds
79- header * common.DemoHeader // Pointer so we can check for nil
80- gameState * gameState
81- demoInfoProvider demoInfoProvider // Provides demo infos to other packages that the core package depends on
82- err error // Contains a error that occurred during parsing if any
83- errLock sync.Mutex // Used to sync up error mutations between parsing & handling go-routines
84- decryptionKey []byte // Stored in `match730_*.dem.info` see MatchInfoDecryptionKey().
70+ bitReader * bit.BitReader
71+ stParser sendTableParser
72+ additionalNetMessageCreators map [int ]NetMessageCreator // Map of net-message-IDs to NetMessageCreators (for parsing custom net-messages)
73+ msgQueue chan any // Queue of net-messages
74+ msgDispatcher * dp.Dispatcher // Net-message dispatcher
75+ gameEventHandler gameEventHandler
76+ userMessageHandler userMessageHandler
77+ eventDispatcher * dp.Dispatcher
78+ currentFrame int // Demo-frame, not ingame-tick
79+ tickInterval float32 // Duration between ticks in seconds
80+ header * common.DemoHeader // Pointer so we can check for nil
81+ gameState * gameState
82+ demoInfoProvider demoInfoProvider // Provides demo infos to other packages that the core package depends on
83+ err error // Contains a error that occurred during parsing if any
84+ errLock sync.Mutex // Used to sync up error mutations between parsing & handling go-routines
85+ decryptionKey []byte // Stored in `match730_*.dem.info` see MatchInfoDecryptionKey().
86+ source2FallbackGameEventListBin []byte // sv_hibernate_when_empty bug workaround
8587 /**
8688 * Set to the client slot of the recording player.
8789 * Always -1 for GOTV demos.
@@ -353,13 +355,21 @@ type ParserConfig struct {
353355 // Unfortunately Source 2 demos *may* not contain Source 1 game events, that's why the parser will try to mimic them.
354356 // It has an impact only with Source 2 demos and is false by default.
355357 DisableMimicSource1Events bool
358+
359+ // Source2FallbackGameEventListBin is a fallback game event list protobuf message for Source 2 demos.
360+ // It's used when the game event list is not found in the demo file.
361+ // This can happen due to a CS2 bug with sv_hibernate_when_empty.
362+ Source2FallbackGameEventListBin []byte
356363}
357364
358365// DefaultParserConfig is the default Parser configuration used by NewParser().
359366var DefaultParserConfig = ParserConfig {
360367 MsgQueueBufferSize : - 1 ,
361368}
362369
370+ //go:embed s2_CMsgSource1LegacyGameEventList.pb.bin
371+ var defaultSource2FallbackGameEventListBin []byte
372+
363373// NewParserWithConfig returns a new Parser with a custom configuration.
364374//
365375// See also: NewParser() & ParserConfig
@@ -382,6 +392,11 @@ func NewParserWithConfig(demostream io.Reader, config ParserConfig) Parser {
382392 p .decryptionKey = config .NetMessageDecryptionKey
383393 p .recordingPlayerSlot = - 1
384394 p .disableMimicSource1GameEvents = config .DisableMimicSource1Events
395+ p .source2FallbackGameEventListBin = config .Source2FallbackGameEventListBin
396+
397+ if p .source2FallbackGameEventListBin == nil {
398+ p .source2FallbackGameEventListBin = defaultSource2FallbackGameEventListBin
399+ }
385400
386401 dispatcherCfg := dp.Config {
387402 PanicHandler : func (v any ) {
0 commit comments