Skip to content

Commit 784bee1

Browse files
authored
Merge pull request #417 from akiver/rank
feat: add player rank properties
2 parents 66c5d56 + 7de8cfb commit 784bee1

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

pkg/demoinfocs/common/player.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,51 @@ func (p *Player) Armor() int {
368368
return getInt(p.Entity, "m_ArmorValue")
369369
}
370370

371+
// RankType returns the current rank type that the player is playing for.
372+
// CS:GO values:
373+
// -1 -> Information not present, the demo is too old
374+
// 0 -> None/not available
375+
// 6 -> Classic Competitive
376+
// 7 -> Wingman 2v2
377+
// 10 -> Danger zone
378+
//
379+
// CS2 values:
380+
// -1 -> Not available, demo probably not coming from a Valve server
381+
// 0 -> None?
382+
// 11 -> Classic Competitive
383+
func (p *Player) RankType() int {
384+
if p.demoInfoProvider.IsSource2() {
385+
return getInt(p.Entity, "m_iCompetitiveRankType")
386+
}
387+
388+
// This prop is not available in old demos
389+
if prop, exists := p.resourceEntity().PropertyValue("m_iCompetitiveRankType." + p.entityIDStr()); exists {
390+
return prop.Int()
391+
}
392+
393+
return -1
394+
}
395+
396+
// Rank returns the current rank of the player for the current RankType.
397+
// CS:GO demos -> from 0 to 18 (0 = unranked/unknown, 18 = Global Elite)
398+
// CS2 demos -> Number representation of the player's rank.
399+
func (p *Player) Rank() int {
400+
if p.demoInfoProvider.IsSource2() {
401+
return getInt(p.Entity, "m_iCompetitiveRanking")
402+
}
403+
404+
return getInt(p.resourceEntity(), "m_iCompetitiveRanking."+p.entityIDStr())
405+
}
406+
407+
// CompetitiveWins returns the amount of competitive wins the player has for the current RankType.
408+
func (p *Player) CompetitiveWins() int {
409+
if p.demoInfoProvider.IsSource2() {
410+
return getInt(p.Entity, "m_iCompetitiveWins")
411+
}
412+
413+
return getInt(p.resourceEntity(), "m_iCompetitiveWins."+p.entityIDStr())
414+
}
415+
371416
// Money returns the amount of money in the player's bank.
372417
func (p *Player) Money() int {
373418
if p.demoInfoProvider.IsSource2() {

pkg/demoinfocs/common/player_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,24 @@ func TestPlayer_LastPlaceName(t *testing.T) {
561561
assert.Equal(t, "TopofMid", pl.LastPlaceName())
562562
}
563563

564+
func TestPlayer_RankType(t *testing.T) {
565+
pl := playerWithResourceProperty("m_iCompetitiveRankType", st.PropertyValue{IntVal: 6})
566+
567+
assert.Equal(t, 6, pl.RankType())
568+
}
569+
570+
func TestPlayer_Rank(t *testing.T) {
571+
pl := playerWithResourceProperty("m_iCompetitiveRanking", st.PropertyValue{IntVal: 10})
572+
573+
assert.Equal(t, 10, pl.Rank())
574+
}
575+
576+
func TestPlayer_CompetitiveWins(t *testing.T) {
577+
pl := playerWithResourceProperty("m_iCompetitiveWins", st.PropertyValue{IntVal: 190})
578+
579+
assert.Equal(t, 190, pl.CompetitiveWins())
580+
}
581+
564582
func newPlayer(tick int) *Player {
565583
return NewPlayer(mockDemoInfoProvider(128, tick))
566584
}

pkg/demoinfocs/net_messages.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/binary"
66
"fmt"
77

8+
"github.com/markus-wa/go-unassert"
89
"github.com/markus-wa/ice-cipher-go/pkg/ice"
910
"google.golang.org/protobuf/proto"
1011

@@ -108,6 +109,28 @@ func (p *parser) handleServerInfoS2(srvInfo *msgs2.CSVCMsg_ServerInfo) {
108109
})
109110
}
110111

112+
func (p *parser) handleServerRankUpdate(msg *msgs2.CCSUsrMsg_ServerRankUpdate) {
113+
for _, v := range msg.RankUpdate {
114+
steamID32 := uint32(v.GetAccountId())
115+
player, ok := p.gameState.playersBySteamID32[steamID32]
116+
if !ok {
117+
errMsg := fmt.Sprintf("rank update for unknown player with SteamID32=%d", steamID32)
118+
119+
p.eventDispatcher.Dispatch(events.ParserWarn{Message: errMsg})
120+
unassert.Error(errMsg)
121+
}
122+
123+
p.eventDispatcher.Dispatch(events.RankUpdate{
124+
SteamID32: v.GetAccountId(),
125+
RankOld: int(v.GetRankOld()),
126+
RankNew: int(v.GetRankNew()),
127+
WinCount: int(v.GetNumWins()),
128+
RankChange: v.GetRankChange(),
129+
Player: player,
130+
})
131+
}
132+
}
133+
111134
func (p *parser) handleEncryptedData(msg *msg.CSVCMsg_EncryptedData) {
112135
if msg.GetKeyType() != 2 {
113136
return

pkg/demoinfocs/parser.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ func NewParserWithConfig(demostream io.Reader, config ParserConfig) Parser {
411411
p.msgDispatcher.RegisterHandler(p.handleCreateStringTableS2)
412412
p.msgDispatcher.RegisterHandler(p.handleUpdateStringTableS2)
413413
p.msgDispatcher.RegisterHandler(p.handleSetConVarS2)
414+
p.msgDispatcher.RegisterHandler(p.handleServerRankUpdate)
414415

415416
if config.MsgQueueBufferSize >= 0 {
416417
p.initMsgQueue(config.MsgQueueBufferSize)

0 commit comments

Comments
 (0)