Skip to content

Commit ce1ecd5

Browse files
authored
core: add ParserConfig.IgnoreErrBombsiteIndexNotFound flag to ignore unknown bombsite indices (#315)
see #314
1 parent efa5898 commit ce1ecd5

File tree

6 files changed

+75
-21
lines changed

6 files changed

+75
-21
lines changed

pkg/demoinfocs/demoinfocs_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const (
3232
csDemosPath = testDataPath + "/cs-demos"
3333
demSetPath = csDemosPath + "/set"
3434
defaultDemPath = csDemosPath + "/default.dem"
35+
retakeDemPath = csDemosPath + "/retake_unknwon_bombsite_index.dem"
3536
unexpectedEndOfDemoPath = csDemosPath + "/unexpected_end_of_demo.dem"
3637
)
3738

@@ -193,6 +194,41 @@ func TestDemoInfoCs(t *testing.T) {
193194
assertGolden(t, assertions, "default", actual.Bytes())
194195
}
195196

197+
func TestRetake_BadBombsiteIndex(t *testing.T) {
198+
t.Parallel()
199+
200+
if testing.Short() {
201+
t.Skip("skipping test due to -short flag")
202+
}
203+
204+
f := openFile(t, retakeDemPath)
205+
defer mustClose(t, f)
206+
207+
p := demoinfocs.NewParser(f)
208+
209+
err := p.ParseToEnd()
210+
assert.Error(t, err, demoinfocs.ErrBombsiteIndexNotFound)
211+
}
212+
213+
func TestRetake_IgnoreBombsiteIndexNotFound(t *testing.T) {
214+
t.Parallel()
215+
216+
if testing.Short() {
217+
t.Skip("skipping test due to -short flag")
218+
}
219+
220+
f := openFile(t, retakeDemPath)
221+
defer mustClose(t, f)
222+
223+
cfg := demoinfocs.DefaultParserConfig
224+
cfg.IgnoreErrBombsiteIndexNotFound = true
225+
226+
p := demoinfocs.NewParserWithConfig(f, cfg)
227+
228+
err := p.ParseToEnd()
229+
assert.NoError(t, err)
230+
}
231+
196232
func TestUnexpectedEndOfDemo(t *testing.T) {
197233
t.Parallel()
198234

pkg/demoinfocs/events/events.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,9 @@ type bombsite rune
275275

276276
// Bombsite identifiers
277277
const (
278-
BombsiteA bombsite = 'A'
279-
BombsiteB bombsite = 'B'
278+
BomsiteUnknown bombsite = 0
279+
BombsiteA bombsite = 'A'
280+
BombsiteB bombsite = 'B'
280281
)
281282

282283
// BombEvent contains the common attributes of bomb events. Dont register

pkg/demoinfocs/game_events.go

+29-16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/golang/geo/r3"
77
"github.com/markus-wa/go-unassert"
8+
"github.com/pkg/errors"
89

910
common "github.com/markus-wa/demoinfocs-golang/v2/pkg/demoinfocs/common"
1011
events "github.com/markus-wa/demoinfocs-golang/v2/pkg/demoinfocs/events"
@@ -52,10 +53,11 @@ func (p *parser) handleGameEvent(ge *msg.CSVCMsg_GameEvent) {
5253
}
5354

5455
type gameEventHandler struct {
55-
parser *parser
56-
gameEventNameToHandler map[string]gameEventHandlerFunc
57-
userIDToFallDamageFrame map[int32]int
58-
frameToRoundEndReason map[int]events.RoundEndReason
56+
parser *parser
57+
gameEventNameToHandler map[string]gameEventHandlerFunc
58+
userIDToFallDamageFrame map[int32]int
59+
frameToRoundEndReason map[int]events.RoundEndReason
60+
ignoreBombsiteIndexNotFound bool // see https://github.com/markus-wa/demoinfocs-golang/issues/314
5961
}
6062

6163
func (geh gameEventHandler) dispatch(event interface{}) {
@@ -77,11 +79,12 @@ func (geh gameEventHandler) playerByUserID32(userID int32) *common.Player {
7779
type gameEventHandlerFunc func(map[string]*msg.CSVCMsg_GameEventKeyT)
7880

7981
//nolint:funlen
80-
func newGameEventHandler(parser *parser) gameEventHandler {
82+
func newGameEventHandler(parser *parser, ignoreBombsiteIndexNotFound bool) gameEventHandler {
8183
geh := gameEventHandler{
82-
parser: parser,
83-
userIDToFallDamageFrame: make(map[int32]int),
84-
frameToRoundEndReason: make(map[int]events.RoundEndReason),
84+
parser: parser,
85+
userIDToFallDamageFrame: make(map[int32]int),
86+
frameToRoundEndReason: make(map[int]events.RoundEndReason),
87+
ignoreBombsiteIndexNotFound: ignoreBombsiteIndexNotFound,
8588
}
8689

8790
// some events need to be delayed until their data is available
@@ -633,6 +636,11 @@ func (geh gameEventHandler) bombExploded(data map[string]*msg.CSVCMsg_GameEventK
633636
geh.dispatch(events.BombExplode{BombEvent: bombEvent})
634637
}
635638

639+
// ErrBombsiteIndexNotFound indicates that a game-event occurred that contained an unknown bombsite index.
640+
// This error can be disabled by setting ParserConfig.IgnoreErrBombsiteIndexNotFound = true.
641+
// See https://github.com/markus-wa/demoinfocs-golang/issues/314
642+
var ErrBombsiteIndexNotFound = errors.New("bombsite index not found - see https://github.com/markus-wa/demoinfocs-golang/issues/314")
643+
636644
func (geh gameEventHandler) bombEvent(data map[string]*msg.CSVCMsg_GameEventKeyT) (events.BombEvent, error) {
637645
bombEvent := events.BombEvent{Player: geh.playerByUserID32(data["userid"].GetValShort())}
638646

@@ -653,17 +661,22 @@ func (geh gameEventHandler) bombEvent(data map[string]*msg.CSVCMsg_GameEventKeyT
653661
default:
654662
t := geh.parser.triggers[site]
655663

664+
// when not found, only error if site is not 0, for retake games it may be 0 => unknown
656665
if t == nil {
657-
return bombEvent, fmt.Errorf("bombsite with index %d not found", site)
666+
if !geh.ignoreBombsiteIndexNotFound {
667+
return bombEvent, errors.Wrapf(ErrBombsiteIndexNotFound, "bombsite with index %d not found", site)
668+
}
669+
} else {
670+
if t.contains(geh.parser.bombsiteA.center) {
671+
bombEvent.Site = events.BombsiteA
672+
geh.parser.bombsiteA.index = site
673+
} else if t.contains(geh.parser.bombsiteB.center) {
674+
bombEvent.Site = events.BombsiteB
675+
geh.parser.bombsiteB.index = site
676+
}
658677
}
659678

660-
if t.contains(geh.parser.bombsiteA.center) {
661-
bombEvent.Site = events.BombsiteA
662-
geh.parser.bombsiteA.index = site
663-
} else if t.contains(geh.parser.bombsiteB.center) {
664-
bombEvent.Site = events.BombsiteB
665-
geh.parser.bombsiteB.index = site
666-
} else {
679+
if bombEvent.Site == events.BomsiteUnknown {
667680
// this may occur on de_grind for bombsite B, really makes you think
668681
// see https://github.com/markus-wa/demoinfocs-golang/issues/280
669682
geh.dispatch(events.ParserWarn{

pkg/demoinfocs/parser.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ type ParserConfig struct {
312312
// Check out parsing.go to see which net-messages are already being parsed by default.
313313
// This is a beta feature and may be changed or replaced without notice.
314314
AdditionalNetMessageCreators map[int]NetMessageCreator
315+
316+
// IgnoreErrBombsiteIndexNotFound tells the parser to not return an error when a bombsite-index from a game-event is not found in the demo.
317+
// See https://github.com/markus-wa/demoinfocs-golang/issues/314
318+
IgnoreErrBombsiteIndexNotFound bool
315319
}
316320

317321
// DefaultParserConfig is the default Parser configuration used by NewParser().
@@ -334,7 +338,7 @@ func NewParserWithConfig(demostream io.Reader, config ParserConfig) Parser {
334338
p.demoInfoProvider = demoInfoProvider{parser: &p}
335339
p.gameState = newGameState(p.demoInfoProvider)
336340
p.grenadeModelIndices = make(map[int]common.EquipmentType)
337-
p.gameEventHandler = newGameEventHandler(&p)
341+
p.gameEventHandler = newGameEventHandler(&p, config.IgnoreErrBombsiteIndexNotFound)
338342
p.userMessageHandler = newUserMessageHandler(&p)
339343
p.bombsiteA.index = -1
340344
p.bombsiteB.index = -1

scripts/coverage.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -e
44

55
scripts_dir=$(dirname "$0")
6-
$scripts_dir/download-test-data.sh default.7z unexpected_end_of_demo.7z regression-set.7z
6+
$scripts_dir/download-test-data.sh default.7z unexpected_end_of_demo.7z regression-set.7z retake_unknwon_bombsite_index.7z
77

88
# don't cover mocks and generated protobuf code
99
coverpkg_ignore='/(fake|msg)'

test/cs-demos

Submodule cs-demos updated from 851caa0 to 2be8467

0 commit comments

Comments
 (0)