diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-09-30 17:40:19 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-30 17:40:19 +0300 |
| commit | 5053478537eac61db5fa7926cdc44ec3b5f09053 (patch) | |
| tree | ae28630f18d709f72369848a210abc3251c86cdf /pkg | |
| parent | update messages todo (#16) (diff) | |
| download | sdp.go-5053478537eac61db5fa7926cdc44ec3b5f09053.tar.gz sdp.go-5053478537eac61db5fa7926cdc44ec3b5f09053.tar.bz2 sdp.go-5053478537eac61db5fa7926cdc44ec3b5f09053.zip | |
finish stringtablesentry parsing besides instancebaseline (#18)
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/classes/dataTables.go | 24 | ||||
| -rw-r--r-- | pkg/classes/stringTables.go | 204 |
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 | ||
| 23 | type ServerClassInfo struct { | 23 | type ServerClassInfo struct { |
| 24 | ClassId uint16 | 24 | DataTableID uint16 |
| 25 | ClassName string | 25 | ClassName string |
| 26 | DataTableName string | 26 | DataTableName string |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | type prop struct { | 29 | type 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 | ||
| 105 | func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo { | 105 | func 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 | ||
| 130 | type sendPropType int | 130 | type SendPropType int |
| 131 | 131 | ||
| 132 | const ( | 132 | const ( |
| 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 | ||
| 164 | func (prop prop) GetFlags() []string { | 164 | func (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 | ||
| 226 | func (sendPropType sendPropType) String() string { | 226 | func (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 @@ | |||
| 1 | package classes | 1 | package classes |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 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 | ||
| 19 | type StringTableEntry struct { | ||
| 20 | Name string | ||
| 21 | EntryData StringTableEntryData | ||
| 22 | } | ||
| 23 | |||
| 24 | type StringTableEntryData struct { | ||
| 25 | // TODO: Parse StringTableEntry | ||
| 26 | } | ||
| 27 | |||
| 28 | type StringTableClass struct { | 22 | type StringTableClass struct { |
| 29 | Name string | 23 | Name string |
| 30 | Data string | 24 | Data string |
| 31 | } | 25 | } |
| 26 | type StringTableEntry struct { | ||
| 27 | Name string | ||
| 28 | EntryData any | ||
| 29 | } | ||
| 32 | 30 | ||
| 33 | func (stringTables *StringTables) ParseStringTables(reader *bitreader.Reader) { | 31 | func (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 | ||
| 79 | func (stringTableEntry *StringTableEntry) Parse(reader *bitreader.Reader) { | 77 | func (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 | |||
| 86 | func (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 | ||
| 92 | func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader) { | 120 | func (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 | |||
| 167 | func (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 | |||
| 175 | func (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 | |||
| 183 | func (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 | |||
| 191 | func (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 | |||
| 208 | func (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 | |||
| 231 | func (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 | |||
| 240 | const ( | ||
| 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 | ) | ||