Skip to content

Commit

Permalink
core: add ParserConfig.IgnoreErrBombsiteIndexNotFound flag to ignore …
Browse files Browse the repository at this point in the history
…unknown bombsite indices (#315)

see #314
  • Loading branch information
markus-wa authored Oct 21, 2021
1 parent efa5898 commit ce1ecd5
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 21 deletions.
36 changes: 36 additions & 0 deletions pkg/demoinfocs/demoinfocs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const (
csDemosPath = testDataPath + "/cs-demos"
demSetPath = csDemosPath + "/set"
defaultDemPath = csDemosPath + "/default.dem"
retakeDemPath = csDemosPath + "/retake_unknwon_bombsite_index.dem"
unexpectedEndOfDemoPath = csDemosPath + "/unexpected_end_of_demo.dem"
)

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

func TestRetake_BadBombsiteIndex(t *testing.T) {
t.Parallel()

if testing.Short() {
t.Skip("skipping test due to -short flag")
}

f := openFile(t, retakeDemPath)
defer mustClose(t, f)

p := demoinfocs.NewParser(f)

err := p.ParseToEnd()
assert.Error(t, err, demoinfocs.ErrBombsiteIndexNotFound)
}

func TestRetake_IgnoreBombsiteIndexNotFound(t *testing.T) {
t.Parallel()

if testing.Short() {
t.Skip("skipping test due to -short flag")
}

f := openFile(t, retakeDemPath)
defer mustClose(t, f)

cfg := demoinfocs.DefaultParserConfig
cfg.IgnoreErrBombsiteIndexNotFound = true

p := demoinfocs.NewParserWithConfig(f, cfg)

err := p.ParseToEnd()
assert.NoError(t, err)
}

func TestUnexpectedEndOfDemo(t *testing.T) {
t.Parallel()

Expand Down
5 changes: 3 additions & 2 deletions pkg/demoinfocs/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,9 @@ type bombsite rune

// Bombsite identifiers
const (
BombsiteA bombsite = 'A'
BombsiteB bombsite = 'B'
BomsiteUnknown bombsite = 0
BombsiteA bombsite = 'A'
BombsiteB bombsite = 'B'
)

// BombEvent contains the common attributes of bomb events. Dont register
Expand Down
45 changes: 29 additions & 16 deletions pkg/demoinfocs/game_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/golang/geo/r3"
"github.com/markus-wa/go-unassert"
"github.com/pkg/errors"

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

type gameEventHandler struct {
parser *parser
gameEventNameToHandler map[string]gameEventHandlerFunc
userIDToFallDamageFrame map[int32]int
frameToRoundEndReason map[int]events.RoundEndReason
parser *parser
gameEventNameToHandler map[string]gameEventHandlerFunc
userIDToFallDamageFrame map[int32]int
frameToRoundEndReason map[int]events.RoundEndReason
ignoreBombsiteIndexNotFound bool // see https://github.com/markus-wa/demoinfocs-golang/issues/314
}

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

//nolint:funlen
func newGameEventHandler(parser *parser) gameEventHandler {
func newGameEventHandler(parser *parser, ignoreBombsiteIndexNotFound bool) gameEventHandler {
geh := gameEventHandler{
parser: parser,
userIDToFallDamageFrame: make(map[int32]int),
frameToRoundEndReason: make(map[int]events.RoundEndReason),
parser: parser,
userIDToFallDamageFrame: make(map[int32]int),
frameToRoundEndReason: make(map[int]events.RoundEndReason),
ignoreBombsiteIndexNotFound: ignoreBombsiteIndexNotFound,
}

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

// ErrBombsiteIndexNotFound indicates that a game-event occurred that contained an unknown bombsite index.
// This error can be disabled by setting ParserConfig.IgnoreErrBombsiteIndexNotFound = true.
// See https://github.com/markus-wa/demoinfocs-golang/issues/314
var ErrBombsiteIndexNotFound = errors.New("bombsite index not found - see https://github.com/markus-wa/demoinfocs-golang/issues/314")

func (geh gameEventHandler) bombEvent(data map[string]*msg.CSVCMsg_GameEventKeyT) (events.BombEvent, error) {
bombEvent := events.BombEvent{Player: geh.playerByUserID32(data["userid"].GetValShort())}

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

// when not found, only error if site is not 0, for retake games it may be 0 => unknown
if t == nil {
return bombEvent, fmt.Errorf("bombsite with index %d not found", site)
if !geh.ignoreBombsiteIndexNotFound {
return bombEvent, errors.Wrapf(ErrBombsiteIndexNotFound, "bombsite with index %d not found", site)
}
} else {
if t.contains(geh.parser.bombsiteA.center) {
bombEvent.Site = events.BombsiteA
geh.parser.bombsiteA.index = site
} else if t.contains(geh.parser.bombsiteB.center) {
bombEvent.Site = events.BombsiteB
geh.parser.bombsiteB.index = site
}
}

if t.contains(geh.parser.bombsiteA.center) {
bombEvent.Site = events.BombsiteA
geh.parser.bombsiteA.index = site
} else if t.contains(geh.parser.bombsiteB.center) {
bombEvent.Site = events.BombsiteB
geh.parser.bombsiteB.index = site
} else {
if bombEvent.Site == events.BomsiteUnknown {
// this may occur on de_grind for bombsite B, really makes you think
// see https://github.com/markus-wa/demoinfocs-golang/issues/280
geh.dispatch(events.ParserWarn{
Expand Down
6 changes: 5 additions & 1 deletion pkg/demoinfocs/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ type ParserConfig struct {
// Check out parsing.go to see which net-messages are already being parsed by default.
// This is a beta feature and may be changed or replaced without notice.
AdditionalNetMessageCreators map[int]NetMessageCreator

// IgnoreErrBombsiteIndexNotFound tells the parser to not return an error when a bombsite-index from a game-event is not found in the demo.
// See https://github.com/markus-wa/demoinfocs-golang/issues/314
IgnoreErrBombsiteIndexNotFound bool
}

// DefaultParserConfig is the default Parser configuration used by NewParser().
Expand All @@ -334,7 +338,7 @@ func NewParserWithConfig(demostream io.Reader, config ParserConfig) Parser {
p.demoInfoProvider = demoInfoProvider{parser: &p}
p.gameState = newGameState(p.demoInfoProvider)
p.grenadeModelIndices = make(map[int]common.EquipmentType)
p.gameEventHandler = newGameEventHandler(&p)
p.gameEventHandler = newGameEventHandler(&p, config.IgnoreErrBombsiteIndexNotFound)
p.userMessageHandler = newUserMessageHandler(&p)
p.bombsiteA.index = -1
p.bombsiteB.index = -1
Expand Down
2 changes: 1 addition & 1 deletion scripts/coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

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

# don't cover mocks and generated protobuf code
coverpkg_ignore='/(fake|msg)'
Expand Down
2 changes: 1 addition & 1 deletion test/cs-demos
Submodule cs-demos updated from 851caa to 2be846

0 comments on commit ce1ecd5

Please sign in to comment.