Skip to content

Commit 4f818b0

Browse files
committed
improve SteamID64 handling + change from int64 to uint64
1 parent c4fa251 commit 4f818b0

File tree

6 files changed

+80
-31
lines changed

6 files changed

+80
-31
lines changed

pkg/demoinfocs/common/common.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package common
33

44
import (
55
"math/rand"
6+
"strconv"
7+
"strings"
68
"time"
79

810
"github.com/golang/geo/r3"
@@ -205,3 +207,35 @@ func NewTeamState(team Team, membersCallback func(Team) []*Player) TeamState {
205207
membersCallback: membersCallback,
206208
}
207209
}
210+
211+
// ConvertSteamIDTxtTo32 converts a Steam-ID in text format to a 32-bit variant.
212+
// See https://developer.valvesoftware.com/wiki/SteamID
213+
func ConvertSteamIDTxtTo32(steamID string) (uint32, error) {
214+
arr := strings.Split(steamID, ":")
215+
216+
Y, err := strconv.ParseUint(arr[1], 10, 32)
217+
if err != nil {
218+
return 0, err
219+
}
220+
221+
Z, err := strconv.ParseUint(arr[2], 10, 32)
222+
if err != nil {
223+
return 0, err
224+
}
225+
226+
return uint32((Z << 1) + Y), nil
227+
}
228+
229+
const steamID64IndividualIdentifier = 0x0110000100000000
230+
231+
// ConvertSteamID32To64 converts a Steam-ID in 32-bit format to a 64-bit variant.
232+
// See https://developer.valvesoftware.com/wiki/SteamID
233+
func ConvertSteamID32To64(steamID32 uint32) uint64 {
234+
return steamID64IndividualIdentifier + uint64(steamID32)
235+
}
236+
237+
// ConvertSteamID64To32 converts a Steam-ID in 64-bit format to a 32-bit variant.
238+
// See https://developer.valvesoftware.com/wiki/SteamID
239+
func ConvertSteamID64To32(steamID64 uint64) uint32 {
240+
return uint32(steamID64 - steamID64IndividualIdentifier)
241+
}

pkg/demoinfocs/common/common_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,37 @@ func TestTeamState_MoneySpentTotal(t *testing.T) {
113113
assert.Equal(t, 300, state.MoneySpentTotal())
114114
}
115115

