Skip to content

Commit e98a3fa

Browse files
authored
Merge pull request #460 from markus-wa/s2-fake-CMsgSource1LegacyGameEventList
CS2: fake CMsgSource1LegacyGameEventList if missing
2 parents 6c73556 + 7530bcd commit e98a3fa

File tree

7 files changed

+62
-18
lines changed

7 files changed

+62
-18
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/markus-wa/quickhull-go/v2 v2.2.0
1313
github.com/oklog/ulid/v2 v2.1.0
1414
github.com/pkg/errors v0.9.1
15+
github.com/samber/lo v1.38.1
1516
github.com/stretchr/testify v1.8.4
1617
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
1718
google.golang.org/protobuf v1.31.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ github.com/markus-wa/gobitread v0.2.3 h1:COx7dtYQ7Q+77hgUmD+O4MvOcqG7y17RP3Z7Bbj
2525
github.com/markus-wa/gobitread v0.2.3/go.mod h1:PcWXMH4gx7o2CKslbkFkLyJB/aHW7JVRG3MRZe3PINg=
2626
github.com/markus-wa/godispatch v1.4.1 h1:Cdff5x33ShuX3sDmUbYWejk7tOuoHErFYMhUc2h7sLc=
2727
github.com/markus-wa/godispatch v1.4.1/go.mod h1:tk8L0yzLO4oAcFwM2sABMge0HRDJMdE8E7xm4gK/+xM=
28-
github.com/markus-wa/ice-cipher-go v0.0.0-20220823210642-1fcccd18c6c1 h1:YH4WI14HARrM3C6mKUMFDBz93O25oWSlLEYGeL27G0w=
29-
github.com/markus-wa/ice-cipher-go v0.0.0-20220823210642-1fcccd18c6c1/go.mod h1:JIsht5Oa9P50VnGJTvH2a6nkOqDFJbUeU1YRZYvdplw=
3028
github.com/markus-wa/ice-cipher-go v0.0.0-20230901094113-348096939ba7 h1:aR9pvnlnBxifXBmzidpAiq2prLSGlkhE904qnk2sCz4=
3129
github.com/markus-wa/ice-cipher-go v0.0.0-20230901094113-348096939ba7/go.mod h1:JIsht5Oa9P50VnGJTvH2a6nkOqDFJbUeU1YRZYvdplw=
3230
github.com/markus-wa/quickhull-go/v2 v2.2.0 h1:rB99NLYeUHoZQ/aNRcGOGqjNBGmrOaRxdtqTnsTUPTA=
@@ -38,6 +36,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
3836
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3937
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4038
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
39+
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
40+
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
4141
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
4242
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
4343
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

pkg/demoinfocs/demoinfocs_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ import (
1818
"time"
1919

2020
dispatch "github.com/markus-wa/godispatch"
21+
"github.com/samber/lo"
2122
"github.com/stretchr/testify/assert"
2223
"google.golang.org/protobuf/proto"
2324

2425
demoinfocs "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs"
2526
common "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/common"
2627
events "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/events"
2728
msg "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/msg"
29+
"github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/msgs2"
2830
)
2931

3032
const (
@@ -214,6 +216,12 @@ func TestS2(t *testing.T) {
214216

215217
p := demoinfocs.NewParserWithConfig(f, cfg)
216218

219+
if *update {
220+
p.RegisterNetMessageHandler(func(gel *msgs2.CMsgSource1LegacyGameEventList) {
221+
lo.Must0(os.WriteFile("s2_CMsgSource1LegacyGameEventList.pb.bin", lo.Must(proto.Marshal(gel)), 0600))
222+
})
223+
}
224+
217225
t.Log("Parsing header")
218226
_, err = p.ParseHeader()
219227
assertions.NoError(err, "error returned by Parser.ParseHeader()")

pkg/demoinfocs/game_events.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/golang/geo/r3"
77
"github.com/markus-wa/go-unassert"
88
"github.com/pkg/errors"
9+
"google.golang.org/protobuf/proto"
910

1011
common "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/common"
1112
events "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/events"
@@ -79,6 +80,24 @@ func (p *parser) handleGameEvent(ge *msg.CSVCMsg_GameEvent) {
7980
}
8081

8182
func (p *parser) handleGameEventS2(ge *msgs2.CMsgSource1LegacyGameEvent) {
83+
if p.gameEventDescs == nil {
84+
p.eventDispatcher.Dispatch(events.ParserWarn{
85+
Message: "received GameEvent but event descriptors are missing",
86+
Type: events.WarnTypeGameEventBeforeDescriptors,
87+
})
88+
89+
list := new(msgs2.CMsgSource1LegacyGameEventList)
90+
91+
err := proto.Unmarshal(p.source2FallbackGameEventListBin, list)
92+
if err != nil {
93+
p.setError(err)
94+
95+
return
96+
}
97+
98+
p.handleGameEventListS2(list)
99+
}
100+
82101
keys := make([]*msg.CSVCMsg_GameEventKeyT, 0, len(ge.Keys))
83102

84103
for _, k := range ge.Keys {

pkg/demoinfocs/parser.go

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package demoinfocs
22

33
import (
4+
_ "embed"
45
"fmt"
56
"io"
67
"runtime/debug"
@@ -66,22 +67,23 @@ Prints out '{A/B} site went BOOM!' when a bomb explodes.
6667
type 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().
359366
var 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) {

pkg/demoinfocs/parser_interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package demoinfocs
44

55
import (
6+
_ "embed"
67
"time"
78

89
"github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/common"
15 KB
Binary file not shown.

0 commit comments

Comments
 (0)