aboutsummaryrefslogtreecommitdiff
path: root/pkg/classes
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-09-30 17:40:19 +0300
committerGitHub <noreply@github.com>2023-09-30 17:40:19 +0300
commit5053478537eac61db5fa7926cdc44ec3b5f09053 (patch)
treeae28630f18d709f72369848a210abc3251c86cdf /pkg/classes
parentupdate messages todo (#16) (diff)
downloadsdp.go-5053478537eac61db5fa7926cdc44ec3b5f09053.tar.gz
sdp.go-5053478537eac61db5fa7926cdc44ec3b5f09053.tar.bz2
sdp.go-5053478537eac61db5fa7926cdc44ec3b5f09053.zip
finish stringtablesentry parsing besides instancebaseline (#18)
Diffstat (limited to '')
-rw-r--r--pkg/classes/dataTables.go24
-rw-r--r--pkg/classes/stringTables.go204
2 files changed, 195 insertions, 33 deletions
diff --git a/pkg/classes/dataTables.go b/pkg/classes/dataTables.go
index 27ab9e4..7e710bf 100644
--- a/pkg/classes/dataTables.go
+++ b/pkg/classes/dataTables.go
@@ -17,17 +17,17 @@ type SendTable struct {
17 NeedsDecoder bool 17 NeedsDecoder bool
18 NetTableName string 18 NetTableName string
19 NumOfProps int16 19 NumOfProps int16
20 Props []prop 20 Props []SendTableProp
21} 21}
22 22
23type ServerClassInfo struct { 23type ServerClassInfo struct {
24 ClassId uint16 24 DataTableID uint16
25 ClassName string 25 ClassName string
26 DataTableName string 26 DataTableName string
27} 27}
28 28
29type prop struct { 29type SendTableProp struct {
30 SendPropType sendPropType 30 SendPropType SendPropType
31 SendPropName string 31 SendPropName string
32 SendPropFlags uint32 32 SendPropFlags uint32
33 Priority uint8 33 Priority uint8
@@ -71,8 +71,8 @@ func ParseSendTable(reader *bitreader.Reader) SendTable {
71 if propType >= int8(7) { 71 if propType >= int8(7) {
72 return sendTable 72 return sendTable
73 } 73 }
74 prop := prop{ 74 prop := SendTableProp{
75 SendPropType: sendPropType(propType), 75 SendPropType: SendPropType(propType),
76 SendPropName: reader.TryReadString(), 76 SendPropName: reader.TryReadString(),
77 SendPropFlags: uint32(reader.TryReadBits(19)), 77 SendPropFlags: uint32(reader.TryReadBits(19)),
78 Priority: reader.TryReadUInt8(), 78 Priority: reader.TryReadUInt8(),
@@ -104,11 +104,11 @@ func ParseSendTable(reader *bitreader.Reader) SendTable {
104 104
105func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo { 105func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo {
106 serverClassInfo := ServerClassInfo{ 106 serverClassInfo := ServerClassInfo{
107 ClassId: reader.TryReadUInt16(), 107 DataTableID: reader.TryReadUInt16(),
108 ClassName: reader.TryReadString(), 108 ClassName: reader.TryReadString(),
109 DataTableName: reader.TryReadString(), 109 DataTableName: reader.TryReadString(),
110 } 110 }
111 writer.TempAppendLine("\t\t\t[%d] %s (%s)", serverClassInfo.ClassId, serverClassInfo.ClassName, serverClassInfo.DataTableName) 111 writer.TempAppendLine("\t\t\t[%d] %s (%s)", serverClassInfo.DataTableID, serverClassInfo.ClassName, serverClassInfo.DataTableName)
112 return serverClassInfo 112 return serverClassInfo
113} 113}
114 114
@@ -127,10 +127,10 @@ func checkBit(val uint32, bit int) bool {
127 return (val & (uint32(1) << bit)) != 0 127 return (val & (uint32(1) << bit)) != 0
128} 128}
129 129
130type sendPropType int 130type SendPropType int
131 131
132const ( 132const (
133 ESendPropTypeInt sendPropType = iota 133 ESendPropTypeInt SendPropType = iota
134 ESendPropTypeFloat 134 ESendPropTypeFloat
135 ESendPropTypeVector3 135 ESendPropTypeVector3
136 ESendPropTypeVector2 136 ESendPropTypeVector2
@@ -161,7 +161,7 @@ const (
161 ESendPropFlagChangesOften string = "ChangesOften" 161 ESendPropFlagChangesOften string = "ChangesOften"
162) 162)
163 163
164func (prop prop) GetFlags() []string { 164func (prop SendTableProp) GetFlags() []string {
165 flags := []string{} 165 flags := []string{}
166 if checkBit(prop.SendPropFlags, 0) { 166 if checkBit(prop.SendPropFlags, 0) {
167 flags = append(flags, ESendPropFlagUnsigned) 167 flags = append(flags, ESendPropFlagUnsigned)
@@ -223,7 +223,7 @@ func (prop prop) GetFlags() []string {
223 return flags 223 return flags
224} 224}
225 225
226func (sendPropType sendPropType) String() string { 226func (sendPropType SendPropType) String() string {
227 switch sendPropType { 227 switch sendPropType {
228 case ESendPropTypeInt: 228 case ESendPropTypeInt:
229 return "Int" 229 return "Int"
diff --git a/pkg/classes/stringTables.go b/pkg/classes/stringTables.go
index 01939b2..0ac3a2e 100644
--- a/pkg/classes/stringTables.go
+++ b/pkg/classes/stringTables.go
@@ -1,6 +1,9 @@
1package classes 1package classes
2 2
3import ( 3import (
4 "fmt"
5 "strings"
6
4 "github.com/pektezol/bitreader" 7 "github.com/pektezol/bitreader"
5 "github.com/pektezol/demoparser/pkg/writer" 8 "github.com/pektezol/demoparser/pkg/writer"
6) 9)
@@ -16,19 +19,14 @@ type StringTable struct {
16 Classes []StringTableClass 19 Classes []StringTableClass
17} 20}
18 21
19type StringTableEntry struct {
20 Name string
21 EntryData StringTableEntryData
22}
23
24type StringTableEntryData struct {
25 // TODO: Parse StringTableEntry
26}
27
28type StringTableClass struct { 22type StringTableClass struct {
29 Name string 23 Name string
30 Data string 24 Data string
31} 25}
26type StringTableEntry struct {
27 Name string
28 EntryData any
29}
32 30
33func (stringTables *StringTables) ParseStringTables(reader *bitreader.Reader) { 31func (stringTables *StringTables) ParseStringTables(reader *bitreader.Reader) {
34 stringTables.Size = reader.TryReadSInt32() 32 stringTables.Size = reader.TryReadSInt32()
@@ -51,7 +49,7 @@ func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) {
51 49
52 for i := 0; i < int(entryCount); i++ { 50 for i := 0; i < int(entryCount); i++ {
53 var entry StringTableEntry 51 var entry StringTableEntry
54 entry.Parse(reader) 52 entry.Parse(stringTable.Name, reader)
55 stringTable.TableEntries[i] = entry 53 stringTable.TableEntries[i] = entry
56 } 54 }
57 if entryCount != 0 { 55 if entryCount != 0 {
@@ -76,25 +74,189 @@ func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) {
76 } 74 }
77} 75}
78 76
79func (stringTableEntry *StringTableEntry) Parse(reader *bitreader.Reader) { 77func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader) {
78 stringTableClass.Name = reader.TryReadString()
79 writer.TempAppendLine("\t\t\tName: %s", stringTableClass.Name)
80 if reader.TryReadBool() {
81 stringTableClass.Data = reader.TryReadStringLength(uint64(reader.TryReadUInt16()))
82 writer.TempAppendLine("\t\t\tData: %s", stringTableClass.Data)
83 }
84}
85
86func (stringTableEntry *StringTableEntry) Parse(tableName string, reader *bitreader.Reader) {
80 stringTableEntry.Name = reader.TryReadString() 87 stringTableEntry.Name = reader.TryReadString()
88 writer.TempAppendLine("\t\t\tName: %s", stringTableEntry.Name)
81 if reader.TryReadBool() { 89 if reader.TryReadBool() {
82 byteLen, err := reader.ReadBits(16) 90 byteLen, err := reader.ReadBits(16)
83 if err != nil { 91 if err != nil {
84 return 92 return
85 } 93 }
86 dataBsr := reader.TryReadBytesToSlice(byteLen) 94 stringTableEntryReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(byteLen), true)
87 _ = bitreader.NewReaderFromBytes(dataBsr, true) // TODO: Parse StringTableEntry 95 switch tableName {
88 // stringTableEntry.EntryData.ParseStream(entryReader) 96 case StringTableUserInfo:
97 stringTableEntry.ParseUserInfo(stringTableEntryReader)
98 case StringTableServerQueryInfo:
99 stringTableEntry.ParseServerQueryInfo(stringTableEntryReader)
100 case StringTableGameRulesCreation:
101 stringTableEntry.ParseGamesRulesCreation(stringTableEntryReader)
102 case StringTableInfoPanel:
103 stringTableEntry.ParseInfoPanel(stringTableEntryReader)
104 case StringTableLightStyles:
105 stringTableEntry.ParseLightStyles(stringTableEntryReader)
106 case StringTableModelPreCache:
107 stringTableEntry.ParsePrecacheData(stringTableEntryReader)
108 case StringTableGenericPreCache:
109 stringTableEntry.ParsePrecacheData(stringTableEntryReader)
110 case StringTableSoundPreCache:
111 stringTableEntry.ParsePrecacheData(stringTableEntryReader)
112 case StringTableDecalPreCache:
113 stringTableEntry.ParsePrecacheData(stringTableEntryReader)
114 default:
115 stringTableEntry.ParseUnknown(stringTableEntryReader)
116 }
89 } 117 }
90} 118}
91 119
92func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader) { 120func (stringTableEntry *StringTableEntry) ParseUserInfo(reader *bitreader.Reader) {
93 stringTableClass.Name = reader.TryReadString() 121 const SignedGuidLen int32 = 32
94 writer.TempAppendLine("\t\t\tName: %s", stringTableClass.Name) 122 const MaxPlayerNameLength int32 = 32
95 if reader.TryReadBool() { 123 userInfo := struct {
96 dataLen := reader.TryReadBits(16) 124 SteamID uint64
97 stringTableClass.Data = reader.TryReadStringLength(dataLen) 125 Name string
98 writer.TempAppendLine("\t\t\tData: %s", stringTableClass.Data) 126 UserID int32
127 GUID string
128 FriendsID uint32
129 FriendsName string
130 FakePlayer bool
131 IsHltv bool
132 CustomFiles []uint32
133 FilesDownloaded uint8
134 }{
135 SteamID: reader.TryReadUInt64(),
136 Name: reader.TryReadStringLength(uint64(MaxPlayerNameLength)),
137 UserID: reader.TryReadSInt32(),
138 GUID: reader.TryReadStringLength(uint64(SignedGuidLen) + 1),
139 }
140 reader.SkipBytes(3)
141 userInfo.FriendsID = reader.TryReadUInt32()
142 userInfo.FriendsName = reader.TryReadStringLength(uint64(MaxPlayerNameLength))
143 userInfo.FakePlayer = reader.TryReadUInt8() != 0
144 userInfo.IsHltv = reader.TryReadUInt8() != 0
145 reader.SkipBytes(2)
146 userInfo.CustomFiles = []uint32{reader.TryReadUInt32(), reader.TryReadUInt32(), reader.TryReadUInt32(), reader.TryReadUInt32()}
147 userInfo.FilesDownloaded = reader.TryReadUInt8()
148 reader.SkipBytes(3)
149 stringTableEntry.EntryData = userInfo
150 writer.TempAppendLine("\t\t\t\tSteam Account ID: %d", uint32((userInfo.SteamID&0xFFFFFFFF00000000)|userInfo.SteamID))
151 writer.TempAppendLine("\t\t\t\tSteam Account Instance: %d", uint32(userInfo.SteamID>>32)&0x000FFFFF)
152 writer.TempAppendLine("\t\t\t\tSteam Account Type: %d", uint32(userInfo.SteamID>>52)&0xF)
153 writer.TempAppendLine("\t\t\t\tSteam Account Universe: %d", uint32(userInfo.SteamID>>56)&0xFF)
154 writer.TempAppendLine("\t\t\t\tName: %s", userInfo.Name)
155 writer.TempAppendLine("\t\t\t\tUser ID: %d", userInfo.UserID)
156 writer.TempAppendLine("\t\t\t\tGUID: %s", userInfo.GUID)
157 writer.TempAppendLine("\t\t\t\tFriends ID: %d", userInfo.FriendsID)
158 writer.TempAppendLine("\t\t\t\tFriends Name: %s", userInfo.FriendsName)
159 writer.TempAppendLine("\t\t\t\tFake Player: %t", userInfo.FakePlayer)
160 writer.TempAppendLine("\t\t\t\tIs Htlv: %t", userInfo.IsHltv)
161 if userInfo.CustomFiles != nil {
162 writer.TempAppendLine("\t\t\t\tCustom File CRCs: [logo: 0x%d, sounds: 0x%d, models: 0x%d, txt: 0x%d]", userInfo.CustomFiles[0], userInfo.CustomFiles[1], userInfo.CustomFiles[2], userInfo.CustomFiles[3])
99 } 163 }
164 writer.TempAppendLine("\t\t\t\tFiles Downloaded: %d", userInfo.FilesDownloaded)
100} 165}
166
167func (stringTableEntry *StringTableEntry) ParseServerQueryInfo(reader *bitreader.Reader) {
168 serverQueryInfo := struct{ Port uint32 }{
169 Port: reader.TryReadUInt32(),
170 }
171 stringTableEntry.EntryData = serverQueryInfo
172 writer.TempAppendLine("\t\t\t\tPort: %d", serverQueryInfo.Port)
173}
174
175func (stringTableEntry *StringTableEntry) ParseGamesRulesCreation(reader *bitreader.Reader) {
176 gamesRulesCreation := struct{ Message string }{
177 Message: reader.TryReadString(),
178 }
179 stringTableEntry.EntryData = gamesRulesCreation
180 writer.TempAppendLine("\t\t\t\tMessage: %s", gamesRulesCreation.Message)
181}
182
183func (stringTableEntry *StringTableEntry) ParseInfoPanel(reader *bitreader.Reader) {
184 infoPanel := struct{ Message string }{
185 Message: reader.TryReadString(),
186 }
187 stringTableEntry.EntryData = infoPanel
188 writer.TempAppendLine("\t\t\t\tMessage: %s", infoPanel.Message)
189}
190
191func (stringTableEntry *StringTableEntry) ParseLightStyles(reader *bitreader.Reader) {
192 lightStyles := struct{ Values []byte }{}
193 str := reader.TryReadString()
194 if len(str) != 0 {
195 for _, c := range str {
196 value := byte((c - 'a') * 22)
197 lightStyles.Values = append(lightStyles.Values, value)
198 }
199 }
200 stringTableEntry.EntryData = lightStyles
201 if lightStyles.Values == nil {
202 writer.TempAppendLine("\t\t\t\t0 Frames (256)")
203 } else {
204 writer.TempAppendLine("\t\t\t\t%d frames: %v", len(lightStyles.Values), lightStyles.Values)
205 }
206}
207
208func (stringTableEntry *StringTableEntry) ParsePrecacheData(reader *bitreader.Reader) {
209 type PrecacheFlag uint16
210 const (
211 None PrecacheFlag = 0
212 FatalIfMissing PrecacheFlag = 1
213 Preload PrecacheFlag = 1 << 1
214 )
215 precacheData := struct{ Flags uint8 }{
216 Flags: uint8(reader.TryReadBits(2)),
217 }
218 getFlags := func(flags PrecacheFlag) []string {
219 var flagStrings []string
220 if flags&FatalIfMissing != 0 {
221 flagStrings = append(flagStrings, "FatalIfMissing")
222 }
223 if flags&Preload != 0 {
224 flagStrings = append(flagStrings, "Preload")
225 }
226 return flagStrings
227 }
228 writer.TempAppendLine("\t\t\t\tFlags: %v", getFlags(PrecacheFlag(precacheData.Flags)))
229}
230
231func (stringTableEntry *StringTableEntry) ParseUnknown(reader *bitreader.Reader) {
232 unknown := reader.TryReadBitsToSlice(reader.TryReadRemainingBits())
233 binaryString := ""
234 for _, byteValue := range unknown {
235 binaryString += fmt.Sprintf("%08b ", byteValue)
236 }
237 writer.TempAppendLine("\t\t\t\tUnknown: (%s)", strings.TrimSpace(binaryString))
238}
239
240const (
241 StringTableDownloadables string = "downloadables"
242 StringTableModelPreCache string = "modelprecache"
243 StringTableGenericPreCache string = "genericprecache"
244 StringTableSoundPreCache string = "soundprecache"
245 StringTableDecalPreCache string = "decalprecache"
246 StringTableInstanceBaseLine string = "instancebaseline"
247 StringTableLightStyles string = "lightstyles"
248 StringTableUserInfo string = "userinfo"
249 StringTableServerQueryInfo string = "server_query_info"
250 StringTableParticleEffectNames string = "ParticleEffectNames"
251 StringTableEffectDispatch string = "EffectDispatch"
252 StringTableVguiScreen string = "VguiScreen"
253 StringTableMaterials string = "Materials"
254 StringTableInfoPanel string = "InfoPanel"
255 StringTableScenes string = "Scenes"
256 StringTableMeleeWeapons string = "MeleeWeapons"
257 StringTableGameRulesCreation string = "GameRulesCreation"
258 StringTableBlackMarket string = "BlackMarketTable"
259 // custom?
260 StringTableDynamicModels string = "DynamicModels"
261 StringTableServerMapCycle string = "ServerMapCycle"
262)