Skip to content

Commit 2d2a26e

Browse files
committed
common: fix Player.CashSpentThisRound() & CashSpentTotal()
fixes #126
1 parent d811b02 commit 2d2a26e

File tree

8 files changed

+80
-64
lines changed

8 files changed

+80
-64
lines changed

common/common.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,15 @@ func (ts TeamState) FreezeTimeEndEquipmentValue() (value int) {
165165
// CashSpentThisRound returns the total amount of cash spent by the whole team in the current round.
166166
func (ts TeamState) CashSpentThisRound() (value int) {
167167
for _, pl := range ts.Members() {
168-
value += pl.CashSpentThisRound()
168+
value += pl.AdditionalPlayerInformation.CashSpentThisRound
169169
}
170170
return
171171
}
172172

173173
// CashSpentThisRound returns the total amount of cash spent by the whole team during the whole game up to the current point.
174174
func (ts TeamState) CashSpentTotal() (value int) {
175175
for _, pl := range ts.Members() {
176-
value += pl.CashSpentTotal()
176+
value += pl.AdditionalPlayerInformation.TotalCashSpent
177177
}
178178
return
179179
}

common/common_test.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66

77
"github.com/golang/geo/r3"
88
"github.com/stretchr/testify/assert"
9-
10-
"github.com/markus-wa/demoinfocs-golang/sendtables"
119
)
1210

