Skip to content

Commit 87c1934

Browse files
committed
no longer export DemoHeader etc. - should use DemoFileHeader & ServerInfo
1 parent 8cd2bcb commit 87c1934

13 files changed

+570
-154
lines changed

examples/print-events/print_events.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
demoinfocs "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs"
99
common "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/common"
1010
events "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/events"
11+
"github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/msg"
1112
)
1213

1314
// Run like this: go run print_events.go -demo /path/to/demo.dem
@@ -20,10 +21,9 @@ func main() {
2021
p := demoinfocs.NewParser(f)
2122
defer p.Close()
2223

23-
// Parse header
24-
header, err := p.ParseHeader()
25-
checkError(err)
26-
fmt.Println("Map:", header.MapName)
24+
p.RegisterNetMessageHandler(func(m *msg.CSVCMsg_ServerInfo) {
25+
fmt.Println("Map:", m.GetMapName())
26+
})
2727

2828
// Register handler on kill events
2929
p.RegisterEventHandler(func(e events.Kill) {

pkg/demoinfocs/common/common.go

-36
Original file line numberDiff line numberDiff line change
@@ -24,42 +24,6 @@ const (
2424
TeamCounterTerrorists Team = 3
2525
)
2626

27-
// DemoHeader contains information from a demo's header.
28-
type DemoHeader struct {
29-
Filestamp string // aka. File-type, must be HL2DEMO
30-
NetworkProtocol int // Not sure what this is for
31-
ServerName string // Server's 'hostname' config value
32-
ClientName string // Usually 'GOTV Demo'
33-
MapName string // E.g. de_cache, de_nuke, cs_office, etc.
34-
GameDirectory string // Usually 'csgo'
35-
PlaybackTime time.Duration // Demo duration in seconds (= PlaybackTicks / Server's tickrate)
36-
PlaybackTicks int // Game duration in ticks (= PlaybackTime * Server's tickrate)
37-
PlaybackFrames int // Amount of 'frames' aka demo-ticks recorded (= PlaybackTime * Demo's recording rate)
38-
}
39-
40-
// FrameRate returns the frame rate of the demo (frames / demo-ticks per second).
41-
// Not necessarily the tick-rate the server ran on during the game.
42-
//
43-
// Returns 0 if PlaybackTime or PlaybackFrames are 0 (corrupt demo headers).
44-
func (h *DemoHeader) FrameRate() float64 {
45-
if h.PlaybackTime == 0 {
46-
return 0
47-
}
48-
49-
return float64(h.PlaybackFrames) / h.PlaybackTime.Seconds()
50-
}
51-
52-
// FrameTime returns the time a frame / demo-tick takes in seconds.
53-
//
54-
// Returns 0 if PlaybackTime or PlaybackFrames are 0 (corrupt demo headers).
55-
func (h *DemoHeader) FrameTime() time.Duration {
56-
if h.PlaybackFrames == 0 {
57-
return 0
58-
}
59-
60-
return time.Duration(h.PlaybackTime.Nanoseconds() / int64(h.PlaybackFrames))
61-
}
62-
6327
// GrenadeProjectile is a grenade thrown intentionally by a player. It is used to track grenade projectile
6428
// positions between the time at which they are thrown and until they detonate.
6529
type GrenadeProjectile struct {

pkg/demoinfocs/common/common_test.go

-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package common
22

33
import (
44
"testing"
5-
"time"
65

76
"github.com/golang/geo/r3"
87
"github.com/stretchr/testify/assert"
@@ -32,25 +31,6 @@ func TestGrenadeProjectile_Velocity(t *testing.T) {
3231
assert.Equal(t, expected, p.Velocity())
3332
}
3433

35-
func TestDemoHeader(t *testing.T) {
36-
header := DemoHeader{
37-
PlaybackFrames: 256,
38-
PlaybackTicks: 512,
39-
PlaybackTime: 4 * time.Second,
40-
}
41-
42-
assert.Equal(t, float64(64), header.FrameRate(), "FrameRate should be 64")
43-
assert.Equal(t, time.Second/64, header.FrameTime(), "FrameTime should be 1/64 sec")
44-
}
45-
46-
func TestDemoHeader_FrameRate_PlaybackTime_Zero(t *testing.T) {
47-
assert.Zero(t, new(DemoHeader).FrameRate())
48-
}
49-
50-
func TestDemoHeader_FrameTime_PlaybackFrames_Zero(t *testing.T) {
51-
assert.Zero(t, new(DemoHeader).FrameTime())
52-
}
53-
5434
func TestTeamState_Team(t *testing.T) {
5535
tState := NewTeamState(TeamTerrorists, nil, demoInfoProviderMock{})
5636
ctState := NewTeamState(TeamCounterTerrorists, nil, demoInfoProviderMock{})

pkg/demoinfocs/datatables_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/stretchr/testify/assert"
88
"github.com/stretchr/testify/mock"
99

10-
common "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/common"
1110
events "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/events"
1211
stfake "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/sendtables/fake"
1312
)
@@ -21,7 +20,7 @@ func (DevNullReader) Read(p []byte) (n int, err error) {
2120

2221
func newParser() *parser {
2322
p := NewParser(new(DevNullReader)).(*parser)
24-
p.header = &common.DemoHeader{}
23+
p.header = &header{}
2524

2625
return p
2726
}

pkg/demoinfocs/demoinfocs_test.go

-21
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,6 @@ func TestDemoInfoCs(t *testing.T) {
6666
actual.WriteString(fmt.Sprintf("%#v\n", e))
6767
})
6868

69-
t.Log("Parsing header")
70-
h, err := p.ParseHeader()
71-
assertions.NoError(err, "error returned by Parser.ParseHeader()")
72-
assertions.Equal(h, p.Header(), "values returned by ParseHeader() and Header() don't match")
73-
t.Logf("Header: %v - FrameRate()=%.2f frames/s ; FrameTime()=%s ; TickRate()=%.2f frames/s ; TickTime()=%s\n", h, h.FrameRate(), h.FrameTime(), p.TickRate(), p.TickTime())
74-
7569
t.Log("Registering handlers")
7670
gs := p.GameState()
7771
p.RegisterEventHandler(func(e events.RoundEnd) {
@@ -218,10 +212,6 @@ func TestS2(t *testing.T) {
218212
})
219213
}
220214

221-
t.Log("Parsing header")
222-
_, err = p.ParseHeader()
223-
assertions.NoError(err, "error returned by Parser.ParseHeader()")
224-
225215
t.Log("Parsing to end")
226216
err = p.ParseToEnd()
227217
assertions.NoError(err, "error occurred in ParseToEnd()")
@@ -315,10 +305,6 @@ func TestInvalidFileType(t *testing.T) {
315305
msgWrongError := "invalid demo but error was not ErrInvalidFileType"
316306

317307
p := demoinfocs.NewParser(bytes.NewBuffer(invalidDemoData))
318-
_, err = p.ParseHeader()
319-
assert.Equal(t, demoinfocs.ErrInvalidFileType, err, msgWrongError)
320-
321-
p = demoinfocs.NewParser(bytes.NewBuffer(invalidDemoData))
322308
_, err = p.ParseNextFrame()
323309
assert.Equal(t, demoinfocs.ErrInvalidFileType, err, msgWrongError)
324310

@@ -395,13 +381,6 @@ func testDemoSet(t *testing.T, path string) {
395381

396382
p.RegisterEventHandler(func(warn events.ParserWarn) {
397383
switch warn.Type {
398-
case events.WarnTypeBombsiteUnknown:
399-
if p.Header().MapName == "de_grind" {
400-
t.Log("expected known issue with bomb sites on de_grind occurred:", warn.Message)
401-
402-
return
403-
}
404-
405384
case events.WarnTypeTeamSwapPlayerNil:
406385
t.Log("expected known issue with team swaps occurred:", warn.Message)
407386
return

pkg/demoinfocs/fake/parser.go

-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"golang.org/x/exp/constraints"
1111

1212
demoinfocs "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs"
13-
common "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/common"
1413
st "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/sendtables"
1514
)
1615

@@ -91,11 +90,6 @@ func (p *Parser) ServerClasses() st.ServerClasses {
9190
return p.Called().Get(0).(st.ServerClasses)
9291
}
9392

94-
// Header is a mock-implementation of Parser.Header().
95-
func (p *Parser) Header() common.DemoHeader {
96-
return p.Called().Get(0).(common.DemoHeader)
97-
}
98-
9993
// GameState is a mock-implementation of Parser.GameState().
10094
func (p *Parser) GameState() demoinfocs.GameState {
10195
return p.Called().Get(0).(demoinfocs.GameState)
@@ -152,12 +146,6 @@ func (p *Parser) UnregisterNetMessageHandler(identifier dp.HandlerIdentifier) {
152146
p.msgDispatcher.UnregisterHandler(identifier)
153147
}
154148

155-
// ParseHeader is a mock-implementation of Parser.ParseHeader().
156-
func (p *Parser) ParseHeader() (common.DemoHeader, error) {
157-
args := p.Called()
158-
return args.Get(0).(common.DemoHeader), args.Error(1)
159-
}
160-
161149
// ParseToEnd is a mock-implementation of Parser.ParseToEnd().
162150
//
163151
// Dispatches Parser.Events and Parser.NetMessages in the specified order.

pkg/demoinfocs/fake/parser_test.go

-18
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package fake_test
22

33
import (
44
"testing"
5-
"time"
65

76
assert "github.com/stretchr/testify/assert"
87
"google.golang.org/protobuf/proto"
@@ -13,23 +12,6 @@ import (
1312
msg "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/msg"
1413
)
1514

16-
func TestParseHeader(t *testing.T) {
17-
p := fake.NewParser()
18-
expected := common.DemoHeader{
19-
Filestamp: "HL2DEMO",
20-
MapName: "de_cache",
21-
PlaybackFrames: 64 * 1000,
22-
PlaybackTicks: 128 * 1000,
23-
PlaybackTime: time.Second * 1000,
24-
}
25-
p.On("ParseHeader").Return(expected, nil)
26-
27-
actual, err := p.ParseHeader()
28-
29-
assert.Nil(t, err)
30-
assert.Equal(t, expected, actual)
31-
}
32-
3315
func TestParseNextFrameEvents(t *testing.T) {
3416
p := fake.NewParser()
3517
p.On("ParseNextFrame").Return(true, nil)

pkg/demoinfocs/game_state_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ func newPlayer() *common.Player {
282282

283283
func newPlayerWithEntityID(id int) *common.Player {
284284
pl := common.NewPlayer(demoInfoProvider{
285-
parser: &parser{header: &common.DemoHeader{Filestamp: "HL2DEMO"}},
285+
parser: &parser{header: &header{Filestamp: "HL2DEMO"}},
286286
})
287287
pl.Entity = fakePlayerEntity(id)
288288
pl.IsConnected = true

pkg/demoinfocs/parser.go

+43-15
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,42 @@ type sendTableParser interface {
3535
OnEntity(h st.EntityHandler)
3636
}
3737

38+
// header contains information from a demo's header.
39+
type header struct {
40+
Filestamp string // aka. File-type, must be HL2DEMO
41+
NetworkProtocol int // Not sure what this is for
42+
ServerName string // Server's 'hostname' config value
43+
ClientName string // Usually 'GOTV Demo'
44+
MapName string // E.g. de_cache, de_nuke, cs_office, etc.
45+
GameDirectory string // Usually 'csgo'
46+
PlaybackTime time.Duration // Demo duration in seconds (= PlaybackTicks / Server's tickrate)
47+
PlaybackTicks int // Game duration in ticks (= PlaybackTime * Server's tickrate)
48+
PlaybackFrames int // Amount of 'frames' aka demo-ticks recorded (= PlaybackTime * Demo's recording rate)
49+
}
50+
51+
// FrameRate returns the frame rate of the demo (frames / demo-ticks per second).
52+
// Not necessarily the tick-rate the server ran on during the game.
53+
//
54+
// Returns 0 if PlaybackTime or PlaybackFrames are 0 (corrupt demo headers).
55+
func (h *header) FrameRate() float64 {
56+
if h.PlaybackTime == 0 {
57+
return 0
58+
}
59+
60+
return float64(h.PlaybackFrames) / h.PlaybackTime.Seconds()
61+
}
62+
63+
// FrameTime returns the time a frame / demo-tick takes in seconds.
64+
//
65+
// Returns 0 if PlaybackTime or PlaybackFrames are 0 (corrupt demo headers).
66+
func (h *header) FrameTime() time.Duration {
67+
if h.PlaybackFrames == 0 {
68+
return 0
69+
}
70+
71+
return time.Duration(h.PlaybackTime.Nanoseconds() / int64(h.PlaybackFrames))
72+
}
73+
3874
/*
3975
Parser can parse a CS:GO demo.
4076
Creating a new instance is done via NewParser().
@@ -50,8 +86,6 @@ Example (without error handling):
5086
f, _ := os.Open("/path/to/demo.dem")
5187
p := dem.NewParser(f)
5288
defer p.Close()
53-
header := p.ParseHeader()
54-
fmt.Println("Map:", header.MapName)
5589
p.RegisterEventHandler(func(e events.BombExplode) {
5690
fmt.Printf(e.Site, "went BOOM!")
5791
})
@@ -70,9 +104,9 @@ type parser struct {
70104
msgDispatcher *dp.Dispatcher // Net-message dispatcher
71105
gameEventHandler gameEventHandler
72106
eventDispatcher *dp.Dispatcher
73-
currentFrame int // Demo-frame, not ingame-tick
74-
tickInterval float32 // Duration between ticks in seconds
75-
header *common.DemoHeader // Pointer so we can check for nil
107+
currentFrame int // Demo-frame, not ingame-tick
108+
tickInterval float32 // Duration between ticks in seconds
109+
header *header // Pointer so we can check for nil
76110
gameState *gameState
77111
demoInfoProvider demoInfoProvider // Provides demo infos to other packages that the core package depends on
78112
err error // Contains a error that occurred during parsing if any
@@ -129,20 +163,14 @@ func (p *parser) ServerClasses() st.ServerClasses {
129163
return p.stParser.ServerClasses()
130164
}
131165

132-
// Header returns the DemoHeader which contains the demo's metadata.
133-
// Only possible after ParserHeader() has been called.
134-
func (p *parser) Header() common.DemoHeader {
135-
return *p.header
136-
}
137-
138166
// GameState returns the current game-state.
139167
// It contains most of the relevant information about the game such as players, teams, scores, grenades etc.
140168
func (p *parser) GameState() GameState {
141169
return p.gameState
142170
}
143171

144172
// CurrentFrame return the number of the current frame, aka. 'demo-tick' (Since demos often have a different tick-rate than the game).
145-
// Starts with frame 0, should go up to DemoHeader.PlaybackFrames but might not be the case (usually it's just close to it).
173+
// Starts with frame 0, should go up to header.PlaybackFrames but might not be the case (usually it's just close to it).
146174
func (p *parser) CurrentFrame() int {
147175
return p.currentFrame
148176
}
@@ -168,7 +196,7 @@ func (p *parser) TickRate() float64 {
168196
return -1
169197
}
170198

171-
func legacyTickRate(h common.DemoHeader) float64 {
199+
func legacyTickRate(h header) float64 {
172200
if h.PlaybackTime == 0 {
173201
return 0
174202
}
@@ -192,7 +220,7 @@ func (p *parser) TickTime() time.Duration {
192220
return -1
193221
}
194222

195-
func legayTickTime(h common.DemoHeader) time.Duration {
223+
func legayTickTime(h header) time.Duration {
196224
if h.PlaybackTicks == 0 {
197225
return 0
198226
}
@@ -410,7 +438,7 @@ type ParserConfig struct {
410438
// MsgQueueBufferSize defines the size of the internal net-message queue.
411439
// For large demos, fast i/o and slow CPUs higher numbers are suggested and vice versa.
412440
// The buffer size can easily be in the hundred-thousands to low millions for the best performance.
413-
// A negative value will make the Parser automatically decide the buffer size during ParseHeader()
441+
// A negative value will make the Parser automatically decide the buffer size during parseHeader()
414442
// based on the number of ticks in the demo (nubmer of ticks = buffer size);
415443
// this is the default behavior for DefaultParserConfig.
416444
// Zero enforces sequential parsing.

pkg/demoinfocs/parser_interface.go

+1-13
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import (
88

99
st "github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/sendtables"
1010
dp "github.com/markus-wa/godispatch"
11-
12-
"github.com/markus-wa/demoinfocs-golang/v5/pkg/demoinfocs/common"
1311
)
1412

1513
// Parser is an auto-generated interface for Parser, intended to be used when mockability is needed.
@@ -27,8 +25,6 @@ import (
2725
// f, _ := os.Open("/path/to/demo.dem")
2826
// p := dem.NewParser(f)
2927
// defer p.Close()
30-
// header := p.ParseHeader()
31-
// fmt.Println("Map:", header.MapName)
3228
// p.RegisterEventHandler(func(e events.BombExplode) {
3329
// fmt.Printf(e.Site, "went BOOM!")
3430
// })
@@ -39,14 +35,11 @@ type Parser interface {
3935
// ServerClasses returns the server-classes of this demo.
4036
// These are available after events.DataTablesParsed has been fired.
4137
ServerClasses() st.ServerClasses
42-
// Header returns the DemoHeader which contains the demo's metadata.
43-
// Only possible after ParserHeader() has been called.
44-
Header() common.DemoHeader
4538
// GameState returns the current game-state.
4639
// It contains most of the relevant information about the game such as players, teams, scores, grenades etc.
4740
GameState() GameState
4841
// CurrentFrame return the number of the current frame, aka. 'demo-tick' (Since demos often have a different tick-rate than the game).
49-
// Starts with frame 0, should go up to DemoHeader.PlaybackFrames but might not be the case (usually it's just close to it).
42+
// Starts with frame 0, should go up to header.PlaybackFrames but might not be the case (usually it's just close to it).
5043
CurrentFrame() int
5144
// CurrentTime returns the time elapsed since the start of the demo
5245
CurrentTime() time.Duration
@@ -107,11 +100,6 @@ type Parser interface {
107100
// This must be called before discarding the Parser to avoid memory leaks.
108101
// Returns an error if closing of underlying resources fails.
109102
Close() error
110-
// ParseHeader attempts to parse the header of the demo and returns it.
111-
// If not done manually this will be called by Parser.ParseNextFrame() or Parser.ParseToEnd().
112-
//
113-
// Returns ErrInvalidFileType if the filestamp (first 8 bytes) doesn't match HL2DEMO.
114-
ParseHeader() (common.DemoHeader, error)
115103
// ParseToEnd attempts to parse the demo until the end.
116104
// Aborts and returns ErrCancelled if Cancel() is called before the end.
117105
//

0 commit comments

Comments
 (0)