Skip to content

Commit

Permalink
organize packets and classes (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
pektezol authored Sep 21, 2023
1 parent 171e350 commit 44eefef
Show file tree
Hide file tree
Showing 16 changed files with 593 additions and 402 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@

Work-In-Progress demo parser for Portal 2 written in Golang.

Usage:
## Couldn't Do This Without Them

- [@UncraftedName](https://github.com/UncraftedName): For [UntitledParser](https://github.com/UncraftedName/UntitledParser)
- [@NeKzor](https://github.com/NeKzor): For [nekz.me/dem](https://nekz.me/dem)

## Usage

```bash
$ ./parser demo.dem
```

Currently supports:
## Currently Supports

- File or folder input using the CLI.
- Basic parsing of demo headers each message type.
- Basic parsing of packet classes.
- Custom injected SAR data parsing.

TODO:
## TODO

- StringTableEntry parsing. ([#8][i8])
- In-depth packet class parsing for each class. ([#7][i7])

- StringTableEntry parsing.
- In-depth packet class parsing for each class.
[i8]: https://github.com/pektezol/DemoParser/issues/8
[i7]: https://github.com/pektezol/DemoParser/issues/7
63 changes: 0 additions & 63 deletions pkg/classes/cmdInfo.go

This file was deleted.

19 changes: 19 additions & 0 deletions pkg/classes/consoleCmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package classes

import (
"strings"

"github.com/pektezol/bitreader"
"github.com/pektezol/demoparser/pkg/writer"
)

type ConsoleCmd struct {
Size int32
Data string
}

func (consoleCmd *ConsoleCmd) ParseConsoleCmd(reader *bitreader.Reader) {
consoleCmd.Size = reader.TryReadSInt32()
consoleCmd.Data = reader.TryReadStringLength(uint64(consoleCmd.Size))
writer.AppendLine("\t%s", strings.TrimSpace(consoleCmd.Data))
}
30 changes: 30 additions & 0 deletions pkg/classes/customData.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package classes

import (
"github.com/pektezol/bitreader"
"github.com/pektezol/demoparser/pkg/writer"
)

type CustomData struct {
Type int32
Size int32
Data string
}

func (customData *CustomData) ParseCustomData(reader *bitreader.Reader, tickNumber int32, packetType uint8) {
customData.Type = reader.TryReadSInt32()
customData.Size = reader.TryReadSInt32()
if customData.Type != 0 || customData.Size == 8 {
// Not SAR data
writer.AppendLine("[%d] %s (%d):", tickNumber, "CUSTOMDATA", packetType)
customData.Data = string(reader.TryReadBytesToSlice(uint64(customData.Size)))
writer.AppendLine("\t%s", customData.Data)
return
}
// SAR data
writer.AppendLine("[%d] %s (%d):", tickNumber, "SARDATA", packetType)
sarData := SarData{}
data := reader.TryReadBytesToSlice(uint64(customData.Size))
sarReader := bitreader.NewReaderFromBytes(data, true)
sarData.ParseSarData(sarReader)
}
151 changes: 101 additions & 50 deletions pkg/classes/sendTable.go → pkg/classes/dataTables.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ import (
"github.com/pektezol/demoparser/pkg/writer"
)

type DataTables struct {
Size int32
SendTable []SendTable
ServerClassInfo []ServerClassInfo
}

type SendTable struct {
NeedsDecoder bool
NetTableName string
NumOfProps int16
Props []prop
}

type ServerClassInfo struct {
ClassId uint16
ClassName string
DataTableName string
}

type prop struct {
SendPropType sendPropType
SendPropName string
Expand All @@ -26,6 +38,95 @@ type prop struct {
NumElements int32
}

func (dataTables *DataTables) ParseDataTables(reader *bitreader.Reader) {
dataTables.Size = int32(reader.TryReadSInt32())
dataTableReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(dataTables.Size)), true)
count := 0
for dataTableReader.TryReadBool() {
count++
dataTables.SendTable = append(dataTables.SendTable, ParseSendTable(dataTableReader))
}
writer.AppendLine("\t%d Send Tables:", count)
writer.AppendOutputFromTemp()
numOfClasses := dataTableReader.TryReadBits(16)
for count = 0; count < int(numOfClasses); count++ {
dataTables.ServerClassInfo = append(dataTables.ServerClassInfo, ParseServerClassInfo(dataTableReader, count, int(numOfClasses)))
}
writer.AppendLine("\t%d Classes:", count)
writer.AppendOutputFromTemp()
}

func ParseSendTable(reader *bitreader.Reader) SendTable {
sendTable := SendTable{
NeedsDecoder: reader.TryReadBool(),
NetTableName: reader.TryReadString(),
NumOfProps: int16(reader.TryReadBits(10)),
}
if sendTable.NumOfProps < 0 {
return sendTable
}
writer.TempAppendLine("\t\t%s (%d Props):", sendTable.NetTableName, sendTable.NumOfProps)
for count := 0; count < int(sendTable.NumOfProps); count++ {
propType := int8(reader.TryReadBits(5))
if propType >= int8(7) {
return sendTable
}
prop := prop{
SendPropType: sendPropType(propType),
SendPropName: reader.TryReadString(),
SendPropFlags: uint32(reader.TryReadBits(19)),
Priority: reader.TryReadUInt8(),
}
writer.TempAppend("\t\t\t%s\t", prop.SendPropType)
if propType == int8(ESendPropTypeDataTable) || checkBit(prop.SendPropFlags, 6) {
prop.ExcludeDtName = reader.TryReadString()
writer.TempAppend(":\t%s\t", prop.ExcludeDtName)
} else {
switch propType {
case int8(ESendPropTypeString), int8(ESendPropTypeInt), int8(ESendPropTypeFloat), int8(ESendPropTypeVector3), int8(ESendPropTypeVector2):
prop.LowValue = reader.TryReadFloat32()
prop.HighValue = reader.TryReadFloat32()
prop.NumBits = int32(reader.TryReadBits(7))
writer.TempAppend("Low: %f\tHigh: %f\t%d bits\t", prop.LowValue, prop.HighValue, prop.NumBits)
case int8(ESendPropTypeArray):
prop.NumElements = int32(reader.TryReadBits(10))
writer.TempAppend("Elements: %d\t", prop.NumElements)
default:
writer.TempAppend("Unknown Prop Type: %v\t", propType)
return sendTable
}
}
writer.TempAppend("Flags: %v\tPriority: %d\n", prop.GetFlags(), prop.Priority)
sendTable.Props = append(sendTable.Props, prop)
}
return sendTable
}

func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo {
serverClassInfo := ServerClassInfo{
ClassId: reader.TryReadUInt16(),
ClassName: reader.TryReadString(),
DataTableName: reader.TryReadString(),
}
writer.TempAppendLine("\t\t\t[%d] %s (%s)", serverClassInfo.ClassId, serverClassInfo.ClassName, serverClassInfo.DataTableName)
return serverClassInfo
}

// func serverClassBits(numOfClasses int) int {
// return highestBitIndex(uint(numOfClasses)) + 1
// }

// func highestBitIndex(i uint) int {
// var j int
// for j = 31; j >= 0 && (i&(1<<j)) == 0; j-- {
// }
// return j
// }

func checkBit(val uint32, bit int) bool {
return (val & (uint32(1) << bit)) != 0
}

type sendPropType int

const (
Expand Down Expand Up @@ -142,53 +243,3 @@ func (sendPropType sendPropType) String() string {
return fmt.Sprintf("%d", int(sendPropType))
}
}

func ParseSendTable(reader *bitreader.Reader) SendTable {
sendTable := SendTable{
NeedsDecoder: reader.TryReadBool(),
NetTableName: reader.TryReadString(),
NumOfProps: int16(reader.TryReadBits(10)),
}
if sendTable.NumOfProps < 0 {
return sendTable
}
writer.TempAppendLine("\t\t%s (%d Props):", sendTable.NetTableName, sendTable.NumOfProps)
for count := 0; count < int(sendTable.NumOfProps); count++ {
propType := int8(reader.TryReadBits(5))
if propType >= int8(7) {
return sendTable
}
prop := prop{
SendPropType: sendPropType(propType),
SendPropName: reader.TryReadString(),
SendPropFlags: uint32(reader.TryReadBits(19)),
Priority: reader.TryReadUInt8(),
}
writer.TempAppend("\t\t\t%s\t", prop.SendPropType)
if propType == int8(ESendPropTypeDataTable) || checkBit(prop.SendPropFlags, 6) {
prop.ExcludeDtName = reader.TryReadString()
writer.TempAppend(":\t%s\t", prop.ExcludeDtName)
} else {
switch propType {
case int8(ESendPropTypeString), int8(ESendPropTypeInt), int8(ESendPropTypeFloat), int8(ESendPropTypeVector3), int8(ESendPropTypeVector2):
prop.LowValue = reader.TryReadFloat32()
prop.HighValue = reader.TryReadFloat32()
prop.NumBits = int32(reader.TryReadBits(7))
writer.TempAppend("Low: %f\tHigh: %f\t%d bits\t", prop.LowValue, prop.HighValue, prop.NumBits)
case int8(ESendPropTypeArray):
prop.NumElements = int32(reader.TryReadBits(10))
writer.TempAppend("Elements: %d\t", prop.NumElements)
default:
writer.TempAppend("Unknown Prop Type: %v\t", propType)
return sendTable
}
}
writer.TempAppend("Flags: %v\tPriority: %d\n", prop.GetFlags(), prop.Priority)
sendTable.Props = append(sendTable.Props, prop)
}
return sendTable
}

func checkBit(val uint32, bit int) bool {
return (val & (uint32(1) << bit)) != 0
}
Loading

0 comments on commit 44eefef

Please sign in to comment.