1311
func TestBombPosition(t *testing.T) {
@@ -77,23 +75,3 @@ func TestTeamState_FreezeTimeEndEquipmentValue(t *testing.T) {
7775

7876
assert.Equal(t, 300, state.FreezeTimeEndEquipmentValue())
7977
}
80-
81-
func TestTeamState_CashSpentThisRound(t *testing.T) {
82-
members := []*Player{
83-
playerWithProperty("m_iCashSpentThisRound", sendtables.PropertyValue{IntVal: 100}),
84-
playerWithProperty("m_iCashSpentThisRound", sendtables.PropertyValue{IntVal: 200}),
85-
}
86-
state := NewTeamState(TeamTerrorists, func(Team) []*Player { return members })
87-
88-
assert.Equal(t, 300, state.CashSpentThisRound())
89-
}
90-
91-
func TestTeamState_CashSpentTotal(t *testing.T) {
92-
members := []*Player{
93-
playerWithProperty("m_iTotalCashSpent", sendtables.PropertyValue{IntVal: 100}),
94-
playerWithProperty("m_iTotalCashSpent", sendtables.PropertyValue{IntVal: 200}),
95-
}
96-
state := NewTeamState(TeamTerrorists, func(Team) []*Player { return members })
97-
98-
assert.Equal(t, 300, state.CashSpentTotal())
99-
}

common/player.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import (
99

1010
// Player contains mostly game-relevant player information.
1111
type Player struct {
12-
tickRate float64 // the in-game tick rate, used for IsBlinded()
13-
ingameTickProvider ingameTickProvider // provider for the current in-game tick, used for IsBlinded()
12+
demoInfoProvider demoInfoProvider // provider for demo info such as tick-rate or current tick
1413

1514
SteamID int64 // int64 representation of the User's Steam ID
1615
Position r3.Vector // In-game coordinates. Like the one you get from cl_showpos 1
@@ -73,11 +72,12 @@ func (p *Player) flashDurationTimeFull() time.Duration {
7372
func (p *Player) FlashDurationTimeRemaining() time.Duration {
7473
// In case the demo header is broken
7574
// TODO: read tickRate from CVARs as fallback
76-
if p.tickRate == 0 {
75+
tickRate := p.demoInfoProvider.TickRate()
76+
if tickRate == 0 {
7777
return time.Duration(p.FlashDuration) * time.Second
7878
}
7979

80-
timeSinceFlash := time.Duration(float64(p.ingameTickProvider()-p.FlashTick) / p.tickRate * float64(time.Second))
80+
timeSinceFlash := time.Duration(float64(p.demoInfoProvider.IngameTick()-p.FlashTick) / tickRate * float64(time.Second))
8181
remaining := p.flashDurationTimeFull() - timeSinceFlash
8282
if remaining < 0 {
8383
return 0
@@ -159,37 +159,43 @@ func (p *Player) IsScoped() bool {
159159
}
160160

161161
// CashSpentThisRound returns the amount of cash the player spent in the current round.
162+
//
163+
// Deprecated, use Player.AdditionalPlayerInformation.CashSpentThisRound instead.
162164
func (p *Player) CashSpentThisRound() int {
163-
return p.Entity.FindPropertyI("m_iCashSpentThisRound").Value().IntVal
165+
return p.AdditionalPlayerInformation.CashSpentThisRound
164166
}
165167

166168
// CashSpentTotal returns the amount of cash the player spent during the whole game up to the current point.
169+
//
170+
// Deprecated, use Player.AdditionalPlayerInformation.TotalCashSpent instead.
167171
func (p *Player) CashSpentTotal() int {
168-
return p.Entity.FindPropertyI("m_iTotalCashSpent").Value().IntVal
172+
return p.AdditionalPlayerInformation.TotalCashSpent
169173
}
170174

171175
// AdditionalPlayerInformation contains mostly scoreboard information.
172176
type AdditionalPlayerInformation struct {
173-
Kills int
174-
Deaths int
175-
Assists int
176-
Score int
177-
MVPs int
178-
Ping int
179-
ClanTag string
180-
TotalCashSpent int
177+
Kills int
178+
Deaths int
179+
Assists int
180+
Score int
181+
MVPs int
182+
Ping int
183+
ClanTag string
184+
TotalCashSpent int
185+
CashSpentThisRound int
181186
}
182187

183-
// ingameTickProvider is a function that returns the current ingame tick of the demo related to a player.
184-
type ingameTickProvider func() int
188+
type demoInfoProvider interface {
189+
IngameTick() int // current in-game tick, used for IsBlinded()
190+
TickRate() float64 // in-game tick rate, used for Player.IsBlinded()
191+
}
185192

186193
// NewPlayer creates a *Player with an initialized equipment map.
187194
//
188195
// Intended for internal use only.
189-
func NewPlayer(tickRate float64, ingameTickProvider ingameTickProvider) *Player {
196+
func NewPlayer(demoInfoProvider demoInfoProvider) *Player {
190197
return &Player{
191-
RawWeapons: make(map[int]*Equipment),
192-
tickRate: tickRate,
193-
ingameTickProvider: ingameTickProvider,
198+
RawWeapons: make(map[int]*Equipment),
199+
demoInfoProvider: demoInfoProvider,
194200
}
195201
}

common/player_test.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func TestPlayer_FlashDurationTime(t *testing.T) {
8787
}
8888

8989
func TestPlayer_FlashDurationTimeRemaining_Default(t *testing.T) {
90-
pl := NewPlayer(0, tickProvider(128))
90+
pl := NewPlayer(mockDemoInfoProvider(0, 128))
9191

9292
assert.Equal(t, time.Duration(0), pl.FlashDurationTimeRemaining())
9393
}
@@ -117,7 +117,7 @@ func TestPlayer_FlashDurationTimeRemaining_FlashDuration_Over(t *testing.T) {
117117
}
118118

119119
func TestPlayer_FlashDurationTimeRemaining_Fallback(t *testing.T) {
120-
pl := NewPlayer(0, tickProvider(128))
120+
pl := NewPlayer(mockDemoInfoProvider(0, 128))
121121

122122
pl.FlashDuration = 2
123123
pl.FlashTick = 128 * 2
@@ -191,24 +191,28 @@ func TestPlayer_IsScoped(t *testing.T) {
191191
assert.True(t, pl.IsScoped())
192192
}
193193

194-
func TestPlayer_CashSpentThisRound(t *testing.T) {
195-
pl := playerWithProperty("m_iCashSpentThisRound", sendtables.PropertyValue{IntVal: 500})
196-
197-
assert.Equal(t, 500, pl.CashSpentThisRound())
194+
func newPlayer(tick int) *Player {
195+
return NewPlayer(mockDemoInfoProvider(128, tick))
198196
}
199197

200-
func TestPlayer_CashSpentTotal(t *testing.T) {
201-
pl := playerWithProperty("m_iTotalCashSpent", sendtables.PropertyValue{IntVal: 500})
198+
type demoInfoProviderMock struct {
199+
tickRate float64
200+
ingameTick int
201+
}
202202

203-
assert.Equal(t, 500, pl.CashSpentTotal())
203+
func (p demoInfoProviderMock) TickRate() float64 {
204+
return p.tickRate
204205
}
205206

206-
func newPlayer(tick int) *Player {
207-
return NewPlayer(128, tickProvider(tick))
207+
func (p demoInfoProviderMock) IngameTick() int {
208+
return p.ingameTick
208209
}
209210

210-
func tickProvider(tick int) ingameTickProvider {
211-
return func() int { return tick }
211+
func mockDemoInfoProvider(tickRate float64, tick int) demoInfoProvider {
212+
return demoInfoProviderMock{
213+
tickRate: tickRate,
214+
ingameTick: tick,
215+
}
212216
}
213217

214218
func playerWithProperty(propName string, value sendtables.PropertyValue) *Player {

datatables.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ func (p *Parser) bindPlayers() {
174174
plInfo.BindProperty("m_iAssists."+iStr, &p.additionalPlayerInfo[i2].Assists, st.ValTypeInt)
175175
plInfo.BindProperty("m_iMVPs."+iStr, &p.additionalPlayerInfo[i2].MVPs, st.ValTypeInt)
176176
plInfo.BindProperty("m_iTotalCashSpent."+iStr, &p.additionalPlayerInfo[i2].TotalCashSpent, st.ValTypeInt)
177+
if prop := plInfo.FindProperty("m_iCashSpentThisRound." + iStr); prop != nil {
178+
prop.Bind(&p.additionalPlayerInfo[i2].CashSpentThisRound, st.ValTypeInt)
179+
}
177180
}
178181
})
179182
}
@@ -191,7 +194,7 @@ func (p *Parser) bindNewPlayer(playerEntity st.IEntity) {
191194
isNew = true
192195

193196
// TODO: read tickRate from CVARs as fallback
194-
pl = common.NewPlayer(p.header.TickRate(), p.gameState.IngameTick)
197+
pl = common.NewPlayer(p.demoInfoProvider)
195198
pl.Name = rp.name
196199
pl.SteamID = rp.xuid
197200
pl.IsBot = rp.isFakePlayer || rp.guid == "BOT"

events/events_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
func TestPlayerFlashed_FlashDuration(t *testing.T) {
13-
p := common.NewPlayer(128, func() int { return 0 })
13+
p := common.NewPlayer(demoInfoProvider{})
1414
e := PlayerFlashed{Player: p}
1515

1616
assert.Equal(t, time.Duration(0), e.FlashDuration())
@@ -41,3 +41,14 @@ func TestBombEvents(t *testing.T) {
4141
e.implementsBombEventIf()
4242
}
4343
}
44+
45+
type demoInfoProvider struct {
46+
}
47+
48+
func (p demoInfoProvider) IngameTick() int {
49+
return 0
50+
}
51+
52+
func (p demoInfoProvider) TickRate() float64 {
53+
return 128
54+
}

game_state_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func TestParticipants_FindByHandle_InvalidEntityHandle(t *testing.T) {
149149

150150
func TestParticipants_Connected_SuppressNoEntity(t *testing.T) {
151151
pl := newPlayer()
152-
pl2 := common.NewPlayer(0, func() int { return 0 })
152+
pl2 := common.NewPlayer(nil)
153153
pl2.IsConnected = true
154154

155155
ptcps := Participants{
@@ -254,7 +254,7 @@ func TestParticipants_SpottedBy(t *testing.T) {
254254
}
255255

256256
func newPlayer() *common.Player {
257-
pl := common.NewPlayer(0, func() int { return 0 })
257+
pl := common.NewPlayer(nil)
258258
pl.Entity = new(st.Entity)
259259
pl.IsConnected = true
260260
return pl

parser.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ type Parser struct {
5454
currentFrame int // Demo-frame, not ingame-tick
5555
header *common.DemoHeader // Pointer so we can check for nil
5656
gameState *GameState
57-
cancelChan chan struct{} // Non-anime-related, used for aborting the parsing
58-
err error // Contains a error that occurred during parsing if any
59-
errLock sync.Mutex // Used to sync up error mutations between parsing & handling go-routines
57+
demoInfoProvider demoInfoProvider // Provides demo infos to other packages that the core package depends on
58+
cancelChan chan struct{} // Non-anime-related, used for aborting the parsing
59+
err error // Contains a error that occurred during parsing if any
60+
errLock sync.Mutex // Used to sync up error mutations between parsing & handling go-routines
6061

6162
// Additional fields, mainly caching & tracking things
6263

@@ -243,6 +244,7 @@ func NewParserWithConfig(demostream io.Reader, config ParserConfig) *Parser {
243244
p.grenadeModelIndices = make(map[int]common.EquipmentElement)
244245
p.gameEventHandler = newGameEventHandler(&p)
245246
p.userMessageHandler = newUserMessageHandler(&p)
247+
p.demoInfoProvider = demoInfoProvider{parser: &p}
246248

247249
// Attach proto msg handlers
248250
p.msgDispatcher.RegisterHandler(p.handlePacketEntities)
@@ -267,3 +269,15 @@ func (p *Parser) initMsgQueue(buf int) {
267269
p.msgQueue = make(chan interface{}, buf)
268270
p.msgDispatcher.AddQueues(p.msgQueue)
269271
}
272+
273+
type demoInfoProvider struct {
274+
parser *Parser
275+
}
276+
277+
func (p demoInfoProvider) IngameTick() int {
278+
return p.parser.gameState.IngameTick()
279+
}
280+
281+
func (p demoInfoProvider) TickRate() float64 {
282+
return p.parser.header.TickRate()
283+
}

0 commit comments

Comments
 (0)