116+
func TestConvertSteamIDTxtTo32(t *testing.T) {
117+
id, err := ConvertSteamIDTxtTo32("STEAM_0:1:26343269")
118+
119+
assert.Nil(t, err)
120+
assert.Equal(t, uint32(52686539), id)
121+
}
122+
123+
func TestConvertSteamIDTxtTo32_Error(t *testing.T) {
124+
id, err := ConvertSteamIDTxtTo32("STEAM_0:1:a")
125+
126+
assert.Equal(t, uint32(0), id)
127+
assert.NotNil(t, err)
128+
129+
id, err = ConvertSteamIDTxtTo32("STEAM_0:b:21643603")
130+
131+
assert.Equal(t, uint32(0), id)
132+
assert.NotNil(t, err)
133+
}
134+
135+
func TestConvertSteamID32To64(t *testing.T) {
136+
id := ConvertSteamID32To64(52686539)
137+
138+
assert.Equal(t, uint64(76561198012952267), id)
139+
}
140+
141+
func TestConvertSteamID64To32(t *testing.T) {
142+
id := ConvertSteamID64To32(76561198012952267)
143+
144+
assert.Equal(t, uint32(52686539), id)
145+
}
146+
116147
type demoInfoProviderMock struct {
117148
tickRate float64
118149
ingameTick int

pkg/demoinfocs/common/player.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const (
2121
type Player struct {
2222
demoInfoProvider demoInfoProvider // provider for demo info such as tick-rate or current tick
2323

24-
SteamID int64 // int64 representation of the User's Steam ID
24+
SteamID uint64 // int64 representation of the User's Steam ID
2525
LastAlivePosition r3.Vector // The location where the player was last alive. Should be equal to Position if the player is still alive.
2626
UserID int // Mostly used in game-events to address this player
2727
Name string // Steam / in-game user name

pkg/demoinfocs/game_events.go

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package demoinfocs
33
import (
44
"errors"
55
"fmt"
6-
"strconv"
7-
86
"github.com/golang/geo/r3"
97
"github.com/markus-wa/go-unassert"
108

@@ -427,7 +425,7 @@ func (geh gameEventHandler) playerConnect(data map[string]*msg.CSVCMsg_GameEvent
427425
}
428426

429427
var err error
430-
pl.xuid, err = getCommunityID(pl.guid)
428+
pl.xuid, err = guidToSteamID64(pl.guid)
431429

432430
if err != nil {
433431
geh.parser.setError(fmt.Errorf("failed to parse player XUID: %v", err.Error()))
@@ -734,24 +732,15 @@ func mapGameEventData(d *msg.CSVCMsg_GameEventListDescriptorT, e *msg.CSVCMsg_Ga
734732
return data
735733
}
736734

737-
// We're all better off not asking questions
738-
const valveMagicNumber = 76561197960265728
739-
740-
func getCommunityID(guid string) (int64, error) {
735+
func guidToSteamID64(guid string) (uint64, error) {
741736
if guid == "BOT" {
742737
return 0, nil
743738
}
744739

745-
authSrv, errSrv := strconv.ParseInt(guid[8:9], 10, 64)
746-
if errSrv != nil {
747-
return 0, errSrv
748-
}
749-
750-
authID, errID := strconv.ParseInt(guid[10:], 10, 64)
751-
if errID != nil {
752-
return 0, errID
740+
steamID32, err := common.ConvertSteamIDTxtTo32(guid)
741+
if err != nil {
742+
return 0, err
753743
}
754744

755-
// WTF are we doing here?
756-
return valveMagicNumber + authID*2 + authSrv, nil
745+
return common.ConvertSteamID32To64(steamID32), nil
757746
}

pkg/demoinfocs/game_events_test.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -216,24 +216,19 @@ func TestGetEquipmentInstance_Grenade_Thrown(t *testing.T) {
216216
}
217217

218218
func TestGetCommunityId(t *testing.T) {
219-
xuid, err := getCommunityID("abcdefgh1:3")
219+
xuid, err := guidToSteamID64("STEAM_0:1:26343269")
220220
assert.Nil(t, err)
221-
expected := int64(76561197960265728 + 6 + 1)
222-
assert.Equal(t, expected, xuid)
221+
assert.Equal(t, uint64(76561198012952267), xuid)
223222
}
224223

225224
func TestGetCommunityId_BOT(t *testing.T) {
226-
xuid, err := getCommunityID("BOT")
225+
xuid, err := guidToSteamID64("BOT")
227226
assert.Zero(t, xuid)
228227
assert.Nil(t, err)
229228
}
230229

231-
func TestGetCommunityId_Errors(t *testing.T) {
232-
_, err := getCommunityID("12345678a90123")
230+
func TestGetCommunityId_Error(t *testing.T) {
231+
_, err := guidToSteamID64("STEAM_0:1:abc")
233232
assert.NotNil(t, err)
234-
assert.Equal(t, "strconv.ParseInt: parsing \"a\": invalid syntax", err.Error())
235-
236-
_, err = getCommunityID("1234567890abc")
237-
assert.NotNil(t, err)
238-
assert.Equal(t, "strconv.ParseInt: parsing \"abc\": invalid syntax", err.Error())
233+
assert.Equal(t, "strconv.ParseUint: parsing \"abc\": invalid syntax", err.Error())
239234
}

pkg/demoinfocs/stringtables.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const (
2121

2222
type playerInfo struct {
2323
version int64
24-
xuid int64
24+
xuid uint64
2525
name string
2626
userID int
2727
guid string
@@ -247,7 +247,7 @@ func parsePlayerInfo(reader io.Reader) *playerInfo {
247247

248248
res := &playerInfo{
249249
version: int64(binary.BigEndian.Uint64(br.ReadBytes(8))),
250-
xuid: int64(binary.BigEndian.Uint64(br.ReadBytes(8))),
250+
xuid: binary.BigEndian.Uint64(br.ReadBytes(8)),
251251
name: br.ReadCString(playerNameMaxLength),
252252
userID: int(int32(binary.BigEndian.Uint32(br.ReadBytes(4)))),
253253
guid: br.ReadCString(guidLength),

0 commit comments

Comments
 (0)