@@ -15,6 +15,10 @@ const (
1515 playerWeaponPrePrefix = "bcc_nonlocaldata."
1616)
1717
18+ const (
19+ msgHeaderNotParsed = "Tried to parse tick before parsing header"
20+ )
21+
1822// ParseHeader attempts to parse the header of the demo.
1923// Returns error if the filestamp (first 8 bytes) doesn't match HL2DEMO.
2024func (p * Parser ) ParseHeader () error {
@@ -35,6 +39,12 @@ func (p *Parser) ParseHeader() error {
3539 return errors .New ("Invalid File-Type; expecting HL2DEMO in the first 8 bytes" )
3640 }
3741
42+ // Initialize queue if the buffer size wasn't specified, the amount of ticks
43+ // seems to be a good indicator of how many events we'll get
44+ if p .msgQueue == nil {
45+ p .initMsgQueue (h .PlaybackTicks )
46+ }
47+
3848 p .header = & h
3949 p .eventDispatcher .Dispatch (events.HeaderParsedEvent {Header : h })
4050 return nil
@@ -44,20 +54,30 @@ func (p *Parser) ParseHeader() error {
4454// Aborts and returns an error if Cancel() is called before the end.
4555// May panic if the demo is corrupt in some way.
4656func (p * Parser ) ParseToEnd () error {
57+ if p .header == nil {
58+ panic (msgHeaderNotParsed )
59+ }
60+
4761 for {
4862 select {
4963 case <- p .cancelChan :
5064 return errors .New ("Parsing was cancelled before it finished" )
5165
5266 default :
53- if ! p .ParseNextFrame () {
67+ if ! p .parseFrame () {
68+ // Make sure all the messages of the demo are handled
69+ p .msgDispatcher .SyncQueues (p .msgQueue )
70+
71+ // Close msgQueue
72+ close (p .msgQueue )
5473 return nil
5574 }
5675 }
5776 }
5877}
5978
60- // Cancel aborts ParseToEnd() on the upcoming tick.
79+ // Cancel aborts ParseToEnd(). All information that was already read
80+ // up to this point will still be used (and new events may still be sent).
6181func (p * Parser ) Cancel () {
6282 p .cancelChan <- struct {}{}
6383}
@@ -67,56 +87,30 @@ func (p *Parser) Cancel() {
6787// Panics if header hasn't been parsed yet - see Parser.ParseHeader().
6888func (p * Parser ) ParseNextFrame () bool {
6989 if p .header == nil {
70- panic ("Tried to parse tick before parsing header" )
90+ panic (msgHeaderNotParsed )
7191 }
72- b := p .parseFrame ()
73-
74- for k , rp := range p .rawPlayers {
75- if rp == nil {
76- continue
77- }
78-
79- if pl := p .players [k ]; pl != nil {
80- newPlayer := false
81- if p .connectedPlayers [rp .UserID ] == nil {
82- p .connectedPlayers [rp .UserID ] = pl
83- newPlayer = true
84- }
8592
86- pl .Name = rp .Name
87- pl .SteamID = rp .XUID
88- pl .IsBot = rp .IsFakePlayer
89- pl .AdditionalPlayerInformation = & p .additionalPlayerInfo [pl .EntityID ]
90-
91- if pl .IsAlive () {
92- pl .LastAlivePosition = pl .Position
93- }
94-
95- if newPlayer && pl .SteamID != 0 {
96- p .eventDispatcher .Dispatch (events.PlayerBindEvent {Player : pl })
97- }
98- }
99- }
93+ b := p .parseFrame ()
10094
101- p .eventDispatcher .Dispatch (events.TickDoneEvent {})
95+ // Make sure all the messages of the frame are handled
96+ p .msgDispatcher .SyncQueues (p .msgQueue )
10297
98+ // Close msgQueue if we are done
10399 if ! b {
104100 close (p .msgQueue )
105101 }
106-
107102 return b
108103}
109104
110105func (p * Parser ) parseFrame () bool {
111106 cmd := demoCommand (p .bitReader .ReadSingleByte ())
112107
113- // Ingame tick number
114- p .ingameTick = p .bitReader .ReadSignedInt (32 )
108+ // Send ingame tick number update
109+ p .msgQueue <- ingameTickNumber (p .bitReader .ReadSignedInt (32 ))
110+
115111 // Skip 'player slot'
116112 p .bitReader .ReadSingleByte ()
117113
118- p .currentFrame ++
119-
120114 switch cmd {
121115 case dcSynctick :
122116 // Ignore
@@ -130,6 +124,8 @@ func (p *Parser) parseFrame() bool {
130124 p .bitReader .EndChunk ()
131125
132126 case dcDataTables :
127+ p .msgDispatcher .SyncQueues (p .msgQueue )
128+
133129 p .bitReader .BeginChunk (p .bitReader .ReadSignedInt (32 ) << 3 )
134130 p .stParser .ParsePacket (p .bitReader )
135131 p .bitReader .EndChunk ()
@@ -138,6 +134,8 @@ func (p *Parser) parseFrame() bool {
138134 p .bindEntities ()
139135
140136 case dcStringTables :
137+ p .msgDispatcher .SyncQueues (p .msgQueue )
138+
141139 p .parseStringTables ()
142140
143141 case dcUserCommand :
@@ -158,5 +156,9 @@ func (p *Parser) parseFrame() bool {
158156 default :
159157 panic (fmt .Sprintf ("Canny handle it anymoe (command %v unknown)" , cmd ))
160158 }
159+
160+ // Queue up some post processing
161+ p .msgQueue <- frameParsedToken
162+
161163 return true
162164}
0 commit comments