aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--cmd/parser.go79
-rw-r--r--pkg/classes/consoleCmd.go10
-rw-r--r--pkg/classes/customData.go19
-rw-r--r--pkg/classes/dataTables.go74
-rw-r--r--pkg/classes/packet.go50
-rw-r--r--pkg/classes/sarData.go196
-rw-r--r--pkg/classes/signOn.go36
-rw-r--r--pkg/classes/stop.go8
-rw-r--r--pkg/classes/stringTables.go128
-rw-r--r--pkg/classes/userCmd.go58
-rw-r--r--pkg/messages/messages.go76
-rw-r--r--pkg/messages/types/netDisconnect.go8
-rw-r--r--pkg/messages/types/netFile.go16
-rw-r--r--pkg/messages/types/netNop.go6
-rw-r--r--pkg/messages/types/netSetConVar.go16
-rw-r--r--pkg/messages/types/netSignOnState.go28
-rw-r--r--pkg/messages/types/netSplitScreenUser.go8
-rw-r--r--pkg/messages/types/netStringCmd.go8
-rw-r--r--pkg/messages/types/netTick.go16
-rw-r--r--pkg/messages/types/svcBspDecal.go28
-rw-r--r--pkg/messages/types/svcClassInfo.go24
-rw-r--r--pkg/messages/types/svcCmdKeyValues.go10
-rw-r--r--pkg/messages/types/svcCreateStringTable.go36
-rw-r--r--pkg/messages/types/svcCrosshairAngle.go18
-rw-r--r--pkg/messages/types/svcEntityMessage.go18
-rw-r--r--pkg/messages/types/svcFixAngle.go22
-rw-r--r--pkg/messages/types/svcGameEvent.go40
-rw-r--r--pkg/messages/types/svcGameEventList.go89
-rw-r--r--pkg/messages/types/svcGetCvarValue.go12
-rw-r--r--pkg/messages/types/svcMenu.go14
-rw-r--r--pkg/messages/types/svcPacketEntities.go34
-rw-r--r--pkg/messages/types/svcPaintmapData.go10
-rw-r--r--pkg/messages/types/svcPrefetch.go8
-rw-r--r--pkg/messages/types/svcPrint.go8
-rw-r--r--pkg/messages/types/svcSendTable.go16
-rw-r--r--pkg/messages/types/svcServerInfo.go68
-rw-r--r--pkg/messages/types/svcSetPause.go8
-rw-r--r--pkg/messages/types/svcSetView.go8
-rw-r--r--pkg/messages/types/svcSounds.go18
-rw-r--r--pkg/messages/types/svcSplitScreen.go14
-rw-r--r--pkg/messages/types/svcTempEntities.go14
-rw-r--r--pkg/messages/types/svcUpdateStringTable.go16
-rw-r--r--pkg/messages/types/svcUserMessage.go495
-rw-r--r--pkg/messages/types/svcVoiceData.go18
-rw-r--r--pkg/messages/types/svcVoiceInit.go16
-rw-r--r--pkg/packets/headers.go42
-rw-r--r--pkg/packets/packets.go89
-rw-r--r--pkg/types/gameevent.go80
-rw-r--r--pkg/types/types.go71
-rw-r--r--pkg/writer/writer.go50
51 files changed, 1149 insertions, 1091 deletions
diff --git a/README.md b/README.md
index 84d0f08..3872967 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
1# sdp.go [![Go Report Card](https://goreportcard.com/badge/github.com/pektezol/sdp.go)](https://goreportcard.com/report/github.com/pektezol/sdp.go) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/pektezol/sdp.go/blob/main/LICENSE) 1# sdp.go [![Go Report Card](https://goreportcard.com/badge/github.com/pektezol/sdp.go)](https://goreportcard.com/report/github.com/pektezol/sdp.go) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/pektezol/sdp.go/blob/main/LICENSE)
2 2
3Source Demo Parser for Portal 2 written in Golang. 3Source Demo Parser written in Golang.
4Currently supports Portal 2.
4 5
5## Couldn't Do This Without Them 6## Couldn't Do This Without Them
6 7
@@ -18,9 +19,12 @@ $ ./parser demos/
18## Currently Supports 19## Currently Supports
19 20
20- File or folder input using the CLI. 21- File or folder input using the CLI.
22- API calls over library import.
23- Either pretty text or JSON output.
21- Parsing of demo headers and each (most) message type. 24- Parsing of demo headers and each (most) message type.
22- Parsing of packet classes. 25- Parsing of packet classes.
23- Custom injected SAR data parsing. 26- Custom injected SAR data parsing.
27- Multi-threaded parsing over multiple demos.
24 28
25## TODO 29## TODO
26 30
diff --git a/cmd/parser.go b/cmd/parser.go
index f21d91f..06ebbfe 100644
--- a/cmd/parser.go
+++ b/cmd/parser.go
@@ -4,21 +4,17 @@ import (
4 "errors" 4 "errors"
5 "fmt" 5 "fmt"
6 "os" 6 "os"
7 "strings" 7 "path/filepath"
8 "sync"
8 9
9 "github.com/pektezol/bitreader" 10 "github.com/pektezol/bitreader"
10 "github.com/pektezol/sdp.go/pkg/packets" 11 "github.com/pektezol/sdp.go/pkg/packets"
12 "github.com/pektezol/sdp.go/pkg/types"
11 "github.com/pektezol/sdp.go/pkg/writer" 13 "github.com/pektezol/sdp.go/pkg/writer"
12) 14)
13 15
14type Demo struct {
15 Headers packets.Headers `json:"headers"`
16 Messages []packets.Message `json:"messages"`
17}
18
19type Parser struct { 16type Parser struct {
20 DemoPath string 17 DemoPath string
21 writer strings.Builder
22} 18}
23 19
24func NewParser(demoPath string) *Parser { 20func NewParser(demoPath string) *Parser {
@@ -35,48 +31,61 @@ func main() {
35 os.Exit(1) 31 os.Exit(1)
36 } 32 }
37 parser := NewParser(os.Args[1]) 33 parser := NewParser(os.Args[1])
38 _, err := parser.ParseDemos() 34 demos, err := parser.ParseDemos()
39 if err != nil { 35 if err != nil {
40 fmt.Println(err.Error()) 36 fmt.Println(err.Error())
41 os.Exit(1) 37 os.Exit(1)
42 } 38 }
43 fmt.Println(parser.GetOutput()) 39 for _, d := range demos {
44} 40 fmt.Println(d.Writer.GetOutputString())
45 41 // You can also marshal structs into JSON and print them:
46func (p *Parser) GetOutput() string { 42 // out, _ := json.Marshal(d)
47 return p.writer.String() 43 // fmt.Println(string(out))
44 }
48} 45}
49 46
50func (p *Parser) ParseDemos() ([]Demo, error) { 47func (p *Parser) ParseDemos() ([]*types.Demo, error) {
51 writer.AppendLine("Generated By: github.com/pektezol/sdp.go")
52 files, err := os.ReadDir(p.DemoPath) 48 files, err := os.ReadDir(p.DemoPath)
53 if err != nil { 49 if err != nil {
54 // not a directory 50 // not a directory
55 file, err := os.Open(p.DemoPath) 51 file, err := os.Open(p.DemoPath)
56 if err != nil { 52 if err != nil {
57 return []Demo{}, err 53 return []*types.Demo{}, err
58 } 54 }
59 defer file.Close() 55 defer file.Close()
56 demo := &types.Demo{}
57 demo.Writer = writer.NewWriter()
58 demo.Writer.AppendLine("Generated By: github.com/pektezol/sdp.go")
60 reader := bitreader.NewReader(file, littleEndian) 59 reader := bitreader.NewReader(file, littleEndian)
61 demo := demoParserHandler(reader, file.Name()) 60 p.demoParserHandler(reader, file.Name(), demo, nil)
62 p.writer = writer.GetWriter() 61 return []*types.Demo{demo}, nil
63 return []Demo{demo}, nil
64 } else { 62 } else {
65 demos := []Demo{}
66 // directory 63 // directory
64 demoCount := 0
67 for _, fileinfo := range files { 65 for _, fileinfo := range files {
68 if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { 66 if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" {
69 file, err := os.Open(p.DemoPath + fileinfo.Name()) 67 demoCount++
68 }
69 }
70 wg := new(sync.WaitGroup)
71 wg.Add(demoCount)
72 demos := make([]*types.Demo, demoCount)
73 for i := 0; i < len(demos); i++ {
74 demos[i] = &types.Demo{}
75 demos[i].Writer = writer.NewWriter()
76 demos[i].Writer.AppendLine("Generated By: github.com/pektezol/sdp.go")
77 }
78 for i, fileinfo := range files {
79 if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" {
80 file, err := os.Open(filepath.Join(p.DemoPath, fileinfo.Name()))
70 if err != nil { 81 if err != nil {
71 return []Demo{}, err 82 return []*types.Demo{}, err
72 } 83 }
73 defer file.Close() 84 defer file.Close()
74 reader := bitreader.NewReader(file, littleEndian) 85 go p.demoParserHandler(bitreader.NewReader(file, littleEndian), file.Name(), demos[i], wg)
75 demo := demoParserHandler(reader, file.Name())
76 demos = append(demos, demo)
77 } 86 }
78 } 87 }
79 p.writer = writer.GetWriter() 88 wg.Wait()
80 if len(demos) == 0 { 89 if len(demos) == 0 {
81 return demos, errors.New("no demo found in given directory") 90 return demos, errors.New("no demo found in given directory")
82 } 91 }
@@ -84,23 +93,27 @@ func (p *Parser) ParseDemos() ([]Demo, error) {
84 } 93 }
85} 94}
86 95
87func demoParserHandler(reader *bitreader.Reader, filename string) Demo { 96func (p *Parser) demoParserHandler(reader *bitreader.Reader, filename string, demo *types.Demo, wg *sync.WaitGroup) {
88 demo := Demo{} 97 demo.Writer.AppendLine("\nFile Name: %s", filename)
89 writer.AppendLine("\nFile Name: %s", filename)
90 // this is for recovering after a panic inside parse headers and packet. 98 // this is for recovering after a panic inside parse headers and packet.
91 // this approach was taken since error handling bitreader functions would take a long time. 99 // this approach was taken since error handling bitreader functions would take a long time.
92 defer func() { 100 defer func() {
93 if err := recover(); err != nil { 101 if err := recover(); err != nil {
94 writer.AppendLine("failed to parse demo: %v", err) 102 if wg != nil {
103 wg.Done()
104 }
105 demo.Writer.AppendLine("failed to parse demo: %v", err)
95 } 106 }
96 }() 107 }()
97 demo.Headers = packets.ParseHeaders(reader) 108 demo.Headers = packets.ParseHeaders(reader, demo)
98 for { 109 for {
99 message := packets.ParseMessage(reader) 110 message := packets.ParseMessage(reader, demo)
100 demo.Messages = append(demo.Messages, message) 111 demo.Messages = append(demo.Messages, message)
101 if message.PacketType == 7 { 112 if message.PacketType == 7 {
113 if wg != nil {
114 wg.Done()
115 }
102 break 116 break
103 } 117 }
104 } 118 }
105 return demo
106} 119}
diff --git a/pkg/classes/consoleCmd.go b/pkg/classes/consoleCmd.go
index 47a44e0..83f7333 100644
--- a/pkg/classes/consoleCmd.go
+++ b/pkg/classes/consoleCmd.go
@@ -4,16 +4,16 @@ import (
4 "strings" 4 "strings"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type ConsoleCmd struct { 10type ConsoleCmd struct {
11 Size int32 11 Size int32 `json:"size"`
12 Data string 12 Data string `json:"data"`
13} 13}
14 14
15func (consoleCmd *ConsoleCmd) ParseConsoleCmd(reader *bitreader.Reader) { 15func (consoleCmd *ConsoleCmd) ParseConsoleCmd(reader *bitreader.Reader, demo *types.Demo) {
16 consoleCmd.Size = reader.TryReadSInt32() 16 consoleCmd.Size = reader.TryReadSInt32()
17 consoleCmd.Data = reader.TryReadStringLength(uint64(consoleCmd.Size)) 17 consoleCmd.Data = reader.TryReadStringLength(uint64(consoleCmd.Size))
18 writer.AppendLine("\t%s", strings.TrimSpace(consoleCmd.Data)) 18 demo.Writer.AppendLine("\t%s", strings.TrimSpace(consoleCmd.Data))
19} 19}
diff --git a/pkg/classes/customData.go b/pkg/classes/customData.go
index 1d6f30a..4c1a79e 100644
--- a/pkg/classes/customData.go
+++ b/pkg/classes/customData.go
@@ -2,29 +2,30 @@ package classes
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type CustomData struct { 8type CustomData struct {
9 Type int32 9 Type int32 `json:"type"`
10 Size int32 10 Size int32 `json:"size"`
11 Data string 11 Data any `json:"data"`
12} 12}
13 13
14func (customData *CustomData) ParseCustomData(reader *bitreader.Reader, tickNumber int32, packetType uint8) { 14func (customData *CustomData) ParseCustomData(reader *bitreader.Reader, tickNumber int32, packetType uint8, demo *types.Demo) {
15 customData.Type = reader.TryReadSInt32() 15 customData.Type = reader.TryReadSInt32()
16 customData.Size = reader.TryReadSInt32() 16 customData.Size = reader.TryReadSInt32()
17 if customData.Type != 0 || customData.Size == 8 { 17 if customData.Type != 0 || customData.Size == 8 {
18 // Not SAR data 18 // Not SAR data
19 writer.AppendLine("[%d] %s (%d):", tickNumber, "CUSTOMDATA", packetType) 19 demo.Writer.AppendLine("[%d] %s (%d):", tickNumber, "CUSTOMDATA", packetType)
20 customData.Data = string(reader.TryReadBytesToSlice(uint64(customData.Size))) 20 customData.Data = string(reader.TryReadBytesToSlice(uint64(customData.Size)))
21 writer.AppendLine("\t%s", customData.Data) 21 demo.Writer.AppendLine("\t%s", customData.Data)
22 return 22 return
23 } 23 }
24 // SAR data 24 // SAR data
25 writer.AppendLine("[%d] %s (%d):", tickNumber, "SARDATA", packetType) 25 demo.Writer.AppendLine("[%d] %s (%d):", tickNumber, "SARDATA", packetType)
26 sarData := SarData{} 26 sarData := SarData{}
27 data := reader.TryReadBytesToSlice(uint64(customData.Size)) 27 data := reader.TryReadBytesToSlice(uint64(customData.Size))
28 sarReader := bitreader.NewReaderFromBytes(data, true) 28 sarReader := bitreader.NewReaderFromBytes(data, true)
29 sarData.ParseSarData(sarReader) 29 sarData.ParseSarData(sarReader, demo)
30 customData.Data = sarData
30} 31}
diff --git a/pkg/classes/dataTables.go b/pkg/classes/dataTables.go
index 50be8fe..cf3762a 100644
--- a/pkg/classes/dataTables.go
+++ b/pkg/classes/dataTables.go
@@ -4,59 +4,59 @@ import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type DataTables struct { 10type DataTables struct {
11 Size int32 11 Size int32 `json:"size"`
12 SendTable []SendTable 12 SendTable []SendTable `json:"send_table"`
13 ServerClassInfo []ServerClassInfo 13 ServerClassInfo []ServerClassInfo `json:"server_class_info"`
14} 14}
15 15
16type SendTable struct { 16type SendTable struct {
17 NeedsDecoder bool 17 NeedsDecoder bool `json:"needs_decoder"`
18 NetTableName string 18 NetTableName string `json:"net_table_name"`
19 NumOfProps int16 19 NumOfProps int16 `json:"num_of_props"`
20 Props []SendTableProp 20 Props []SendTableProp `json:"props"`
21} 21}
22 22
23type ServerClassInfo struct { 23type ServerClassInfo struct {
24 DataTableID uint16 24 DataTableID uint16 `json:"data_table_id"`
25 ClassName string 25 ClassName string `json:"class_name"`
26 DataTableName string 26 DataTableName string `json:"data_table_name"`
27} 27}
28 28
29type SendTableProp struct { 29type SendTableProp struct {
30 SendPropType SendPropType 30 SendPropType SendPropType `json:"send_prop_type"`
31 SendPropName string 31 SendPropName string `json:"send_prop_name"`
32 SendPropFlags uint32 32 SendPropFlags uint32 `json:"send_prop_flags"`
33 Priority uint8 33 Priority uint8 `json:"priority"`
34 ExcludeDtName string 34 ExcludeDtName string `json:"exclude_dt_name"`
35 LowValue float32 35 LowValue float32 `json:"low_value"`
36 HighValue float32 36 HighValue float32 `json:"high_value"`
37 NumBits int32 37 NumBits int32 `json:"num_bits"`
38 NumElements int32 38 NumElements int32 `json:"num_elements"`
39} 39}
40 40
41func (dataTables *DataTables) ParseDataTables(reader *bitreader.Reader) { 41func (dataTables *DataTables) ParseDataTables(reader *bitreader.Reader, demo *types.Demo) {
42 dataTables.Size = int32(reader.TryReadSInt32()) 42 dataTables.Size = int32(reader.TryReadSInt32())
43 dataTableReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(dataTables.Size)), true) 43 dataTableReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(dataTables.Size)), true)
44 count := 0 44 count := 0
45 for dataTableReader.TryReadBool() { 45 for dataTableReader.TryReadBool() {
46 count++ 46 count++
47 dataTables.SendTable = append(dataTables.SendTable, ParseSendTable(dataTableReader)) 47 dataTables.SendTable = append(dataTables.SendTable, ParseSendTable(dataTableReader, demo))
48 } 48 }
49 writer.AppendLine("\t%d Send Tables:", count) 49 demo.Writer.AppendLine("\t%d Send Tables:", count)
50 writer.AppendOutputFromTemp() 50 demo.Writer.AppendOutputFromTemp()
51 numOfClasses := dataTableReader.TryReadBits(16) 51 numOfClasses := dataTableReader.TryReadBits(16)
52 for count = 0; count < int(numOfClasses); count++ { 52 for count = 0; count < int(numOfClasses); count++ {
53 dataTables.ServerClassInfo = append(dataTables.ServerClassInfo, ParseServerClassInfo(dataTableReader, count, int(numOfClasses))) 53 dataTables.ServerClassInfo = append(dataTables.ServerClassInfo, ParseServerClassInfo(dataTableReader, count, int(numOfClasses), demo))
54 } 54 }
55 writer.AppendLine("\t%d Classes:", count) 55 demo.Writer.AppendLine("\t%d Classes:", count)
56 writer.AppendOutputFromTemp() 56 demo.Writer.AppendOutputFromTemp()
57} 57}
58 58
59func ParseSendTable(reader *bitreader.Reader) SendTable { 59func ParseSendTable(reader *bitreader.Reader, demo *types.Demo) SendTable {
60 sendTable := SendTable{ 60 sendTable := SendTable{
61 NeedsDecoder: reader.TryReadBool(), 61 NeedsDecoder: reader.TryReadBool(),
62 NetTableName: reader.TryReadString(), 62 NetTableName: reader.TryReadString(),
@@ -65,7 +65,7 @@ func ParseSendTable(reader *bitreader.Reader) SendTable {
65 if sendTable.NumOfProps < 0 { 65 if sendTable.NumOfProps < 0 {
66 return sendTable 66 return sendTable
67 } 67 }
68 writer.TempAppendLine("\t\t%s (%d Props):", sendTable.NetTableName, sendTable.NumOfProps) 68 demo.Writer.TempAppendLine("\t\t%s (%d Props):", sendTable.NetTableName, sendTable.NumOfProps)
69 for count := 0; count < int(sendTable.NumOfProps); count++ { 69 for count := 0; count < int(sendTable.NumOfProps); count++ {
70 propType := int8(reader.TryReadBits(5)) 70 propType := int8(reader.TryReadBits(5))
71 if propType >= int8(7) { 71 if propType >= int8(7) {
@@ -77,38 +77,38 @@ func ParseSendTable(reader *bitreader.Reader) SendTable {
77 SendPropFlags: uint32(reader.TryReadBits(19)), 77 SendPropFlags: uint32(reader.TryReadBits(19)),
78 Priority: reader.TryReadUInt8(), 78 Priority: reader.TryReadUInt8(),
79 } 79 }
80 writer.TempAppend("\t\t\t%s\t", prop.SendPropType) 80 demo.Writer.TempAppend("\t\t\t%s\t", prop.SendPropType)
81 if propType == int8(ESendPropTypeDataTable) || checkBit(prop.SendPropFlags, 6) { 81 if propType == int8(ESendPropTypeDataTable) || checkBit(prop.SendPropFlags, 6) {
82 prop.ExcludeDtName = reader.TryReadString() 82 prop.ExcludeDtName = reader.TryReadString()
83 writer.TempAppend(":\t%s\t", prop.ExcludeDtName) 83 demo.Writer.TempAppend(":\t%s\t", prop.ExcludeDtName)
84 } else { 84 } else {
85 switch propType { 85 switch propType {
86 case int8(ESendPropTypeString), int8(ESendPropTypeInt), int8(ESendPropTypeFloat), int8(ESendPropTypeVector3), int8(ESendPropTypeVector2): 86 case int8(ESendPropTypeString), int8(ESendPropTypeInt), int8(ESendPropTypeFloat), int8(ESendPropTypeVector3), int8(ESendPropTypeVector2):
87 prop.LowValue = reader.TryReadFloat32() 87 prop.LowValue = reader.TryReadFloat32()
88 prop.HighValue = reader.TryReadFloat32() 88 prop.HighValue = reader.TryReadFloat32()
89 prop.NumBits = int32(reader.TryReadBits(7)) 89 prop.NumBits = int32(reader.TryReadBits(7))
90 writer.TempAppend("Low: %f\tHigh: %f\t%d bits\t", prop.LowValue, prop.HighValue, prop.NumBits) 90 demo.Writer.TempAppend("Low: %f\tHigh: %f\t%d bits\t", prop.LowValue, prop.HighValue, prop.NumBits)
91 case int8(ESendPropTypeArray): 91 case int8(ESendPropTypeArray):
92 prop.NumElements = int32(reader.TryReadBits(10)) 92 prop.NumElements = int32(reader.TryReadBits(10))
93 writer.TempAppend("Elements: %d\t", prop.NumElements) 93 demo.Writer.TempAppend("Elements: %d\t", prop.NumElements)
94 default: 94 default:
95 writer.TempAppend("Unknown Prop Type: %v\t", propType) 95 demo.Writer.TempAppend("Unknown Prop Type: %v\t", propType)
96 return sendTable 96 return sendTable
97 } 97 }
98 } 98 }
99 writer.TempAppend("Flags: %v\tPriority: %d\n", prop.GetFlags(), prop.Priority) 99 demo.Writer.TempAppend("Flags: %v\tPriority: %d\n", prop.GetFlags(), prop.Priority)
100 sendTable.Props = append(sendTable.Props, prop) 100 sendTable.Props = append(sendTable.Props, prop)
101 } 101 }
102 return sendTable 102 return sendTable
103} 103}
104 104
105func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo { 105func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int, demo *types.Demo) ServerClassInfo {
106 serverClassInfo := ServerClassInfo{ 106 serverClassInfo := ServerClassInfo{
107 DataTableID: 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.DataTableID, serverClassInfo.ClassName, serverClassInfo.DataTableName) 111 demo.Writer.TempAppendLine("\t\t\t[%d] %s (%s)", serverClassInfo.DataTableID, serverClassInfo.ClassName, serverClassInfo.DataTableName)
112 return serverClassInfo 112 return serverClassInfo
113} 113}
114 114
diff --git a/pkg/classes/packet.go b/pkg/classes/packet.go
index 445ae91..c4f9676 100644
--- a/pkg/classes/packet.go
+++ b/pkg/classes/packet.go
@@ -5,32 +5,32 @@ import (
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/messages" 7 "github.com/pektezol/sdp.go/pkg/messages"
8 "github.com/pektezol/sdp.go/pkg/writer" 8 "github.com/pektezol/sdp.go/pkg/types"
9) 9)
10 10
11const MSSC int = 2 11const MSSC int = 2
12 12
13type Packet struct { 13type Packet struct {
14 PacketInfo []CmdInfo 14 PacketInfo []CmdInfo `json:"packet_info"`
15 InSequence uint32 15 InSequence uint32 `json:"in_sequence"`
16 OutSequence uint32 16 OutSequence uint32 `json:"out_sequence"`
17 Size uint32 17 Size uint32 `json:"size"`
18 Data []any 18 Data []any `json:"data"`
19} 19}
20 20
21type CmdInfo struct { 21type CmdInfo struct {
22 Flags uint32 22 Flags uint32 `json:"flags"`
23 ViewOrigin []float32 23 ViewOrigin []float32 `json:"view_origin"`
24 ViewAngles []float32 24 ViewAngles []float32 `json:"view_angles"`
25 LocalViewAngles []float32 25 LocalViewAngles []float32 `json:"local_view_angles"`
26 ViewOrigin2 []float32 26 ViewOrigin2 []float32 `json:"view_origin_2"`
27 ViewAngles2 []float32 27 ViewAngles2 []float32 `json:"view_angles_2"`
28 LocalViewAngles2 []float32 28 LocalViewAngles2 []float32 `json:"local_view_angles_2"`
29} 29}
30 30
31func (packet *Packet) ParsePacket(reader *bitreader.Reader) { 31func (packet *Packet) ParsePacket(reader *bitreader.Reader, demo *types.Demo) {
32 for count := 0; count < MSSC; count++ { 32 for count := 0; count < MSSC; count++ {
33 packet.ParseCmdInfo(reader) 33 packet.ParseCmdInfo(reader, demo)
34 } 34 }
35 packet.InSequence = reader.TryReadUInt32() 35 packet.InSequence = reader.TryReadUInt32()
36 packet.OutSequence = reader.TryReadUInt32() 36 packet.OutSequence = reader.TryReadUInt32()
@@ -41,11 +41,11 @@ func (packet *Packet) ParsePacket(reader *bitreader.Reader) {
41 if err != nil { 41 if err != nil {
42 break 42 break
43 } 43 }
44 packet.Data = append(packet.Data, messages.ParseMessages(messageType, packetReader)) 44 packet.Data = append(packet.Data, messages.ParseMessages(messageType, packetReader, demo))
45 } 45 }
46} 46}
47 47
48func (packet *Packet) ParseCmdInfo(reader *bitreader.Reader) { 48func (packet *Packet) ParseCmdInfo(reader *bitreader.Reader, demo *types.Demo) {
49 packet.PacketInfo = append(packet.PacketInfo, CmdInfo{ 49 packet.PacketInfo = append(packet.PacketInfo, CmdInfo{
50 Flags: reader.TryReadUInt32(), 50 Flags: reader.TryReadUInt32(),
51 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 51 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
@@ -55,14 +55,14 @@ func (packet *Packet) ParseCmdInfo(reader *bitreader.Reader) {
55 ViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 55 ViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
56 LocalViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 56 LocalViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
57 }) 57 })
58 writer.AppendLine("\tFlags: %s", CmdInfoFlags(packet.PacketInfo[len(packet.PacketInfo)-1].Flags).String()) 58 demo.Writer.AppendLine("\tFlags: %s", CmdInfoFlags(packet.PacketInfo[len(packet.PacketInfo)-1].Flags).String())
59 writer.AppendLine("\tView Origin: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewOrigin) 59 demo.Writer.AppendLine("\tView Origin: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewOrigin)
60 writer.AppendLine("\tView Angles: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewAngles) 60 demo.Writer.AppendLine("\tView Angles: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewAngles)
61 writer.AppendLine("\tLocal View Angles: %v", packet.PacketInfo[len(packet.PacketInfo)-1].LocalViewAngles) 61 demo.Writer.AppendLine("\tLocal View Angles: %v", packet.PacketInfo[len(packet.PacketInfo)-1].LocalViewAngles)
62 writer.AppendLine("\tView Origin 2: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewOrigin2) 62 demo.Writer.AppendLine("\tView Origin 2: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewOrigin2)
63 writer.AppendLine("\tView Angles 2: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewAngles2) 63 demo.Writer.AppendLine("\tView Angles 2: %v", packet.PacketInfo[len(packet.PacketInfo)-1].ViewAngles2)
64 writer.AppendLine("\tLocal View Angles 2: %v", packet.PacketInfo[len(packet.PacketInfo)-1].LocalViewAngles2) 64 demo.Writer.AppendLine("\tLocal View Angles 2: %v", packet.PacketInfo[len(packet.PacketInfo)-1].LocalViewAngles2)
65 writer.AppendLine("") 65 demo.Writer.AppendLine("")
66} 66}
67 67
68type CmdInfoFlags int 68type CmdInfoFlags int
diff --git a/pkg/classes/sarData.go b/pkg/classes/sarData.go
index 4a5bfed..ec2830e 100644
--- a/pkg/classes/sarData.go
+++ b/pkg/classes/sarData.go
@@ -5,7 +5,7 @@ import (
5 "fmt" 5 "fmt"
6 6
7 "github.com/pektezol/bitreader" 7 "github.com/pektezol/bitreader"
8 "github.com/pektezol/sdp.go/pkg/writer" 8 "github.com/pektezol/sdp.go/pkg/types"
9) 9)
10 10
11type SarDataType uint8 11type SarDataType uint8
@@ -69,89 +69,89 @@ func (sarDataType SarDataType) String() string {
69} 69}
70 70
71type SarData struct { 71type SarData struct {
72 Type SarDataType 72 Type SarDataType `json:"type"`
73 Slot int 73 Slot int `json:"slot"`
74 Data any 74 Data any `json:"data"`
75} 75}
76 76
77type SarDataTimescaleCheat struct { 77type SarDataTimescaleCheat struct {
78 Timescale float32 78 Timescale float32 `json:"timescale"`
79} 79}
80 80
81type SarDataInitialCVar struct { 81type SarDataInitialCVar struct {
82 CVar string 82 CVar string `json:"cvar"`
83 Val string 83 Val string `json:"val"`
84} 84}
85 85
86type SarDataChecksum struct { 86type SarDataChecksum struct {
87 DemoSum uint32 87 DemoSum uint32 `json:"demo_sum"`
88 SarSum uint32 88 SarSum uint32 `json:"sar_sum"`
89} 89}
90 90
91type SarDataChecksumV2 struct { 91type SarDataChecksumV2 struct {
92 SarSum uint32 92 SarSum uint32 `json:"sar_sum"`
93 Signature [64]byte 93 Signature [64]byte `json:"signature"`
94} 94}
95 95
96type SarDataEntityInput struct { 96type SarDataEntityInput struct {
97 TargetName string 97 TargetName string `json:"target_name"`
98 ClassName string 98 ClassName string `json:"class_name"`
99 InputName string 99 InputName string `json:"input_name"`
100 Parameter string 100 Parameter string `json:"parameter"`
101} 101}
102 102
103type SarDataPortalPlacement struct { 103type SarDataPortalPlacement struct {
104 Orange bool 104 Orange bool `json:"orange"`
105 X float32 105 X float32 `json:"x"`
106 Y float32 106 Y float32 `json:"y"`
107 Z float32 107 Z float32 `json:"z"`
108} 108}
109 109
110type SarDataPause struct { 110type SarDataPause struct {
111 PauseTicks uint32 111 PauseTicks uint32 `json:"pause_ticks"`
112} 112}
113 113
114type SarDataWaitRun struct { 114type SarDataWaitRun struct {
115 Ticks int 115 Ticks int `json:"ticks"`
116 Cmd string 116 Cmd string `json:"cmd"`
117} 117}
118 118
119type SarDataHWaitRun struct { 119type SarDataHWaitRun struct {
120 Ticks int 120 Ticks int `json:"ticks"`
121 Cmd string 121 Cmd string `json:"cmd"`
122} 122}
123 123
124type SarDataSpeedrunTime struct { 124type SarDataSpeedrunTime struct {
125 NSplits uint32 125 NSplits uint32 `json:"n_splits"`
126 Splits []SarDataSpeedrunTimeSplits 126 Splits []SarDataSpeedrunTimeSplits `json:"splits"`
127} 127}
128 128
129type SarDataSpeedrunTimeSegs struct { 129type SarDataSpeedrunTimeSegs struct {
130 Name string 130 Name string `json:"name"`
131 Ticks uint32 131 Ticks uint32 `json:"ticks"`
132} 132}
133 133
134type SarDataSpeedrunTimeSplits struct { 134type SarDataSpeedrunTimeSplits struct {
135 Name string 135 Name string `json:"name"`
136 NSegs uint32 136 NSegs uint32 `json:"n_segs"`
137 Segs []SarDataSpeedrunTimeSegs 137 Segs []SarDataSpeedrunTimeSegs `json:"segs"`
138} 138}
139 139
140type SarDataTimestamp struct { 140type SarDataTimestamp struct {
141 Year uint16 141 Year uint16 `json:"year"`
142 Month uint8 142 Month uint8 `json:"month"`
143 Day uint8 143 Day uint8 `json:"day"`
144 Hour uint8 144 Hour uint8 `json:"hour"`
145 Minute uint8 145 Minute uint8 `json:"minute"`
146 Second uint8 146 Second uint8 `json:"second"`
147} 147}
148 148
149type SarDataFileChecksum struct { 149type SarDataFileChecksum struct {
150 Sum uint32 150 Sum uint32 `json:"sum"`
151 Path string 151 Path string `json:"path"`
152} 152}
153 153
154func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) { 154func (sarData *SarData) ParseSarData(reader *bitreader.Reader, demo *types.Demo) (err error) {
155 reader.SkipBytes(8) 155 reader.SkipBytes(8)
156 len := reader.TryReadRemainingBits() / 8 156 len := reader.TryReadRemainingBits() / 8
157 if len == 0 { 157 if len == 0 {
@@ -164,32 +164,32 @@ func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) {
164 len = 9 164 len = 9
165 } 165 }
166 dataReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(len-1), true) 166 dataReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(len-1), true)
167 writer.AppendLine("\tMessage: %s (%d):", sarData.Type.String(), sarData.Type) 167 demo.Writer.AppendLine("\tMessage: %s (%d):", sarData.Type.String(), sarData.Type)
168 switch sarData.Type { 168 switch sarData.Type {
169 case ESarDataTimescaleCheat: 169 case ESarDataTimescaleCheat:
170 sarData.Data, err = parseTimescaleCheatData(dataReader, len) 170 sarData.Data, err = parseTimescaleCheatData(dataReader, len, demo)
171 if err != nil { 171 if err != nil {
172 sarData.Data = nil 172 sarData.Data = nil
173 } 173 }
174 case ESarDataInitialCVar: 174 case ESarDataInitialCVar:
175 sarData.Data = parseInitialCVarData(dataReader) 175 sarData.Data = parseInitialCVarData(dataReader, demo)
176 case ESarDataEntityInputSlot: 176 case ESarDataEntityInputSlot:
177 sarData.Slot = int(dataReader.TryReadBytes(1)) 177 sarData.Slot = int(dataReader.TryReadBytes(1))
178 writer.AppendLine("\t\tSlot: %d", sarData.Slot) 178 demo.Writer.AppendLine("\t\tSlot: %d", sarData.Slot)
179 case ESarDataEntityInput: 179 case ESarDataEntityInput:
180 sarData.Data = parseEntityInputData(dataReader) 180 sarData.Data = parseEntityInputData(dataReader, demo)
181 case ESarDataChecksum: 181 case ESarDataChecksum:
182 sarData.Data, err = parseChecksumData(dataReader, len) 182 sarData.Data, err = parseChecksumData(dataReader, len, demo)
183 if err != nil { 183 if err != nil {
184 sarData.Data = nil 184 sarData.Data = nil
185 } 185 }
186 case ESarDataChecksumV2: 186 case ESarDataChecksumV2:
187 sarData.Data, err = parseChecksumV2Data(dataReader, len) 187 sarData.Data, err = parseChecksumV2Data(dataReader, len, demo)
188 if err != nil { 188 if err != nil {
189 sarData.Data = nil 189 sarData.Data = nil
190 } 190 }
191 case ESarDataPortalPlacement: 191 case ESarDataPortalPlacement:
192 data, slot, err := parsePortalPlacementData(dataReader, len) 192 data, slot, err := parsePortalPlacementData(dataReader, len, demo)
193 if err != nil { 193 if err != nil {
194 sarData.Data = nil 194 sarData.Data = nil
195 } else { 195 } else {
@@ -201,34 +201,34 @@ func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) {
201 if err != nil { 201 if err != nil {
202 sarData.Data = nil 202 sarData.Data = nil
203 } 203 }
204 writer.AppendLine("\t\tSlot: %d", sarData.Slot) 204 demo.Writer.AppendLine("\t\tSlot: %d", sarData.Slot)
205 case ESarDataPause: 205 case ESarDataPause:
206 sarData.Data, err = parsePauseData(dataReader, len) 206 sarData.Data, err = parsePauseData(dataReader, len, demo)
207 if err != nil { 207 if err != nil {
208 sarData.Data = nil 208 sarData.Data = nil
209 } 209 }
210 case ESarDataWaitRun: 210 case ESarDataWaitRun:
211 sarData.Data, err = parseWaitRunData(dataReader, len) 211 sarData.Data, err = parseWaitRunData(dataReader, len, demo)
212 if err != nil { 212 if err != nil {
213 sarData.Data = nil 213 sarData.Data = nil
214 } 214 }
215 case ESarDataHWaitRun: 215 case ESarDataHWaitRun:
216 sarData.Data, err = parseHWaitRunData(dataReader, len) 216 sarData.Data, err = parseHWaitRunData(dataReader, len, demo)
217 if err != nil { 217 if err != nil {
218 sarData.Data = nil 218 sarData.Data = nil
219 } 219 }
220 case ESarDataSpeedrunTime: 220 case ESarDataSpeedrunTime:
221 sarData.Data, err = parseSpeedrunTimeData(dataReader, len) 221 sarData.Data, err = parseSpeedrunTimeData(dataReader, len, demo)
222 if err != nil { 222 if err != nil {
223 sarData.Data = nil 223 sarData.Data = nil
224 } 224 }
225 case ESarDataTimestamp: 225 case ESarDataTimestamp:
226 sarData.Data, err = parseTimestampData(dataReader, len) 226 sarData.Data, err = parseTimestampData(dataReader, len, demo)
227 if err != nil { 227 if err != nil {
228 sarData.Data = nil 228 sarData.Data = nil
229 } 229 }
230 case ESarDataFileChecksum: 230 case ESarDataFileChecksum:
231 sarData.Data, err = parseFileChecksumData(dataReader, len) 231 sarData.Data, err = parseFileChecksumData(dataReader, len, demo)
232 if err != nil { 232 if err != nil {
233 sarData.Data = nil 233 sarData.Data = nil
234 } 234 }
@@ -239,41 +239,41 @@ func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) {
239 return nil 239 return nil
240} 240}
241 241
242func parseTimescaleCheatData(reader *bitreader.Reader, length uint64) (SarDataTimescaleCheat, error) { 242func parseTimescaleCheatData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataTimescaleCheat, error) {
243 if length != 5 { 243 if length != 5 {
244 return SarDataTimescaleCheat{}, errors.New("sar data invalid") 244 return SarDataTimescaleCheat{}, errors.New("sar data invalid")
245 } 245 }
246 sarDataTimescaleCheat := SarDataTimescaleCheat{ 246 sarDataTimescaleCheat := SarDataTimescaleCheat{
247 Timescale: reader.TryReadFloat32(), 247 Timescale: reader.TryReadFloat32(),
248 } 248 }
249 writer.AppendLine("\t\tTimescale: %f", sarDataTimescaleCheat.Timescale) 249 demo.Writer.AppendLine("\t\tTimescale: %f", sarDataTimescaleCheat.Timescale)
250 return sarDataTimescaleCheat, nil 250 return sarDataTimescaleCheat, nil
251} 251}
252 252
253func parseInitialCVarData(reader *bitreader.Reader) SarDataInitialCVar { 253func parseInitialCVarData(reader *bitreader.Reader, demo *types.Demo) SarDataInitialCVar {
254 sarDataInitialCvar := SarDataInitialCVar{ 254 sarDataInitialCvar := SarDataInitialCVar{
255 CVar: reader.TryReadString(), 255 CVar: reader.TryReadString(),
256 Val: reader.TryReadString(), 256 Val: reader.TryReadString(),
257 } 257 }
258 writer.AppendLine("\t\tCvar: \"%s\" = \"%s\"", sarDataInitialCvar.CVar, sarDataInitialCvar.Val) 258 demo.Writer.AppendLine("\t\tCvar: \"%s\" = \"%s\"", sarDataInitialCvar.CVar, sarDataInitialCvar.Val)
259 return sarDataInitialCvar 259 return sarDataInitialCvar
260} 260}
261 261
262func parseEntityInputData(reader *bitreader.Reader) SarDataEntityInput { 262func parseEntityInputData(reader *bitreader.Reader, demo *types.Demo) SarDataEntityInput {
263 sarDataEntityInput := SarDataEntityInput{ 263 sarDataEntityInput := SarDataEntityInput{
264 TargetName: reader.TryReadString(), 264 TargetName: reader.TryReadString(),
265 ClassName: reader.TryReadString(), 265 ClassName: reader.TryReadString(),
266 InputName: reader.TryReadString(), 266 InputName: reader.TryReadString(),
267 Parameter: reader.TryReadString(), 267 Parameter: reader.TryReadString(),
268 } 268 }
269 writer.AppendLine("\t\tTarget: %s", sarDataEntityInput.TargetName) 269 demo.Writer.AppendLine("\t\tTarget: %s", sarDataEntityInput.TargetName)
270 writer.AppendLine("\t\tClass: %s", sarDataEntityInput.ClassName) 270 demo.Writer.AppendLine("\t\tClass: %s", sarDataEntityInput.ClassName)
271 writer.AppendLine("\t\tInput: %s", sarDataEntityInput.InputName) 271 demo.Writer.AppendLine("\t\tInput: %s", sarDataEntityInput.InputName)
272 writer.AppendLine("\t\tParameter: %s", sarDataEntityInput.Parameter) 272 demo.Writer.AppendLine("\t\tParameter: %s", sarDataEntityInput.Parameter)
273 return sarDataEntityInput 273 return sarDataEntityInput
274} 274}
275 275
276func parseChecksumData(reader *bitreader.Reader, length uint64) (SarDataChecksum, error) { 276func parseChecksumData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataChecksum, error) {
277 if length != 9 { 277 if length != 9 {
278 return SarDataChecksum{}, errors.New("sar data invalid") 278 return SarDataChecksum{}, errors.New("sar data invalid")
279 } 279 }
@@ -281,12 +281,12 @@ func parseChecksumData(reader *bitreader.Reader, length uint64) (SarDataChecksum
281 DemoSum: reader.TryReadUInt32(), 281 DemoSum: reader.TryReadUInt32(),
282 SarSum: reader.TryReadUInt32(), 282 SarSum: reader.TryReadUInt32(),
283 } 283 }
284 writer.AppendLine("\t\tDemo Checksum: %d", sarDataChecksum.DemoSum) 284 demo.Writer.AppendLine("\t\tDemo Checksum: %d", sarDataChecksum.DemoSum)
285 writer.AppendLine("\t\tSAR Checksum: %d", sarDataChecksum.SarSum) 285 demo.Writer.AppendLine("\t\tSAR Checksum: %d", sarDataChecksum.SarSum)
286 return sarDataChecksum, nil 286 return sarDataChecksum, nil
287} 287}
288 288
289func parseChecksumV2Data(reader *bitreader.Reader, length uint64) (SarDataChecksumV2, error) { 289func parseChecksumV2Data(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataChecksumV2, error) {
290 if length != 69 { 290 if length != 69 {
291 return SarDataChecksumV2{}, errors.New("sar data invalid") 291 return SarDataChecksumV2{}, errors.New("sar data invalid")
292 } 292 }
@@ -294,12 +294,12 @@ func parseChecksumV2Data(reader *bitreader.Reader, length uint64) (SarDataChecks
294 SarSum: reader.TryReadUInt32(), 294 SarSum: reader.TryReadUInt32(),
295 Signature: [64]byte(reader.TryReadBytesToSlice(60)), 295 Signature: [64]byte(reader.TryReadBytesToSlice(60)),
296 } 296 }
297 writer.AppendLine("\t\tSAR Checksum: %d", sarDataChecksumV2.SarSum) 297 demo.Writer.AppendLine("\t\tSAR Checksum: %d", sarDataChecksumV2.SarSum)
298 writer.AppendLine("\t\tSignature: %v", sarDataChecksumV2.Signature) 298 demo.Writer.AppendLine("\t\tSignature: %v", sarDataChecksumV2.Signature)
299 return sarDataChecksumV2, nil 299 return sarDataChecksumV2, nil
300} 300}
301 301
302func parsePortalPlacementData(reader *bitreader.Reader, length uint64) (SarDataPortalPlacement, int, error) { 302func parsePortalPlacementData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataPortalPlacement, int, error) {
303 if length != 15 { 303 if length != 15 {
304 return SarDataPortalPlacement{}, 0, errors.New("sar data invalid") 304 return SarDataPortalPlacement{}, 0, errors.New("sar data invalid")
305 } 305 }
@@ -312,10 +312,10 @@ func parsePortalPlacementData(reader *bitreader.Reader, length uint64) (SarDataP
312 Y: reader.TryReadFloat32(), 312 Y: reader.TryReadFloat32(),
313 Z: reader.TryReadFloat32(), 313 Z: reader.TryReadFloat32(),
314 } 314 }
315 writer.AppendLine("\t\tOrange: %t", orange) 315 demo.Writer.AppendLine("\t\tOrange: %t", orange)
316 writer.AppendLine("\t\tX: %f", sarDataPortalPlacement.X) 316 demo.Writer.AppendLine("\t\tX: %f", sarDataPortalPlacement.X)
317 writer.AppendLine("\t\tY: %f", sarDataPortalPlacement.Y) 317 demo.Writer.AppendLine("\t\tY: %f", sarDataPortalPlacement.Y)
318 writer.AppendLine("\t\tZ: %f", sarDataPortalPlacement.Z) 318 demo.Writer.AppendLine("\t\tZ: %f", sarDataPortalPlacement.Z)
319 return sarDataPortalPlacement, slot, nil 319 return sarDataPortalPlacement, slot, nil
320} 320}
321 321
@@ -326,18 +326,18 @@ func parseChallengeFlagsCrouchFlyData(reader *bitreader.Reader, length uint64) (
326 return int(reader.TryReadBytes(1)), nil 326 return int(reader.TryReadBytes(1)), nil
327} 327}
328 328
329func parsePauseData(reader *bitreader.Reader, length uint64) (SarDataPause, error) { 329func parsePauseData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataPause, error) {
330 if length != 5 { 330 if length != 5 {
331 return SarDataPause{}, errors.New("sar data invalid") 331 return SarDataPause{}, errors.New("sar data invalid")
332 } 332 }
333 sarDataPause := SarDataPause{ 333 sarDataPause := SarDataPause{
334 PauseTicks: reader.TryReadUInt32(), 334 PauseTicks: reader.TryReadUInt32(),
335 } 335 }
336 writer.AppendLine("\t\tPause Ticks: %d", sarDataPause.PauseTicks) 336 demo.Writer.AppendLine("\t\tPause Ticks: %d", sarDataPause.PauseTicks)
337 return sarDataPause, nil 337 return sarDataPause, nil
338} 338}
339 339
340func parseWaitRunData(reader *bitreader.Reader, length uint64) (SarDataWaitRun, error) { 340func parseWaitRunData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataWaitRun, error) {
341 if length < 6 { 341 if length < 6 {
342 return SarDataWaitRun{}, errors.New("sar data invalid") 342 return SarDataWaitRun{}, errors.New("sar data invalid")
343 } 343 }
@@ -345,12 +345,12 @@ func parseWaitRunData(reader *bitreader.Reader, length uint64) (SarDataWaitRun,
345 Ticks: int(reader.TryReadUInt32()), 345 Ticks: int(reader.TryReadUInt32()),
346 Cmd: reader.TryReadString(), 346 Cmd: reader.TryReadString(),
347 } 347 }
348 writer.AppendLine("\t\tTicks: %d", sarDataWaitRun.Ticks) 348 demo.Writer.AppendLine("\t\tTicks: %d", sarDataWaitRun.Ticks)
349 writer.AppendLine("\t\tCmd: \"%s\"", sarDataWaitRun.Cmd) 349 demo.Writer.AppendLine("\t\tCmd: \"%s\"", sarDataWaitRun.Cmd)
350 return sarDataWaitRun, nil 350 return sarDataWaitRun, nil
351} 351}
352 352
353func parseHWaitRunData(reader *bitreader.Reader, length uint64) (SarDataHWaitRun, error) { 353func parseHWaitRunData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataHWaitRun, error) {
354 if length < 6 { 354 if length < 6 {
355 return SarDataHWaitRun{}, errors.New("sar data invalid") 355 return SarDataHWaitRun{}, errors.New("sar data invalid")
356 } 356 }
@@ -358,12 +358,12 @@ func parseHWaitRunData(reader *bitreader.Reader, length uint64) (SarDataHWaitRun
358 Ticks: int(reader.TryReadUInt32()), 358 Ticks: int(reader.TryReadUInt32()),
359 Cmd: reader.TryReadString(), 359 Cmd: reader.TryReadString(),
360 } 360 }
361 writer.AppendLine("\t\tTicks: %d", sarDataHWaitRun.Ticks) 361 demo.Writer.AppendLine("\t\tTicks: %d", sarDataHWaitRun.Ticks)
362 writer.AppendLine("\t\tCmd: \"%s\"", sarDataHWaitRun.Cmd) 362 demo.Writer.AppendLine("\t\tCmd: \"%s\"", sarDataHWaitRun.Cmd)
363 return sarDataHWaitRun, nil 363 return sarDataHWaitRun, nil
364} 364}
365 365
366func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64) (SarDataSpeedrunTime, error) { 366func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataSpeedrunTime, error) {
367 if length < 5 { 367 if length < 5 {
368 return SarDataSpeedrunTime{}, errors.New("sar data invalid") 368 return SarDataSpeedrunTime{}, errors.New("sar data invalid")
369 } 369 }
@@ -372,14 +372,14 @@ func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64) (SarDataSpee
372 for splitCount := 0; splitCount < int(numberOfSplits); splitCount++ { 372 for splitCount := 0; splitCount < int(numberOfSplits); splitCount++ {
373 splits[splitCount].Name = reader.TryReadString() 373 splits[splitCount].Name = reader.TryReadString()
374 splits[splitCount].NSegs = reader.TryReadUInt32() 374 splits[splitCount].NSegs = reader.TryReadUInt32()
375 writer.AppendLine("\t\t[%d] Split Name: \"%s\"", splitCount, splits[splitCount].Name) 375 demo.Writer.AppendLine("\t\t[%d] Split Name: \"%s\"", splitCount, splits[splitCount].Name)
376 writer.AppendLine("\t\t[%d] Number of Segments: %d", splitCount, splits[splitCount].NSegs) 376 demo.Writer.AppendLine("\t\t[%d] Number of Segments: %d", splitCount, splits[splitCount].NSegs)
377 splits[splitCount].Segs = make([]SarDataSpeedrunTimeSegs, splits[splitCount].NSegs) 377 splits[splitCount].Segs = make([]SarDataSpeedrunTimeSegs, splits[splitCount].NSegs)
378 for segCount := 0; segCount < int(splits[splitCount].NSegs); segCount++ { 378 for segCount := 0; segCount < int(splits[splitCount].NSegs); segCount++ {
379 splits[splitCount].Segs[segCount].Name = reader.TryReadString() 379 splits[splitCount].Segs[segCount].Name = reader.TryReadString()
380 splits[splitCount].Segs[segCount].Ticks = reader.TryReadUInt32() 380 splits[splitCount].Segs[segCount].Ticks = reader.TryReadUInt32()
381 writer.AppendLine("\t\t\t[%d] Segment Name: \"%s\"", segCount, splits[splitCount].Segs[segCount].Name) 381 demo.Writer.AppendLine("\t\t\t[%d] Segment Name: \"%s\"", segCount, splits[splitCount].Segs[segCount].Name)
382 writer.AppendLine("\t\t\t[%d] Segment Ticks: %d", segCount, splits[splitCount].Segs[segCount].Ticks) 382 demo.Writer.AppendLine("\t\t\t[%d] Segment Ticks: %d", segCount, splits[splitCount].Segs[segCount].Ticks)
383 } 383 }
384 } 384 }
385 return SarDataSpeedrunTime{ 385 return SarDataSpeedrunTime{
@@ -388,7 +388,7 @@ func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64) (SarDataSpee
388 }, nil 388 }, nil
389} 389}
390 390
391func parseTimestampData(reader *bitreader.Reader, length uint64) (SarDataTimestamp, error) { 391func parseTimestampData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataTimestamp, error) {
392 if length != 8 { 392 if length != 8 {
393 return SarDataTimestamp{}, errors.New("sar data invalid") 393 return SarDataTimestamp{}, errors.New("sar data invalid")
394 } 394 }
@@ -401,16 +401,16 @@ func parseTimestampData(reader *bitreader.Reader, length uint64) (SarDataTimesta
401 Minute: timestamp[5], 401 Minute: timestamp[5],
402 Second: timestamp[6], 402 Second: timestamp[6],
403 } 403 }
404 writer.AppendLine("\t\tYear: %d", sarDataTimeStamp.Year) 404 demo.Writer.AppendLine("\t\tYear: %d", sarDataTimeStamp.Year)
405 writer.AppendLine("\t\tMonth: %d", sarDataTimeStamp.Month) 405 demo.Writer.AppendLine("\t\tMonth: %d", sarDataTimeStamp.Month)
406 writer.AppendLine("\t\tDay: %d", sarDataTimeStamp.Day) 406 demo.Writer.AppendLine("\t\tDay: %d", sarDataTimeStamp.Day)
407 writer.AppendLine("\t\tHour: %d", sarDataTimeStamp.Hour) 407 demo.Writer.AppendLine("\t\tHour: %d", sarDataTimeStamp.Hour)
408 writer.AppendLine("\t\tMinute: %d", sarDataTimeStamp.Minute) 408 demo.Writer.AppendLine("\t\tMinute: %d", sarDataTimeStamp.Minute)
409 writer.AppendLine("\t\tSecond: %d", sarDataTimeStamp.Second) 409 demo.Writer.AppendLine("\t\tSecond: %d", sarDataTimeStamp.Second)
410 return sarDataTimeStamp, nil 410 return sarDataTimeStamp, nil
411} 411}
412 412
413func parseFileChecksumData(reader *bitreader.Reader, length uint64) (SarDataFileChecksum, error) { 413func parseFileChecksumData(reader *bitreader.Reader, length uint64, demo *types.Demo) (SarDataFileChecksum, error) {
414 if length < 6 { 414 if length < 6 {
415 return SarDataFileChecksum{}, errors.New("sar data invalid") 415 return SarDataFileChecksum{}, errors.New("sar data invalid")
416 } 416 }
@@ -418,7 +418,7 @@ func parseFileChecksumData(reader *bitreader.Reader, length uint64) (SarDataFile
418 Sum: reader.TryReadUInt32(), 418 Sum: reader.TryReadUInt32(),
419 Path: reader.TryReadString(), 419 Path: reader.TryReadString(),
420 } 420 }
421 writer.AppendLine("\t\tChecksum: %d", sarDataFileChecksum.Sum) 421 demo.Writer.AppendLine("\t\tChecksum: %d", sarDataFileChecksum.Sum)
422 writer.AppendLine("\t\tPath: \"%s\"", sarDataFileChecksum.Path) 422 demo.Writer.AppendLine("\t\tPath: \"%s\"", sarDataFileChecksum.Path)
423 return sarDataFileChecksum, nil 423 return sarDataFileChecksum, nil
424} 424}
diff --git a/pkg/classes/signOn.go b/pkg/classes/signOn.go
index 0d5ca55..e6d2f4e 100644
--- a/pkg/classes/signOn.go
+++ b/pkg/classes/signOn.go
@@ -3,20 +3,20 @@ package classes
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/messages" 5 "github.com/pektezol/sdp.go/pkg/messages"
6 "github.com/pektezol/sdp.go/pkg/writer" 6 "github.com/pektezol/sdp.go/pkg/types"
7) 7)
8 8
9type SignOn struct { 9type SignOn struct {
10 PacketInfo []CmdInfo 10 PacketInfo []CmdInfo `json:"packet_info"`
11 InSequence uint32 11 InSequence uint32 `json:"in_sequence"`
12 OutSequence uint32 12 OutSequence uint32 `json:"out_sequence"`
13 Size uint32 13 Size uint32 `json:"size"`
14 Data []any 14 Data []any `json:"data"`
15} 15}
16 16
17func (signOn *SignOn) ParseSignOn(reader *bitreader.Reader) { 17func (signOn *SignOn) ParseSignOn(reader *bitreader.Reader, demo *types.Demo) {
18 for count := 0; count < MSSC; count++ { 18 for count := 0; count < MSSC; count++ {
19 signOn.ParseCmdInfo(reader) 19 signOn.ParseCmdInfo(reader, demo)
20 } 20 }
21 signOn.InSequence = reader.TryReadUInt32() 21 signOn.InSequence = reader.TryReadUInt32()
22 signOn.OutSequence = reader.TryReadUInt32() 22 signOn.OutSequence = reader.TryReadUInt32()
@@ -27,11 +27,11 @@ func (signOn *SignOn) ParseSignOn(reader *bitreader.Reader) {
27 if err != nil { 27 if err != nil {
28 break 28 break
29 } 29 }
30 signOn.Data = append(signOn.Data, messages.ParseMessages(messageType, packetReader)) 30 signOn.Data = append(signOn.Data, messages.ParseMessages(messageType, packetReader, demo))
31 } 31 }
32} 32}
33 33
34func (signOn *SignOn) ParseCmdInfo(reader *bitreader.Reader) { 34func (signOn *SignOn) ParseCmdInfo(reader *bitreader.Reader, demo *types.Demo) {
35 signOn.PacketInfo = append(signOn.PacketInfo, CmdInfo{ 35 signOn.PacketInfo = append(signOn.PacketInfo, CmdInfo{
36 Flags: reader.TryReadUInt32(), 36 Flags: reader.TryReadUInt32(),
37 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 37 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
@@ -41,12 +41,12 @@ func (signOn *SignOn) ParseCmdInfo(reader *bitreader.Reader) {
41 ViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 41 ViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
42 LocalViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 42 LocalViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
43 }) 43 })
44 writer.AppendLine("\tFlags: %s", CmdInfoFlags(signOn.PacketInfo[len(signOn.PacketInfo)-1].Flags).String()) 44 demo.Writer.AppendLine("\tFlags: %s", CmdInfoFlags(signOn.PacketInfo[len(signOn.PacketInfo)-1].Flags).String())
45 writer.AppendLine("\tView Origin: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewOrigin) 45 demo.Writer.AppendLine("\tView Origin: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewOrigin)
46 writer.AppendLine("\tView Angles: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewAngles) 46 demo.Writer.AppendLine("\tView Angles: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewAngles)
47 writer.AppendLine("\tLocal View Angles: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].LocalViewAngles) 47 demo.Writer.AppendLine("\tLocal View Angles: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].LocalViewAngles)
48 writer.AppendLine("\tView Origin 2: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewOrigin2) 48 demo.Writer.AppendLine("\tView Origin 2: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewOrigin2)
49 writer.AppendLine("\tView Angles 2: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewAngles2) 49 demo.Writer.AppendLine("\tView Angles 2: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].ViewAngles2)
50 writer.AppendLine("\tLocal View Angles 2: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].LocalViewAngles2) 50 demo.Writer.AppendLine("\tLocal View Angles 2: %v", signOn.PacketInfo[len(signOn.PacketInfo)-1].LocalViewAngles2)
51 writer.AppendLine("") 51 demo.Writer.AppendLine("")
52} 52}
diff --git a/pkg/classes/stop.go b/pkg/classes/stop.go
index 97db6cf..c6b52a9 100644
--- a/pkg/classes/stop.go
+++ b/pkg/classes/stop.go
@@ -2,16 +2,16 @@ package classes
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type Stop struct { 8type Stop struct {
9 RemainingData []byte 9 RemainingData []byte `json:"remaining_data"`
10} 10}
11 11
12func (stop *Stop) ParseStop(reader *bitreader.Reader) { 12func (stop *Stop) ParseStop(reader *bitreader.Reader, demo *types.Demo) {
13 if reader.TryReadBool() { 13 if reader.TryReadBool() {
14 stop.RemainingData = reader.TryReadBitsToSlice(uint64(reader.TryReadRemainingBits())) 14 stop.RemainingData = reader.TryReadBitsToSlice(uint64(reader.TryReadRemainingBits()))
15 writer.AppendLine("\tRemaining Data: %v", stop.RemainingData) 15 demo.Writer.AppendLine("\tRemaining Data: %v", stop.RemainingData)
16 } 16 }
17} 17}
diff --git a/pkg/classes/stringTables.go b/pkg/classes/stringTables.go
index 7848b1c..6e1510c 100644
--- a/pkg/classes/stringTables.go
+++ b/pkg/classes/stringTables.go
@@ -5,58 +5,58 @@ import (
5 "strings" 5 "strings"
6 6
7 "github.com/pektezol/bitreader" 7 "github.com/pektezol/bitreader"
8 "github.com/pektezol/sdp.go/pkg/writer" 8 "github.com/pektezol/sdp.go/pkg/types"
9) 9)
10 10
11type StringTables struct { 11type StringTables struct {
12 Size int32 12 Size int32 `json:"size"`
13 Data []StringTable 13 Data []StringTable `json:"data"`
14} 14}
15 15
16type StringTable struct { 16type StringTable struct {
17 Name string 17 Name string `json:"name"`
18 TableEntries []StringTableEntry 18 TableEntries []StringTableEntry `json:"table_entries"`
19 Classes []StringTableClass 19 Classes []StringTableClass `json:"classes"`
20} 20}
21 21
22type StringTableClass struct { 22type StringTableClass struct {
23 Name string 23 Name string `json:"name"`
24 Data string 24 Data string `json:"data"`
25} 25}
26type StringTableEntry struct { 26type StringTableEntry struct {
27 Name string 27 Name string `json:"name"`
28 EntryData any 28 EntryData any `json:"entry_data"`
29} 29}
30 30
31func (stringTables *StringTables) ParseStringTables(reader *bitreader.Reader) { 31func (stringTables *StringTables) ParseStringTables(reader *bitreader.Reader, demo *types.Demo) {
32 stringTables.Size = reader.TryReadSInt32() 32 stringTables.Size = reader.TryReadSInt32()
33 stringTableReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(stringTables.Size)), true) 33 stringTableReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(stringTables.Size)), true)
34 tableCount := stringTableReader.TryReadBits(8) 34 tableCount := stringTableReader.TryReadBits(8)
35 tables := make([]StringTable, tableCount) 35 tables := make([]StringTable, tableCount)
36 for i := 0; i < int(tableCount); i++ { 36 for i := 0; i < int(tableCount); i++ {
37 var table StringTable 37 var table StringTable
38 table.ParseStream(stringTableReader) 38 table.ParseStream(stringTableReader, demo)
39 tables[i] = table 39 tables[i] = table
40 } 40 }
41 stringTables.Data = tables 41 stringTables.Data = tables
42} 42}
43 43
44func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) { 44func (stringTable *StringTable) ParseStream(reader *bitreader.Reader, demo *types.Demo) {
45 stringTable.Name = reader.TryReadString() 45 stringTable.Name = reader.TryReadString()
46 entryCount := reader.TryReadBits(16) 46 entryCount := reader.TryReadBits(16)
47 writer.AppendLine("\tTable Name: %s", stringTable.Name) 47 demo.Writer.AppendLine("\tTable Name: %s", stringTable.Name)
48 stringTable.TableEntries = make([]StringTableEntry, entryCount) 48 stringTable.TableEntries = make([]StringTableEntry, entryCount)
49 49
50 for i := 0; i < int(entryCount); i++ { 50 for i := 0; i < int(entryCount); i++ {
51 var entry StringTableEntry 51 var entry StringTableEntry
52 entry.Parse(stringTable.Name, reader) 52 entry.Parse(stringTable.Name, reader, demo)
53 stringTable.TableEntries[i] = entry 53 stringTable.TableEntries[i] = entry
54 } 54 }
55 if entryCount != 0 { 55 if entryCount != 0 {
56 writer.AppendLine("\t\t%d Table Entries:", entryCount) 56 demo.Writer.AppendLine("\t\t%d Table Entries:", entryCount)
57 writer.AppendOutputFromTemp() 57 demo.Writer.AppendOutputFromTemp()
58 } else { 58 } else {
59 writer.AppendLine("\t\tNo Table Entries") 59 demo.Writer.AppendLine("\t\tNo Table Entries")
60 } 60 }
61 if reader.TryReadBool() { 61 if reader.TryReadBool() {
62 classCount := reader.TryReadBits(16) 62 classCount := reader.TryReadBits(16)
@@ -64,28 +64,28 @@ func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) {
64 64
65 for i := 0; i < int(classCount); i++ { 65 for i := 0; i < int(classCount); i++ {
66 var class StringTableClass 66 var class StringTableClass
67 class.Parse(reader) 67 class.Parse(reader, demo)
68 stringTable.Classes[i] = class 68 stringTable.Classes[i] = class
69 } 69 }
70 writer.AppendLine("\t\t%d Classes:", classCount) 70 demo.Writer.AppendLine("\t\t%d Classes:", classCount)
71 writer.AppendOutputFromTemp() 71 demo.Writer.AppendOutputFromTemp()
72 } else { 72 } else {
73 writer.AppendLine("\t\tNo Class Entries") 73 demo.Writer.AppendLine("\t\tNo Class Entries")
74 } 74 }
75} 75}
76 76
77func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader) { 77func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader, demo *types.Demo) {
78 stringTableClass.Name = reader.TryReadString() 78 stringTableClass.Name = reader.TryReadString()
79 writer.TempAppendLine("\t\t\tName: %s", stringTableClass.Name) 79 demo.Writer.TempAppendLine("\t\t\tName: %s", stringTableClass.Name)
80 if reader.TryReadBool() { 80 if reader.TryReadBool() {
81 stringTableClass.Data = reader.TryReadStringLength(uint64(reader.TryReadUInt16())) 81 stringTableClass.Data = reader.TryReadStringLength(uint64(reader.TryReadUInt16()))
82 writer.TempAppendLine("\t\t\tData: %s", stringTableClass.Data) 82 demo.Writer.TempAppendLine("\t\t\tData: %s", stringTableClass.Data)
83 } 83 }
84} 84}
85 85
86func (stringTableEntry *StringTableEntry) Parse(tableName string, reader *bitreader.Reader) { 86func (stringTableEntry *StringTableEntry) Parse(tableName string, reader *bitreader.Reader, demo *types.Demo) {
87 stringTableEntry.Name = reader.TryReadString() 87 stringTableEntry.Name = reader.TryReadString()
88 writer.TempAppendLine("\t\t\tName: %s", stringTableEntry.Name) 88 demo.Writer.TempAppendLine("\t\t\tName: %s", stringTableEntry.Name)
89 if reader.TryReadBool() { 89 if reader.TryReadBool() {
90 byteLen, err := reader.ReadBits(16) 90 byteLen, err := reader.ReadBits(16)
91 if err != nil { 91 if err != nil {
@@ -94,30 +94,30 @@ func (stringTableEntry *StringTableEntry) Parse(tableName string, reader *bitrea
94 stringTableEntryReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(byteLen), true) 94 stringTableEntryReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(byteLen), true)
95 switch tableName { 95 switch tableName {
96 case StringTableUserInfo: 96 case StringTableUserInfo:
97 stringTableEntry.ParseUserInfo(stringTableEntryReader) 97 stringTableEntry.ParseUserInfo(stringTableEntryReader, demo)
98 case StringTableServerQueryInfo: 98 case StringTableServerQueryInfo:
99 stringTableEntry.ParseServerQueryInfo(stringTableEntryReader) 99 stringTableEntry.ParseServerQueryInfo(stringTableEntryReader, demo)
100 case StringTableGameRulesCreation: 100 case StringTableGameRulesCreation:
101 stringTableEntry.ParseGamesRulesCreation(stringTableEntryReader) 101 stringTableEntry.ParseGamesRulesCreation(stringTableEntryReader, demo)
102 case StringTableInfoPanel: 102 case StringTableInfoPanel:
103 stringTableEntry.ParseInfoPanel(stringTableEntryReader) 103 stringTableEntry.ParseInfoPanel(stringTableEntryReader, demo)
104 case StringTableLightStyles: 104 case StringTableLightStyles:
105 stringTableEntry.ParseLightStyles(stringTableEntryReader) 105 stringTableEntry.ParseLightStyles(stringTableEntryReader, demo)
106 case StringTableModelPreCache: 106 case StringTableModelPreCache:
107 stringTableEntry.ParsePrecacheData(stringTableEntryReader) 107 stringTableEntry.ParsePrecacheData(stringTableEntryReader, demo)
108 case StringTableGenericPreCache: 108 case StringTableGenericPreCache:
109 stringTableEntry.ParsePrecacheData(stringTableEntryReader) 109 stringTableEntry.ParsePrecacheData(stringTableEntryReader, demo)
110 case StringTableSoundPreCache: 110 case StringTableSoundPreCache:
111 stringTableEntry.ParsePrecacheData(stringTableEntryReader) 111 stringTableEntry.ParsePrecacheData(stringTableEntryReader, demo)
112 case StringTableDecalPreCache: 112 case StringTableDecalPreCache:
113 stringTableEntry.ParsePrecacheData(stringTableEntryReader) 113 stringTableEntry.ParsePrecacheData(stringTableEntryReader, demo)
114 default: 114 default:
115 stringTableEntry.ParseUnknown(stringTableEntryReader) 115 stringTableEntry.ParseUnknown(stringTableEntryReader, demo)
116 } 116 }
117 } 117 }
118} 118}
119 119
120func (stringTableEntry *StringTableEntry) ParseUserInfo(reader *bitreader.Reader) { 120func (stringTableEntry *StringTableEntry) ParseUserInfo(reader *bitreader.Reader, demo *types.Demo) {
121 const SignedGuidLen int32 = 32 121 const SignedGuidLen int32 = 32
122 const MaxPlayerNameLength int32 = 32 122 const MaxPlayerNameLength int32 = 32
123 userInfo := struct { 123 userInfo := struct {
@@ -147,48 +147,48 @@ func (stringTableEntry *StringTableEntry) ParseUserInfo(reader *bitreader.Reader
147 userInfo.FilesDownloaded = reader.TryReadUInt8() 147 userInfo.FilesDownloaded = reader.TryReadUInt8()
148 reader.SkipBytes(3) 148 reader.SkipBytes(3)
149 stringTableEntry.EntryData = userInfo 149 stringTableEntry.EntryData = userInfo
150 writer.TempAppendLine("\t\t\t\tSteam Account ID: %d", uint32((userInfo.SteamID&0xFFFFFFFF00000000)|userInfo.SteamID)) 150 demo.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) 151 demo.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) 152 demo.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) 153 demo.Writer.TempAppendLine("\t\t\t\tSteam Account Universe: %d", uint32(userInfo.SteamID>>56)&0xFF)
154 writer.TempAppendLine("\t\t\t\tName: %s", userInfo.Name) 154 demo.Writer.TempAppendLine("\t\t\t\tName: %s", userInfo.Name)
155 writer.TempAppendLine("\t\t\t\tUser ID: %d", userInfo.UserID) 155 demo.Writer.TempAppendLine("\t\t\t\tUser ID: %d", userInfo.UserID)
156 writer.TempAppendLine("\t\t\t\tGUID: %s", userInfo.GUID) 156 demo.Writer.TempAppendLine("\t\t\t\tGUID: %s", userInfo.GUID)
157 writer.TempAppendLine("\t\t\t\tFriends ID: %d", userInfo.FriendsID) 157 demo.Writer.TempAppendLine("\t\t\t\tFriends ID: %d", userInfo.FriendsID)
158 writer.TempAppendLine("\t\t\t\tFriends Name: %s", userInfo.FriendsName) 158 demo.Writer.TempAppendLine("\t\t\t\tFriends Name: %s", userInfo.FriendsName)
159 writer.TempAppendLine("\t\t\t\tFake Player: %t", userInfo.FakePlayer) 159 demo.Writer.TempAppendLine("\t\t\t\tFake Player: %t", userInfo.FakePlayer)
160 writer.TempAppendLine("\t\t\t\tIs Htlv: %t", userInfo.IsHltv) 160 demo.Writer.TempAppendLine("\t\t\t\tIs Htlv: %t", userInfo.IsHltv)
161 if userInfo.CustomFiles != nil { 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]) 162 demo.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])
163 } 163 }
164 writer.TempAppendLine("\t\t\t\tFiles Downloaded: %d", userInfo.FilesDownloaded) 164 demo.Writer.TempAppendLine("\t\t\t\tFiles Downloaded: %d", userInfo.FilesDownloaded)
165} 165}
166 166
167func (stringTableEntry *StringTableEntry) ParseServerQueryInfo(reader *bitreader.Reader) { 167func (stringTableEntry *StringTableEntry) ParseServerQueryInfo(reader *bitreader.Reader, demo *types.Demo) {
168 serverQueryInfo := struct{ Port uint32 }{ 168 serverQueryInfo := struct{ Port uint32 }{
169 Port: reader.TryReadUInt32(), 169 Port: reader.TryReadUInt32(),
170 } 170 }
171 stringTableEntry.EntryData = serverQueryInfo 171 stringTableEntry.EntryData = serverQueryInfo
172 writer.TempAppendLine("\t\t\t\tPort: %d", serverQueryInfo.Port) 172 demo.Writer.TempAppendLine("\t\t\t\tPort: %d", serverQueryInfo.Port)
173} 173}
174 174
175func (stringTableEntry *StringTableEntry) ParseGamesRulesCreation(reader *bitreader.Reader) { 175func (stringTableEntry *StringTableEntry) ParseGamesRulesCreation(reader *bitreader.Reader, demo *types.Demo) {
176 gamesRulesCreation := struct{ Message string }{ 176 gamesRulesCreation := struct{ Message string }{
177 Message: reader.TryReadString(), 177 Message: reader.TryReadString(),
178 } 178 }
179 stringTableEntry.EntryData = gamesRulesCreation 179 stringTableEntry.EntryData = gamesRulesCreation
180 writer.TempAppendLine("\t\t\t\tMessage: %s", gamesRulesCreation.Message) 180 demo.Writer.TempAppendLine("\t\t\t\tMessage: %s", gamesRulesCreation.Message)
181} 181}
182 182
183func (stringTableEntry *StringTableEntry) ParseInfoPanel(reader *bitreader.Reader) { 183func (stringTableEntry *StringTableEntry) ParseInfoPanel(reader *bitreader.Reader, demo *types.Demo) {
184 infoPanel := struct{ Message string }{ 184 infoPanel := struct{ Message string }{
185 Message: reader.TryReadString(), 185 Message: reader.TryReadString(),
186 } 186 }
187 stringTableEntry.EntryData = infoPanel 187 stringTableEntry.EntryData = infoPanel
188 writer.TempAppendLine("\t\t\t\tMessage: %s", infoPanel.Message) 188 demo.Writer.TempAppendLine("\t\t\t\tMessage: %s", infoPanel.Message)
189} 189}
190 190
191func (stringTableEntry *StringTableEntry) ParseLightStyles(reader *bitreader.Reader) { 191func (stringTableEntry *StringTableEntry) ParseLightStyles(reader *bitreader.Reader, demo *types.Demo) {
192 lightStyles := struct{ Values []byte }{} 192 lightStyles := struct{ Values []byte }{}
193 str := reader.TryReadString() 193 str := reader.TryReadString()
194 if len(str) != 0 { 194 if len(str) != 0 {
@@ -199,13 +199,13 @@ func (stringTableEntry *StringTableEntry) ParseLightStyles(reader *bitreader.Rea
199 } 199 }
200 stringTableEntry.EntryData = lightStyles 200 stringTableEntry.EntryData = lightStyles
201 if lightStyles.Values == nil { 201 if lightStyles.Values == nil {
202 writer.TempAppendLine("\t\t\t\t0 Frames (256)") 202 demo.Writer.TempAppendLine("\t\t\t\t0 Frames (256)")
203 } else { 203 } else {
204 writer.TempAppendLine("\t\t\t\t%d frames: %v", len(lightStyles.Values), lightStyles.Values) 204 demo.Writer.TempAppendLine("\t\t\t\t%d frames: %v", len(lightStyles.Values), lightStyles.Values)
205 } 205 }
206} 206}
207 207
208func (stringTableEntry *StringTableEntry) ParsePrecacheData(reader *bitreader.Reader) { 208func (stringTableEntry *StringTableEntry) ParsePrecacheData(reader *bitreader.Reader, demo *types.Demo) {
209 type PrecacheFlag uint16 209 type PrecacheFlag uint16
210 const ( 210 const (
211 None PrecacheFlag = 0 211 None PrecacheFlag = 0
@@ -225,16 +225,16 @@ func (stringTableEntry *StringTableEntry) ParsePrecacheData(reader *bitreader.Re
225 } 225 }
226 return flagStrings 226 return flagStrings
227 } 227 }
228 writer.TempAppendLine("\t\t\t\tFlags: %v", getFlags(PrecacheFlag(precacheData.Flags))) 228 demo.Writer.TempAppendLine("\t\t\t\tFlags: %v", getFlags(PrecacheFlag(precacheData.Flags)))
229} 229}
230 230
231func (stringTableEntry *StringTableEntry) ParseUnknown(reader *bitreader.Reader) { 231func (stringTableEntry *StringTableEntry) ParseUnknown(reader *bitreader.Reader, demo *types.Demo) {
232 unknown := reader.TryReadBitsToSlice(reader.TryReadRemainingBits()) 232 unknown := reader.TryReadBitsToSlice(reader.TryReadRemainingBits())
233 binaryString := "" 233 binaryString := ""
234 for _, byteValue := range unknown { 234 for _, byteValue := range unknown {
235 binaryString += fmt.Sprintf("%08b ", byteValue) 235 binaryString += fmt.Sprintf("%08b ", byteValue)
236 } 236 }
237 writer.TempAppendLine("\t\t\t\tUnknown: (%s)", strings.TrimSpace(binaryString)) 237 demo.Writer.TempAppendLine("\t\t\t\tUnknown: (%s)", strings.TrimSpace(binaryString))
238} 238}
239 239
240const ( 240const (
diff --git a/pkg/classes/userCmd.go b/pkg/classes/userCmd.go
index dc0b56d..14ef4e0 100644
--- a/pkg/classes/userCmd.go
+++ b/pkg/classes/userCmd.go
@@ -2,40 +2,40 @@ package classes
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type UserCmd struct { 8type UserCmd struct {
9 Cmd uint32 9 Cmd uint32 `json:"cmd"`
10 Size uint32 10 Size uint32 `json:"size"`
11 Data UserCmdInfo 11 Data UserCmdInfo `json:"data"`
12} 12}
13 13
14type UserCmdInfo struct { 14type UserCmdInfo struct {
15 CommandNumber uint32 15 CommandNumber uint32 `json:"command_number"`
16 TickCount uint32 16 TickCount uint32 `json:"tick_count"`
17 ViewAnglesX float32 17 ViewAnglesX float32 `json:"view_angles_x"`
18 ViewAnglesY float32 18 ViewAnglesY float32 `json:"view_angles_y"`
19 ViewAnglesZ float32 19 ViewAnglesZ float32 `json:"view_angles_z"`
20 ForwardMove float32 20 ForwardMove float32 `json:"forward_move"`
21 SideMove float32 21 SideMove float32 `json:"side_move"`
22 UpMove float32 22 UpMove float32 `json:"up_move"`
23 Buttons uint32 23 Buttons uint32 `json:"buttons"`
24 Impulse uint8 24 Impulse uint8 `json:"impulse"`
25 WeaponSelect uint16 25 WeaponSelect uint16 `json:"weapon_select"`
26 WeaponSubType uint8 26 WeaponSubType uint8 `json:"weapon_sub_type"`
27 MouseDx uint16 27 MouseDx uint16 `json:"mouse_dx"`
28 MouseDy uint16 28 MouseDy uint16 `json:"mouse_dy"`
29} 29}
30 30
31func (userCmd *UserCmd) ParseUserCmd(reader *bitreader.Reader) { 31func (userCmd *UserCmd) ParseUserCmd(reader *bitreader.Reader, demo *types.Demo) {
32 userCmd.Cmd = reader.TryReadUInt32() 32 userCmd.Cmd = reader.TryReadUInt32()
33 userCmd.Size = reader.TryReadUInt32() 33 userCmd.Size = reader.TryReadUInt32()
34 userCmdReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(userCmd.Size)), true) 34 userCmdReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(uint64(userCmd.Size)), true)
35 userCmd.ParseUserCmdInfo(userCmdReader) 35 userCmd.ParseUserCmdInfo(userCmdReader, demo)
36} 36}
37 37
38func (userCmd *UserCmd) ParseUserCmdInfo(reader *bitreader.Reader) { 38func (userCmd *UserCmd) ParseUserCmdInfo(reader *bitreader.Reader, demo *types.Demo) {
39 if reader.TryReadBool() { 39 if reader.TryReadBool() {
40 userCmd.Data.CommandNumber = reader.TryReadUInt32() 40 userCmd.Data.CommandNumber = reader.TryReadUInt32()
41 } 41 }
@@ -78,14 +78,14 @@ func (userCmd *UserCmd) ParseUserCmdInfo(reader *bitreader.Reader) {
78 if reader.TryReadBool() { 78 if reader.TryReadBool() {
79 userCmd.Data.MouseDy = reader.TryReadUInt16() 79 userCmd.Data.MouseDy = reader.TryReadUInt16()
80 } 80 }
81 writer.AppendLine("\tCommand Number: %v", userCmd.Data.CommandNumber) 81 demo.Writer.AppendLine("\tCommand Number: %v", userCmd.Data.CommandNumber)
82 writer.AppendLine("\tTick Count: %v", userCmd.Data.TickCount) 82 demo.Writer.AppendLine("\tTick Count: %v", userCmd.Data.TickCount)
83 writer.AppendLine("\tView Angles: %v", []float32{userCmd.Data.ViewAnglesX, userCmd.Data.ViewAnglesY, userCmd.Data.ViewAnglesZ}) 83 demo.Writer.AppendLine("\tView Angles: %v", []float32{userCmd.Data.ViewAnglesX, userCmd.Data.ViewAnglesY, userCmd.Data.ViewAnglesZ})
84 writer.AppendLine("\tMovement: %v", []float32{userCmd.Data.ForwardMove, userCmd.Data.SideMove, userCmd.Data.UpMove}) 84 demo.Writer.AppendLine("\tMovement: %v", []float32{userCmd.Data.ForwardMove, userCmd.Data.SideMove, userCmd.Data.UpMove})
85 writer.AppendLine("\tButtons: %v", Buttons(userCmd.Data.Buttons).GetButtons()) 85 demo.Writer.AppendLine("\tButtons: %v", Buttons(userCmd.Data.Buttons).GetButtons())
86 writer.AppendLine("\tImpulse: %v", userCmd.Data.Impulse) 86 demo.Writer.AppendLine("\tImpulse: %v", userCmd.Data.Impulse)
87 writer.AppendLine("\tWeapon, Subtype: %v, %v", userCmd.Data.WeaponSelect, userCmd.Data.WeaponSubType) 87 demo.Writer.AppendLine("\tWeapon, Subtype: %v, %v", userCmd.Data.WeaponSelect, userCmd.Data.WeaponSubType)
88 writer.AppendLine("\tMouse Dx, Mouse Dy: %v, %v", userCmd.Data.MouseDx, userCmd.Data.MouseDy) 88 demo.Writer.AppendLine("\tMouse Dx, Mouse Dy: %v, %v", userCmd.Data.MouseDx, userCmd.Data.MouseDy)
89} 89}
90 90
91func (button Buttons) GetButtons() []string { 91func (button Buttons) GetButtons() []string {
diff --git a/pkg/messages/messages.go b/pkg/messages/messages.go
index 0dca169..1c6cf1f 100644
--- a/pkg/messages/messages.go
+++ b/pkg/messages/messages.go
@@ -5,84 +5,84 @@ import (
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 messages "github.com/pektezol/sdp.go/pkg/messages/types" 7 messages "github.com/pektezol/sdp.go/pkg/messages/types"
8 "github.com/pektezol/sdp.go/pkg/writer" 8 types "github.com/pektezol/sdp.go/pkg/types"
9) 9)
10 10
11func ParseMessages(messageType uint64, reader *bitreader.Reader) any { 11func ParseMessages(messageType uint64, reader *bitreader.Reader, demo *types.Demo) any {
12 var messageData any 12 var messageData any
13 switch messageType { 13 switch messageType {
14 case 0: 14 case 0:
15 messageData = messages.ParseNetNop(reader) 15 messageData = messages.ParseNetNop(reader, demo)
16 case 1: 16 case 1:
17 messageData = messages.ParseNetDisconnect(reader) 17 messageData = messages.ParseNetDisconnect(reader, demo)
18 case 2: 18 case 2:
19 messageData = messages.ParseNetFile(reader) 19 messageData = messages.ParseNetFile(reader, demo)
20 case 3: 20 case 3:
21 messageData = messages.ParseNetSplitScreenUser(reader) 21 messageData = messages.ParseNetSplitScreenUser(reader, demo)
22 case 4: 22 case 4:
23 messageData = messages.ParseNetTick(reader) 23 messageData = messages.ParseNetTick(reader, demo)
24 case 5: 24 case 5:
25 messageData = messages.ParseNetStringCmd(reader) 25 messageData = messages.ParseNetStringCmd(reader, demo)
26 case 6: 26 case 6:
27 messageData = messages.ParseNetSetConVar(reader) 27 messageData = messages.ParseNetSetConVar(reader, demo)
28 case 7: 28 case 7:
29 messageData = messages.ParseNetSignOnState(reader) 29 messageData = messages.ParseNetSignOnState(reader, demo)
30 case 8: 30 case 8:
31 messageData = messages.ParseSvcServerInfo(reader) 31 messageData = messages.ParseSvcServerInfo(reader, demo)
32 case 9: 32 case 9:
33 messageData = messages.ParseSvcSendTable(reader) 33 messageData = messages.ParseSvcSendTable(reader, demo)
34 case 10: 34 case 10:
35 messageData = messages.ParseSvcClassInfo(reader) 35 messageData = messages.ParseSvcClassInfo(reader, demo)
36 case 11: 36 case 11:
37 messageData = messages.ParseSvcSetPause(reader) 37 messageData = messages.ParseSvcSetPause(reader, demo)
38 case 12: 38 case 12:
39 messageData = messages.ParseSvcCreateStringTable(reader) // TODO: 39 messageData = messages.ParseSvcCreateStringTable(reader, demo) // TODO:
40 case 13: 40 case 13:
41 messageData = messages.ParseSvcUpdateStringTable(reader) // TODO: 41 messageData = messages.ParseSvcUpdateStringTable(reader, demo) // TODO:
42 case 14: 42 case 14:
43 messageData = messages.ParseSvcVoiceInit(reader) 43 messageData = messages.ParseSvcVoiceInit(reader, demo)
44 case 15: 44 case 15:
45 messageData = messages.ParseSvcVoiceData(reader) 45 messageData = messages.ParseSvcVoiceData(reader, demo)
46 case 16: 46 case 16:
47 messageData = messages.ParseSvcPrint(reader) 47 messageData = messages.ParseSvcPrint(reader, demo)
48 case 17: 48 case 17:
49 messageData = messages.ParseSvcSounds(reader) // TODO: 49 messageData = messages.ParseSvcSounds(reader, demo) // TODO:
50 case 18: 50 case 18:
51 messageData = messages.ParseSvcSetView(reader) 51 messageData = messages.ParseSvcSetView(reader, demo)
52 case 19: 52 case 19:
53 messageData = messages.ParseSvcFixAngle(reader) 53 messageData = messages.ParseSvcFixAngle(reader, demo)
54 case 20: 54 case 20:
55 messageData = messages.ParseSvcCrosshairAngle(reader) 55 messageData = messages.ParseSvcCrosshairAngle(reader, demo)
56 case 21: 56 case 21:
57 messageData = messages.ParseSvcBspDecal(reader) // untested 57 messageData = messages.ParseSvcBspDecal(reader, demo) // untested
58 case 22: 58 case 22:
59 messageData = messages.ParseSvcSplitScreen(reader) // skipped 59 messageData = messages.ParseSvcSplitScreen(reader, demo) // skipped
60 case 23: 60 case 23:
61 messageData = messages.ParseSvcUserMessage(reader) 61 messageData = messages.ParseSvcUserMessage(reader, demo)
62 case 24: 62 case 24:
63 messageData = messages.ParseSvcEntityMessage(reader) // skipped 63 messageData = messages.ParseSvcEntityMessage(reader, demo) // skipped
64 case 25: 64 case 25:
65 messageData = messages.ParseSvcGameEvent(reader) 65 messageData = messages.ParseSvcGameEvent(reader, demo)
66 case 26: 66 case 26:
67 messageData = messages.ParseSvcPacketEntities(reader) // TODO: 67 messageData = messages.ParseSvcPacketEntities(reader, demo) // TODO:
68 case 27: 68 case 27:
69 messageData = messages.ParseSvcTempEntities(reader) // skipped 69 messageData = messages.ParseSvcTempEntities(reader, demo) // skipped
70 case 28: 70 case 28:
71 messageData = messages.ParseSvcPrefetch(reader) 71 messageData = messages.ParseSvcPrefetch(reader, demo)
72 case 29: 72 case 29:
73 messageData = messages.ParseSvcMenu(reader) // skipped 73 messageData = messages.ParseSvcMenu(reader, demo) // skipped
74 case 30: 74 case 30:
75 messageData = messages.ParseSvcGameEventList(reader) 75 messageData = messages.ParseSvcGameEventList(reader, demo)
76 case 31: 76 case 31:
77 messageData = messages.ParseSvcGetCvarValue(reader) 77 messageData = messages.ParseSvcGetCvarValue(reader, demo)
78 case 32: 78 case 32:
79 messageData = messages.ParseSvcCmdKeyValues(reader) 79 messageData = messages.ParseSvcCmdKeyValues(reader, demo)
80 case 33: 80 case 33:
81 messageData = messages.ParseSvcPaintmapData(reader) // skipped 81 messageData = messages.ParseSvcPaintmapData(reader, demo) // skipped
82 default: 82 default:
83 return nil 83 return nil
84 } 84 }
85 writer.AppendLine("\tMessage: %s (%d):", reflect.ValueOf(messageData).Type(), messageType) 85 demo.Writer.AppendLine("\tMessage: %s (%d):", reflect.ValueOf(messageData).Type(), messageType)
86 writer.AppendOutputFromTemp() 86 demo.Writer.AppendOutputFromTemp()
87 return messageData 87 return messageData
88} 88}
diff --git a/pkg/messages/types/netDisconnect.go b/pkg/messages/types/netDisconnect.go
index c3c857e..c8514c0 100644
--- a/pkg/messages/types/netDisconnect.go
+++ b/pkg/messages/types/netDisconnect.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type NetDisconnect struct { 8type NetDisconnect struct {
9 Text string 9 Text string `json:"text"`
10} 10}
11 11
12func ParseNetDisconnect(reader *bitreader.Reader) NetDisconnect { 12func ParseNetDisconnect(reader *bitreader.Reader, demo *types.Demo) NetDisconnect {
13 netDisconnect := NetDisconnect{ 13 netDisconnect := NetDisconnect{
14 Text: reader.TryReadString(), 14 Text: reader.TryReadString(),
15 } 15 }
16 writer.TempAppendLine("\t\tText: %s", netDisconnect.Text) 16 demo.Writer.TempAppendLine("\t\tText: %s", netDisconnect.Text)
17 return netDisconnect 17 return netDisconnect
18} 18}
diff --git a/pkg/messages/types/netFile.go b/pkg/messages/types/netFile.go
index e74cdb3..837a4c0 100644
--- a/pkg/messages/types/netFile.go
+++ b/pkg/messages/types/netFile.go
@@ -4,13 +4,13 @@ import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type NetFile struct { 10type NetFile struct {
11 TransferId uint32 11 TransferId uint32 `json:"transfer_id"`
12 FileName string 12 FileName string `json:"file_name"`
13 FileFlags string 13 FileFlags string `json:"file_flags"`
14} 14}
15 15
16type NetFileFlags int 16type NetFileFlags int
@@ -34,14 +34,14 @@ func (netFileFlags NetFileFlags) String() string {
34 } 34 }
35} 35}
36 36
37func ParseNetFile(reader *bitreader.Reader) NetFile { 37func ParseNetFile(reader *bitreader.Reader, demo *types.Demo) NetFile {
38 netFile := NetFile{ 38 netFile := NetFile{
39 TransferId: reader.TryReadUInt32(), 39 TransferId: reader.TryReadUInt32(),
40 FileName: reader.TryReadString(), 40 FileName: reader.TryReadString(),
41 FileFlags: NetFileFlags(reader.TryReadBits(2)).String(), 41 FileFlags: NetFileFlags(reader.TryReadBits(2)).String(),
42 } 42 }
43 writer.TempAppendLine("\t\tTransfer ID: %d", netFile.TransferId) 43 demo.Writer.TempAppendLine("\t\tTransfer ID: %d", netFile.TransferId)
44 writer.TempAppendLine("\t\tFile Name: %s", netFile.FileName) 44 demo.Writer.TempAppendLine("\t\tFile Name: %s", netFile.FileName)
45 writer.TempAppendLine("\t\tFile Flags: %s", netFile.FileFlags) 45 demo.Writer.TempAppendLine("\t\tFile Flags: %s", netFile.FileFlags)
46 return netFile 46 return netFile
47} 47}
diff --git a/pkg/messages/types/netNop.go b/pkg/messages/types/netNop.go
index c7ba66c..5405659 100644
--- a/pkg/messages/types/netNop.go
+++ b/pkg/messages/types/netNop.go
@@ -2,12 +2,12 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type NetNop struct{} 8type NetNop struct{}
9 9
10func ParseNetNop(reader *bitreader.Reader) NetNop { 10func ParseNetNop(reader *bitreader.Reader, demo *types.Demo) NetNop {
11 writer.TempAppendLine("\t\t{}") 11 demo.Writer.TempAppendLine("\t\t{}")
12 return NetNop{} 12 return NetNop{}
13} 13}
diff --git a/pkg/messages/types/netSetConVar.go b/pkg/messages/types/netSetConVar.go
index e9902b5..0c62fdd 100644
--- a/pkg/messages/types/netSetConVar.go
+++ b/pkg/messages/types/netSetConVar.go
@@ -2,29 +2,29 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type NetSetConVar struct { 8type NetSetConVar struct {
9 Length uint8 9 Length uint8 `json:"length"`
10 ConVars []conVar 10 ConVars []conVar `json:"con_vars"`
11} 11}
12 12
13type conVar struct { 13type conVar struct {
14 Name string 14 Name string `json:"name"`
15 Value string 15 Value string `json:"value"`
16} 16}
17 17
18func ParseNetSetConVar(reader *bitreader.Reader) NetSetConVar { 18func ParseNetSetConVar(reader *bitreader.Reader, demo *types.Demo) NetSetConVar {
19 length := reader.TryReadUInt8() 19 length := reader.TryReadUInt8()
20 convars := []conVar{} 20 convars := []conVar{}
21 writer.TempAppendLine("\t\tLength: %d", length) 21 demo.Writer.TempAppendLine("\t\tLength: %d", length)
22 for count := 0; count < int(length); count++ { 22 for count := 0; count < int(length); count++ {
23 convar := conVar{ 23 convar := conVar{
24 Name: reader.TryReadString(), 24 Name: reader.TryReadString(),
25 Value: reader.TryReadString(), 25 Value: reader.TryReadString(),
26 } 26 }
27 writer.TempAppendLine("\t\t[%d] %s: %s", count, convar.Name, convar.Value) 27 demo.Writer.TempAppendLine("\t\t[%d] %s: %s", count, convar.Name, convar.Value)
28 convars = append(convars, convar) 28 convars = append(convars, convar)
29 } 29 }
30 return NetSetConVar{ 30 return NetSetConVar{
diff --git a/pkg/messages/types/netSignOnState.go b/pkg/messages/types/netSignOnState.go
index e25eaed..0043465 100644
--- a/pkg/messages/types/netSignOnState.go
+++ b/pkg/messages/types/netSignOnState.go
@@ -4,17 +4,17 @@ import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type NetSignOnState struct { 10type NetSignOnState struct {
11 SignOnState string 11 SignOnState string `json:"sign_on_state"`
12 SpawnCount int32 12 SpawnCount int32 `json:"spawn_count"`
13 NumServerPlayers uint32 13 NumServerPlayers uint32 `json:"num_server_players"`
14 IdsLength uint32 14 IdsLength uint32 `json:"ids_length"`
15 PlayersNetworksIds []byte 15 PlayersNetworksIds []byte `json:"players_networks_ids"`
16 MapNameLength uint32 16 MapNameLength uint32 `json:"map_name_length"`
17 MapName string 17 MapName string `json:"map_name"`
18} 18}
19 19
20type SignOnState int 20type SignOnState int
@@ -53,24 +53,24 @@ func (signOnState SignOnState) String() string {
53 } 53 }
54} 54}
55 55
56func ParseNetSignOnState(reader *bitreader.Reader) NetSignOnState { 56func ParseNetSignOnState(reader *bitreader.Reader, demo *types.Demo) NetSignOnState {
57 netSignOnState := NetSignOnState{ 57 netSignOnState := NetSignOnState{
58 SignOnState: SignOnState(reader.TryReadUInt8()).String(), 58 SignOnState: SignOnState(reader.TryReadUInt8()).String(),
59 SpawnCount: reader.TryReadSInt32(), 59 SpawnCount: reader.TryReadSInt32(),
60 NumServerPlayers: reader.TryReadUInt32(), 60 NumServerPlayers: reader.TryReadUInt32(),
61 IdsLength: reader.TryReadUInt32(), 61 IdsLength: reader.TryReadUInt32(),
62 } 62 }
63 writer.TempAppendLine("\t\tSign On State: %s", netSignOnState.SignOnState) 63 demo.Writer.TempAppendLine("\t\tSign On State: %s", netSignOnState.SignOnState)
64 writer.TempAppendLine("\t\tSpawn Count: %d", netSignOnState.SpawnCount) 64 demo.Writer.TempAppendLine("\t\tSpawn Count: %d", netSignOnState.SpawnCount)
65 writer.TempAppendLine("\t\tNumber Of Server Players: %d", netSignOnState.NumServerPlayers) 65 demo.Writer.TempAppendLine("\t\tNumber Of Server Players: %d", netSignOnState.NumServerPlayers)
66 if netSignOnState.IdsLength > 0 { 66 if netSignOnState.IdsLength > 0 {
67 netSignOnState.PlayersNetworksIds = reader.TryReadBytesToSlice(uint64(netSignOnState.IdsLength)) 67 netSignOnState.PlayersNetworksIds = reader.TryReadBytesToSlice(uint64(netSignOnState.IdsLength))
68 writer.TempAppendLine("\t\tPlayer Network IDs: %v", netSignOnState.PlayersNetworksIds) 68 demo.Writer.TempAppendLine("\t\tPlayer Network IDs: %v", netSignOnState.PlayersNetworksIds)
69 } 69 }
70 netSignOnState.MapNameLength = reader.TryReadUInt32() 70 netSignOnState.MapNameLength = reader.TryReadUInt32()
71 if netSignOnState.MapNameLength > 0 { 71 if netSignOnState.MapNameLength > 0 {
72 netSignOnState.MapName = reader.TryReadStringLength(uint64(netSignOnState.MapNameLength)) 72 netSignOnState.MapName = reader.TryReadStringLength(uint64(netSignOnState.MapNameLength))
73 writer.TempAppendLine("\t\tMap Name: %s", netSignOnState.MapName) 73 demo.Writer.TempAppendLine("\t\tMap Name: %s", netSignOnState.MapName)
74 } 74 }
75 return netSignOnState 75 return netSignOnState
76} 76}
diff --git a/pkg/messages/types/netSplitScreenUser.go b/pkg/messages/types/netSplitScreenUser.go
index 535552a..691c723 100644
--- a/pkg/messages/types/netSplitScreenUser.go
+++ b/pkg/messages/types/netSplitScreenUser.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type NetSplitScreenUser struct { 8type NetSplitScreenUser struct {
9 Slot bool 9 Slot bool `json:"slot"`
10} 10}
11 11
12func ParseNetSplitScreenUser(reader *bitreader.Reader) NetSplitScreenUser { 12func ParseNetSplitScreenUser(reader *bitreader.Reader, demo *types.Demo) NetSplitScreenUser {
13 netSplitScreenUser := NetSplitScreenUser{ 13 netSplitScreenUser := NetSplitScreenUser{
14 Slot: reader.TryReadBool(), 14 Slot: reader.TryReadBool(),
15 } 15 }
16 writer.TempAppendLine("\t\tSlot: %t", netSplitScreenUser.Slot) 16 demo.Writer.TempAppendLine("\t\tSlot: %t", netSplitScreenUser.Slot)
17 return netSplitScreenUser 17 return netSplitScreenUser
18} 18}
diff --git a/pkg/messages/types/netStringCmd.go b/pkg/messages/types/netStringCmd.go
index 13d5a13..fb6af2e 100644
--- a/pkg/messages/types/netStringCmd.go
+++ b/pkg/messages/types/netStringCmd.go
@@ -4,17 +4,17 @@ import (
4 "strings" 4 "strings"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type NetStringCmd struct { 10type NetStringCmd struct {
11 Command string 11 Command string `json:"command"`
12} 12}
13 13
14func ParseNetStringCmd(reader *bitreader.Reader) NetStringCmd { 14func ParseNetStringCmd(reader *bitreader.Reader, demo *types.Demo) NetStringCmd {
15 netStringCmd := NetStringCmd{ 15 netStringCmd := NetStringCmd{
16 Command: reader.TryReadString(), 16 Command: reader.TryReadString(),
17 } 17 }
18 writer.TempAppendLine("\t\tCommand: \"%s\"", strings.TrimSpace(netStringCmd.Command)) 18 demo.Writer.TempAppendLine("\t\tCommand: \"%s\"", strings.TrimSpace(netStringCmd.Command))
19 return netStringCmd 19 return netStringCmd
20} 20}
diff --git a/pkg/messages/types/netTick.go b/pkg/messages/types/netTick.go
index 9ef1ce2..0bcbc05 100644
--- a/pkg/messages/types/netTick.go
+++ b/pkg/messages/types/netTick.go
@@ -2,23 +2,23 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type NetTick struct { 8type NetTick struct {
9 Tick uint32 9 Tick uint32 `json:"tick"`
10 HostFrameTime float32 10 HostFrameTime float32 `json:"host_frame_time"`
11 HostFrameTimeStdDeviation float32 11 HostFrameTimeStdDeviation float32 `json:"host_frame_time_std_deviation"`
12} 12}
13 13
14func ParseNetTick(reader *bitreader.Reader) NetTick { 14func ParseNetTick(reader *bitreader.Reader, demo *types.Demo) NetTick {
15 netTick := NetTick{ 15 netTick := NetTick{
16 Tick: reader.TryReadUInt32(), 16 Tick: reader.TryReadUInt32(),
17 HostFrameTime: float32(reader.TryReadUInt16()) / 1e5, 17 HostFrameTime: float32(reader.TryReadUInt16()) / 1e5,
18 HostFrameTimeStdDeviation: float32(reader.TryReadUInt16()) / 1e5, 18 HostFrameTimeStdDeviation: float32(reader.TryReadUInt16()) / 1e5,
19 } 19 }
20 writer.TempAppendLine("\t\tTick: %d", netTick.Tick) 20 demo.Writer.TempAppendLine("\t\tTick: %d", netTick.Tick)
21 writer.TempAppendLine("\t\tHost Frame Time: %f", netTick.HostFrameTime) 21 demo.Writer.TempAppendLine("\t\tHost Frame Time: %f", netTick.HostFrameTime)
22 writer.TempAppendLine("\t\tHost Frame Time Std Deviation: %f", netTick.HostFrameTimeStdDeviation) 22 demo.Writer.TempAppendLine("\t\tHost Frame Time Std Deviation: %f", netTick.HostFrameTimeStdDeviation)
23 return netTick 23 return netTick
24} 24}
diff --git a/pkg/messages/types/svcBspDecal.go b/pkg/messages/types/svcBspDecal.go
index fc5698f..9ef2458 100644
--- a/pkg/messages/types/svcBspDecal.go
+++ b/pkg/messages/types/svcBspDecal.go
@@ -2,23 +2,23 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcBspDecal struct { 8type SvcBspDecal struct {
9 Pos []vectorCoord 9 Pos []vectorCoord `json:"pos"`
10 DecalTextureIndex int16 10 DecalTextureIndex int16 `json:"decal_texture_index"`
11 EntityIndex uint16 11 EntityIndex uint16 `json:"entity_index"`
12 ModelIndex uint16 12 ModelIndex uint16 `json:"model_index"`
13 LowPriority bool 13 LowPriority bool `json:"low_priority"`
14} 14}
15 15
16type vectorCoord struct { 16type vectorCoord struct {
17 Value float32 17 Value float32 `json:"value"`
18 Valid bool 18 Valid bool `json:"valid"`
19} 19}
20 20
21func ParseSvcBspDecal(reader *bitreader.Reader) SvcBspDecal { 21func ParseSvcBspDecal(reader *bitreader.Reader, demo *types.Demo) SvcBspDecal {
22 svcBspDecal := SvcBspDecal{ 22 svcBspDecal := SvcBspDecal{
23 Pos: readVectorCoords(reader), 23 Pos: readVectorCoords(reader),
24 DecalTextureIndex: int16(reader.TryReadBits(9)), 24 DecalTextureIndex: int16(reader.TryReadBits(9)),
@@ -28,11 +28,11 @@ func ParseSvcBspDecal(reader *bitreader.Reader) SvcBspDecal {
28 svcBspDecal.ModelIndex = uint16(reader.TryReadBits(11)) 28 svcBspDecal.ModelIndex = uint16(reader.TryReadBits(11))
29 } 29 }
30 svcBspDecal.LowPriority = reader.TryReadBool() 30 svcBspDecal.LowPriority = reader.TryReadBool()
31 writer.TempAppendLine("\t\tPosition: %v", svcBspDecal.Pos) 31 demo.Writer.TempAppendLine("\t\tPosition: %v", svcBspDecal.Pos)
32 writer.TempAppendLine("\t\tDecal Texture Index: %d", svcBspDecal.DecalTextureIndex) 32 demo.Writer.TempAppendLine("\t\tDecal Texture Index: %d", svcBspDecal.DecalTextureIndex)
33 writer.TempAppendLine("\t\tEntity Index: %d", svcBspDecal.EntityIndex) 33 demo.Writer.TempAppendLine("\t\tEntity Index: %d", svcBspDecal.EntityIndex)
34 writer.TempAppendLine("\t\tModel Index: %d", svcBspDecal.ModelIndex) 34 demo.Writer.TempAppendLine("\t\tModel Index: %d", svcBspDecal.ModelIndex)
35 writer.TempAppendLine("\t\tLow Priority: %t", svcBspDecal.LowPriority) 35 demo.Writer.TempAppendLine("\t\tLow Priority: %t", svcBspDecal.LowPriority)
36 return svcBspDecal 36 return svcBspDecal
37} 37}
38 38
diff --git a/pkg/messages/types/svcClassInfo.go b/pkg/messages/types/svcClassInfo.go
index af382a8..995c61d 100644
--- a/pkg/messages/types/svcClassInfo.go
+++ b/pkg/messages/types/svcClassInfo.go
@@ -4,40 +4,40 @@ import (
4 "math" 4 "math"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type SvcClassInfo struct { 10type SvcClassInfo struct {
11 ClassCount uint16 11 ClassCount uint16 `json:"class_count"`
12 CreateOnClient bool 12 CreateOnClient bool `json:"create_on_client"`
13 ServerClasses []serverClass 13 ServerClasses []serverClass `json:"server_classes"`
14} 14}
15 15
16type serverClass struct { 16type serverClass struct {
17 ClassId int16 17 ClassId int16 `json:"class_id"`
18 ClassName string 18 ClassName string `json:"class_name"`
19 DataTableName string 19 DataTableName string `json:"data_table_name"`
20} 20}
21 21
22func ParseSvcClassInfo(reader *bitreader.Reader) SvcClassInfo { 22func ParseSvcClassInfo(reader *bitreader.Reader, demo *types.Demo) SvcClassInfo {
23 svcClassInfo := SvcClassInfo{ 23 svcClassInfo := SvcClassInfo{
24 ClassCount: reader.TryReadUInt16(), 24 ClassCount: reader.TryReadUInt16(),
25 CreateOnClient: reader.TryReadBool(), 25 CreateOnClient: reader.TryReadBool(),
26 } 26 }
27 classes := []serverClass{} 27 classes := []serverClass{}
28 writer.TempAppendLine("\t\tCreate On Client: %t", svcClassInfo.CreateOnClient) 28 demo.Writer.TempAppendLine("\t\tCreate On Client: %t", svcClassInfo.CreateOnClient)
29 if !svcClassInfo.CreateOnClient { 29 if !svcClassInfo.CreateOnClient {
30 writer.TempAppendLine("\t\t%d Server Classes:", svcClassInfo.ClassCount) 30 demo.Writer.TempAppendLine("\t\t%d Server Classes:", svcClassInfo.ClassCount)
31 for count := 0; count < int(svcClassInfo.ClassCount); count++ { 31 for count := 0; count < int(svcClassInfo.ClassCount); count++ {
32 classes = append(classes, serverClass{ 32 classes = append(classes, serverClass{
33 ClassId: int16(reader.TryReadBits(uint64(math.Log2(float64(svcClassInfo.ClassCount)) + 1))), 33 ClassId: int16(reader.TryReadBits(uint64(math.Log2(float64(svcClassInfo.ClassCount)) + 1))),
34 ClassName: reader.TryReadString(), 34 ClassName: reader.TryReadString(),
35 DataTableName: reader.TryReadString(), 35 DataTableName: reader.TryReadString(),
36 }) 36 })
37 writer.TempAppendLine("\t\t\t[%d] %s (%s)", classes[len(classes)-1].ClassId, classes[len(classes)-1].ClassName, classes[len(classes)-1].DataTableName) 37 demo.Writer.TempAppendLine("\t\t\t[%d] %s (%s)", classes[len(classes)-1].ClassId, classes[len(classes)-1].ClassName, classes[len(classes)-1].DataTableName)
38 } 38 }
39 } else { 39 } else {
40 writer.TempAppendLine("\t\t%d Server Classes", svcClassInfo.ClassCount) 40 demo.Writer.TempAppendLine("\t\t%d Server Classes", svcClassInfo.ClassCount)
41 } 41 }
42 svcClassInfo.ServerClasses = classes 42 svcClassInfo.ServerClasses = classes
43 return svcClassInfo 43 return svcClassInfo
diff --git a/pkg/messages/types/svcCmdKeyValues.go b/pkg/messages/types/svcCmdKeyValues.go
index a5d8f62..6ab9c99 100644
--- a/pkg/messages/types/svcCmdKeyValues.go
+++ b/pkg/messages/types/svcCmdKeyValues.go
@@ -2,19 +2,19 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcCmdKeyValues struct { 8type SvcCmdKeyValues struct {
9 Length uint32 9 Length uint32 `json:"length"`
10 Data []byte 10 Data []byte `json:"data"`
11} 11}
12 12
13func ParseSvcCmdKeyValues(reader *bitreader.Reader) SvcCmdKeyValues { 13func ParseSvcCmdKeyValues(reader *bitreader.Reader, demo *types.Demo) SvcCmdKeyValues {
14 svcCmdKeyValues := SvcCmdKeyValues{ 14 svcCmdKeyValues := SvcCmdKeyValues{
15 Length: reader.TryReadUInt32(), 15 Length: reader.TryReadUInt32(),
16 } 16 }
17 svcCmdKeyValues.Data = reader.TryReadBytesToSlice(uint64(svcCmdKeyValues.Length)) 17 svcCmdKeyValues.Data = reader.TryReadBytesToSlice(uint64(svcCmdKeyValues.Length))
18 writer.TempAppendLine("\t\tData: %v", svcCmdKeyValues.Data) 18 demo.Writer.TempAppendLine("\t\tData: %v", svcCmdKeyValues.Data)
19 return svcCmdKeyValues 19 return svcCmdKeyValues
20} 20}
diff --git a/pkg/messages/types/svcCreateStringTable.go b/pkg/messages/types/svcCreateStringTable.go
index 0fc07cd..9a0c3e0 100644
--- a/pkg/messages/types/svcCreateStringTable.go
+++ b/pkg/messages/types/svcCreateStringTable.go
@@ -4,22 +4,22 @@ import (
4 "math" 4 "math"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type SvcCreateStringTable struct { 10type SvcCreateStringTable struct {
11 Name string 11 Name string `json:"name"`
12 MaxEntries int16 12 MaxEntries int16 `json:"max_entries"`
13 NumEntries int8 13 NumEntries int8 `json:"num_entries"`
14 Length int32 14 Length int32 `json:"length"`
15 UserDataFixedSize bool 15 UserDataFixedSize bool `json:"user_data_fixed_size"`
16 UserDataSize int16 16 UserDataSize int16 `json:"user_data_size"`
17 UserDataSizeBits int8 17 UserDataSizeBits int8 `json:"user_data_size_bits"`
18 Flags int8 18 Flags int8 `json:"flags"`
19 StringData int 19 StringData int `json:"string_data"`
20} 20}
21 21
22func ParseSvcCreateStringTable(reader *bitreader.Reader) SvcCreateStringTable { 22func ParseSvcCreateStringTable(reader *bitreader.Reader, demo *types.Demo) SvcCreateStringTable {
23 svcCreateStringTable := SvcCreateStringTable{ 23 svcCreateStringTable := SvcCreateStringTable{
24 Name: reader.TryReadString(), 24 Name: reader.TryReadString(),
25 MaxEntries: reader.TryReadSInt16(), 25 MaxEntries: reader.TryReadSInt16(),
@@ -32,13 +32,13 @@ func ParseSvcCreateStringTable(reader *bitreader.Reader) SvcCreateStringTable {
32 svcCreateStringTable.UserDataSizeBits = int8(reader.TryReadBits(4)) 32 svcCreateStringTable.UserDataSizeBits = int8(reader.TryReadBits(4))
33 } 33 }
34 svcCreateStringTable.Flags = int8(reader.TryReadBits(2)) 34 svcCreateStringTable.Flags = int8(reader.TryReadBits(2))
35 writer.TempAppendLine("\t\tName: %s", svcCreateStringTable.Name) 35 demo.Writer.TempAppendLine("\t\tName: %s", svcCreateStringTable.Name)
36 writer.TempAppendLine("\t\tMax Enties: %d", svcCreateStringTable.MaxEntries) 36 demo.Writer.TempAppendLine("\t\tMax Enties: %d", svcCreateStringTable.MaxEntries)
37 writer.TempAppendLine("\t\tNumber Of Entiries: %d", svcCreateStringTable.NumEntries) 37 demo.Writer.TempAppendLine("\t\tNumber Of Entiries: %d", svcCreateStringTable.NumEntries)
38 writer.TempAppendLine("\t\tUser Data Fixed Size: %t", svcCreateStringTable.UserDataFixedSize) 38 demo.Writer.TempAppendLine("\t\tUser Data Fixed Size: %t", svcCreateStringTable.UserDataFixedSize)
39 writer.TempAppendLine("\t\tUser Data Size: %d", svcCreateStringTable.UserDataSize) 39 demo.Writer.TempAppendLine("\t\tUser Data Size: %d", svcCreateStringTable.UserDataSize)
40 writer.TempAppendLine("\t\tUser Data Size In Bits: %d", svcCreateStringTable.UserDataSizeBits) 40 demo.Writer.TempAppendLine("\t\tUser Data Size In Bits: %d", svcCreateStringTable.UserDataSizeBits)
41 writer.TempAppendLine("\t\tFlags: %d", svcCreateStringTable.Flags) 41 demo.Writer.TempAppendLine("\t\tFlags: %d", svcCreateStringTable.Flags)
42 reader.SkipBits(uint64(svcCreateStringTable.Length)) // TODO: StringTable parsing 42 reader.SkipBits(uint64(svcCreateStringTable.Length)) // TODO: StringTable parsing
43 return svcCreateStringTable 43 return svcCreateStringTable
44} 44}
diff --git a/pkg/messages/types/svcCrosshairAngle.go b/pkg/messages/types/svcCrosshairAngle.go
index dd57f79..31da616 100644
--- a/pkg/messages/types/svcCrosshairAngle.go
+++ b/pkg/messages/types/svcCrosshairAngle.go
@@ -2,20 +2,20 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcCrosshairAngle struct { 8type SvcCrosshairAngle struct {
9 Angle crosshairAngles 9 Angle crosshairAngles `json:"angle"`
10} 10}
11 11
12type crosshairAngles struct { 12type crosshairAngles struct {
13 X float32 13 X float32 `json:"x"`
14 Y float32 14 Y float32 `json:"y"`
15 Z float32 15 Z float32 `json:"z"`
16} 16}
17 17
18func ParseSvcCrosshairAngle(reader *bitreader.Reader) SvcCrosshairAngle { 18func ParseSvcCrosshairAngle(reader *bitreader.Reader, demo *types.Demo) SvcCrosshairAngle {
19 svcCrosshairAngle := SvcCrosshairAngle{ 19 svcCrosshairAngle := SvcCrosshairAngle{
20 Angle: crosshairAngles{ 20 Angle: crosshairAngles{
21 X: float32(reader.TryReadBits(16)), 21 X: float32(reader.TryReadBits(16)),
@@ -23,8 +23,8 @@ func ParseSvcCrosshairAngle(reader *bitreader.Reader) SvcCrosshairAngle {
23 Z: float32(reader.TryReadBits(16)), 23 Z: float32(reader.TryReadBits(16)),
24 }, 24 },
25 } 25 }
26 writer.TempAppendLine("\t\tX: %f", svcCrosshairAngle.Angle.X) 26 demo.Writer.TempAppendLine("\t\tX: %f", svcCrosshairAngle.Angle.X)
27 writer.TempAppendLine("\t\tY: %f", svcCrosshairAngle.Angle.Y) 27 demo.Writer.TempAppendLine("\t\tY: %f", svcCrosshairAngle.Angle.Y)
28 writer.TempAppendLine("\t\tZ: %f", svcCrosshairAngle.Angle.Z) 28 demo.Writer.TempAppendLine("\t\tZ: %f", svcCrosshairAngle.Angle.Z)
29 return svcCrosshairAngle 29 return svcCrosshairAngle
30} 30}
diff --git a/pkg/messages/types/svcEntityMessage.go b/pkg/messages/types/svcEntityMessage.go
index b955da5..87d7e1b 100644
--- a/pkg/messages/types/svcEntityMessage.go
+++ b/pkg/messages/types/svcEntityMessage.go
@@ -2,25 +2,25 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcEntityMessage struct { 8type SvcEntityMessage struct {
9 EntityIndex uint16 9 EntityIndex uint16 `json:"entity_index"`
10 ClassId uint16 10 ClassId uint16 `json:"class_id"`
11 Length uint16 11 Length uint16 `json:"length"`
12 Data []byte 12 Data []byte `json:"data"`
13} 13}
14 14
15func ParseSvcEntityMessage(reader *bitreader.Reader) SvcEntityMessage { 15func ParseSvcEntityMessage(reader *bitreader.Reader, demo *types.Demo) SvcEntityMessage {
16 svcEntityMessage := SvcEntityMessage{ 16 svcEntityMessage := SvcEntityMessage{
17 EntityIndex: uint16(reader.TryReadBits(11)), 17 EntityIndex: uint16(reader.TryReadBits(11)),
18 ClassId: uint16(reader.TryReadBits(9)), 18 ClassId: uint16(reader.TryReadBits(9)),
19 Length: uint16(reader.TryReadBits(11)), 19 Length: uint16(reader.TryReadBits(11)),
20 } 20 }
21 svcEntityMessage.Data = reader.TryReadBitsToSlice(uint64(svcEntityMessage.Length)) 21 svcEntityMessage.Data = reader.TryReadBitsToSlice(uint64(svcEntityMessage.Length))
22 writer.TempAppendLine("\t\tEntity Index: %d", svcEntityMessage.EntityIndex) 22 demo.Writer.TempAppendLine("\t\tEntity Index: %d", svcEntityMessage.EntityIndex)
23 writer.TempAppendLine("\t\tClass ID: %d", svcEntityMessage.ClassId) 23 demo.Writer.TempAppendLine("\t\tClass ID: %d", svcEntityMessage.ClassId)
24 writer.TempAppendLine("\t\tData: %v", svcEntityMessage.Data) 24 demo.Writer.TempAppendLine("\t\tData: %v", svcEntityMessage.Data)
25 return svcEntityMessage 25 return svcEntityMessage
26} 26}
diff --git a/pkg/messages/types/svcFixAngle.go b/pkg/messages/types/svcFixAngle.go
index d5e7b0f..924bba2 100644
--- a/pkg/messages/types/svcFixAngle.go
+++ b/pkg/messages/types/svcFixAngle.go
@@ -2,21 +2,21 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcFixAngle struct { 8type SvcFixAngle struct {
9 Relative bool 9 Relative bool `json:"relative"`
10 Angle fixAngles 10 Angle fixAngles `json:"angle"`
11} 11}
12 12
13type fixAngles struct { 13type fixAngles struct {
14 X float32 14 X float32 `json:"x"`
15 Y float32 15 Y float32 `json:"y"`
16 Z float32 16 Z float32 `json:"z"`
17} 17}
18 18
19func ParseSvcFixAngle(reader *bitreader.Reader) SvcFixAngle { 19func ParseSvcFixAngle(reader *bitreader.Reader, demo *types.Demo) SvcFixAngle {
20 svcFixAngle := SvcFixAngle{ 20 svcFixAngle := SvcFixAngle{
21 Relative: reader.TryReadBool(), 21 Relative: reader.TryReadBool(),
22 Angle: fixAngles{ 22 Angle: fixAngles{
@@ -25,9 +25,9 @@ func ParseSvcFixAngle(reader *bitreader.Reader) SvcFixAngle {
25 Z: float32(reader.TryReadBits(16)), 25 Z: float32(reader.TryReadBits(16)),
26 }, 26 },
27 } 27 }
28 writer.TempAppendLine("\t\tRelative: %t", svcFixAngle.Relative) 28 demo.Writer.TempAppendLine("\t\tRelative: %t", svcFixAngle.Relative)
29 writer.TempAppendLine("\t\tX: %f", svcFixAngle.Angle.X) 29 demo.Writer.TempAppendLine("\t\tX: %f", svcFixAngle.Angle.X)
30 writer.TempAppendLine("\t\tY: %f", svcFixAngle.Angle.Y) 30 demo.Writer.TempAppendLine("\t\tY: %f", svcFixAngle.Angle.Y)
31 writer.TempAppendLine("\t\tZ: %f", svcFixAngle.Angle.Z) 31 demo.Writer.TempAppendLine("\t\tZ: %f", svcFixAngle.Angle.Z)
32 return svcFixAngle 32 return svcFixAngle
33} 33}
diff --git a/pkg/messages/types/svcGameEvent.go b/pkg/messages/types/svcGameEvent.go
index b325472..cb1e91d 100644
--- a/pkg/messages/types/svcGameEvent.go
+++ b/pkg/messages/types/svcGameEvent.go
@@ -2,56 +2,56 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcGameEvent struct { 8type SvcGameEvent struct {
9 Length uint16 9 Length uint16 `json:"length"`
10 EventID uint32 10 EventID uint32 `json:"event_id"`
11 EventDescription GameEventDescriptor 11 EventDescription types.GameEventDescriptor `json:"event_description"`
12 EventDescriptors []EventDescriptorKey 12 EventDescriptors []EventDescriptorKey `json:"event_descriptors"`
13} 13}
14 14
15type EventDescriptorKey struct { 15type EventDescriptorKey struct {
16 Name string 16 Name string `json:"name"`
17 Descriptor any 17 Descriptor any `json:"descriptor"`
18} 18}
19 19
20func ParseSvcGameEvent(reader *bitreader.Reader) SvcGameEvent { 20func ParseSvcGameEvent(reader *bitreader.Reader, demo *types.Demo) SvcGameEvent {
21 svcGameEvent := SvcGameEvent{ 21 svcGameEvent := SvcGameEvent{
22 Length: uint16(reader.TryReadBits(11)), 22 Length: uint16(reader.TryReadBits(11)),
23 } 23 }
24 gameEventReader := bitreader.NewReaderFromBytes(reader.TryReadBitsToSlice(uint64(svcGameEvent.Length)), true) 24 gameEventReader := bitreader.NewReaderFromBytes(reader.TryReadBitsToSlice(uint64(svcGameEvent.Length)), true)
25 svcGameEvent.parseGameEvent(gameEventReader) 25 svcGameEvent.parseGameEvent(gameEventReader, demo)
26 return svcGameEvent 26 return svcGameEvent
27} 27}
28 28
29func (svcGameEvent *SvcGameEvent) parseGameEvent(reader *bitreader.Reader) { 29func (svcGameEvent *SvcGameEvent) parseGameEvent(reader *bitreader.Reader, demo *types.Demo) {
30 svcGameEvent.EventID = uint32(reader.TryReadBits(9)) 30 svcGameEvent.EventID = uint32(reader.TryReadBits(9))
31 svcGameEvent.EventDescription = GameEventList.GameEventDescriptor[svcGameEvent.EventID] 31 svcGameEvent.EventDescription = demo.GameEventList.GameEventDescriptor[svcGameEvent.EventID]
32 writer.TempAppendLine("\t\t%s (%d):", svcGameEvent.EventDescription.Name, svcGameEvent.EventID) 32 demo.Writer.TempAppendLine("\t\t%s (%d):", svcGameEvent.EventDescription.Name, svcGameEvent.EventID)
33 for _, descriptor := range svcGameEvent.EventDescription.Keys { 33 for _, descriptor := range svcGameEvent.EventDescription.Keys {
34 var value any 34 var value any
35 switch descriptor.Type { 35 switch descriptor.Type {
36 case EventDescriptorString: 36 case types.EventDescriptorString:
37 value = reader.TryReadString() 37 value = reader.TryReadString()
38 case EventDescriptorFloat: 38 case types.EventDescriptorFloat:
39 value = reader.TryReadFloat32() 39 value = reader.TryReadFloat32()
40 case EventDescriptorInt32: 40 case types.EventDescriptorInt32:
41 value = reader.TryReadSInt32() 41 value = reader.TryReadSInt32()
42 case EventDescriptorInt16: 42 case types.EventDescriptorInt16:
43 value = reader.TryReadSInt16() 43 value = reader.TryReadSInt16()
44 case EventDescriptorInt8: 44 case types.EventDescriptorInt8:
45 value = reader.TryReadUInt8() 45 value = reader.TryReadUInt8()
46 case EventDescriptorBool: 46 case types.EventDescriptorBool:
47 value = reader.TryReadBool() 47 value = reader.TryReadBool()
48 case EventDescriptorUInt64: 48 case types.EventDescriptorUInt64:
49 value = reader.TryReadUInt64() 49 value = reader.TryReadUInt64()
50 } 50 }
51 svcGameEvent.EventDescriptors = append(svcGameEvent.EventDescriptors, EventDescriptorKey{ 51 svcGameEvent.EventDescriptors = append(svcGameEvent.EventDescriptors, EventDescriptorKey{
52 Name: descriptor.Name, 52 Name: descriptor.Name,
53 Descriptor: value, 53 Descriptor: value,
54 }) 54 })
55 writer.TempAppendLine("\t\t\t%s: %v", descriptor.Name, value) 55 demo.Writer.TempAppendLine("\t\t\t%s: %v", descriptor.Name, value)
56 } 56 }
57} 57}
diff --git a/pkg/messages/types/svcGameEventList.go b/pkg/messages/types/svcGameEventList.go
index 9a194fd..dafe9b7 100644
--- a/pkg/messages/types/svcGameEventList.go
+++ b/pkg/messages/types/svcGameEventList.go
@@ -1,95 +1,18 @@
1package messages 1package messages
2 2
3import ( 3import (
4 "fmt"
5
6 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
8) 6)
9 7
10var GameEventList *SvcGameEventList 8func ParseSvcGameEventList(reader *bitreader.Reader, demo *types.Demo) types.SvcGameEventList {
11 9 svcGameEventList := types.SvcGameEventList{
12type SvcGameEventList struct {
13 Events int16
14 Length int32
15 GameEventDescriptor []GameEventDescriptor
16}
17
18type GameEventDescriptor struct {
19 EventID uint32
20 Name string
21 Keys []GameEventDescriptorKey
22}
23
24type GameEventDescriptorKey struct {
25 Name string
26 Type EventDescriptor
27}
28
29type EventDescriptor uint8
30
31func ParseSvcGameEventList(reader *bitreader.Reader) SvcGameEventList {
32 svcGameEventList := SvcGameEventList{
33 Events: int16(reader.TryReadBits(9)), 10 Events: int16(reader.TryReadBits(9)),
34 Length: int32(reader.TryReadBits(20)), 11 Length: int32(reader.TryReadBits(20)),
35 } 12 }
36 gameEventListReader := bitreader.NewReaderFromBytes(reader.TryReadBitsToSlice(uint64(svcGameEventList.Length)), true) 13 gameEventListReader := bitreader.NewReaderFromBytes(reader.TryReadBitsToSlice(uint64(svcGameEventList.Length)), true)
37 writer.TempAppendLine("\t\t%d Events:", svcGameEventList.Events) 14 demo.Writer.TempAppendLine("\t\t%d Events:", svcGameEventList.Events)
38 svcGameEventList.parseGameEventDescriptor(gameEventListReader) 15 svcGameEventList.ParseGameEventDescriptor(gameEventListReader, demo)
39 GameEventList = &svcGameEventList 16 demo.GameEventList = &svcGameEventList
40 return svcGameEventList 17 return svcGameEventList
41} 18}
42
43func (svcGameEventList *SvcGameEventList) parseGameEventDescriptor(reader *bitreader.Reader) {
44 svcGameEventList.GameEventDescriptor = make([]GameEventDescriptor, svcGameEventList.Events)
45 for event := 0; event < int(svcGameEventList.Events); event++ {
46 svcGameEventList.GameEventDescriptor[event] = GameEventDescriptor{
47 EventID: uint32(reader.TryReadBits(9)),
48 Name: reader.TryReadString(),
49 }
50 writer.TempAppendLine("\t\t\t%d: %s", svcGameEventList.GameEventDescriptor[event].EventID, svcGameEventList.GameEventDescriptor[event].Name)
51 for {
52 descriptorType := reader.TryReadBits(3)
53 if descriptorType == 0 {
54 break
55 }
56 KeyName := reader.TryReadString()
57 svcGameEventList.GameEventDescriptor[event].Keys = append(svcGameEventList.GameEventDescriptor[event].Keys, GameEventDescriptorKey{
58 Name: KeyName,
59 Type: EventDescriptor(descriptorType),
60 })
61 }
62 writer.TempAppendLine("\t\t\t\tKeys: %v", svcGameEventList.GameEventDescriptor[event].Keys)
63 }
64}
65
66const (
67 EventDescriptorString EventDescriptor = iota + 1
68 EventDescriptorFloat
69 EventDescriptorInt32
70 EventDescriptorInt16
71 EventDescriptorInt8
72 EventDescriptorBool
73 EventDescriptorUInt64
74)
75
76func (eventDescriptor EventDescriptor) String() string {
77 switch eventDescriptor {
78 case EventDescriptorString:
79 return "String"
80 case EventDescriptorFloat:
81 return "Float"
82 case EventDescriptorInt32:
83 return "Int32"
84 case EventDescriptorInt16:
85 return "Int16"
86 case EventDescriptorInt8:
87 return "Int8"
88 case EventDescriptorBool:
89 return "Bool"
90 case EventDescriptorUInt64:
91 return "UInt64"
92 default:
93 return fmt.Sprintf("%d", eventDescriptor)
94 }
95}
diff --git a/pkg/messages/types/svcGetCvarValue.go b/pkg/messages/types/svcGetCvarValue.go
index 5deb9ef..1c3e54c 100644
--- a/pkg/messages/types/svcGetCvarValue.go
+++ b/pkg/messages/types/svcGetCvarValue.go
@@ -2,20 +2,20 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcGetCvarValue struct { 8type SvcGetCvarValue struct {
9 Cookie int32 9 Cookie int32 `json:"cookie"`
10 CvarName string 10 CvarName string `json:"cvar_name"`
11} 11}
12 12
13func ParseSvcGetCvarValue(reader *bitreader.Reader) SvcGetCvarValue { 13func ParseSvcGetCvarValue(reader *bitreader.Reader, demo *types.Demo) SvcGetCvarValue {
14 svcGetCvarValue := SvcGetCvarValue{ 14 svcGetCvarValue := SvcGetCvarValue{
15 Cookie: reader.TryReadSInt32(), 15 Cookie: reader.TryReadSInt32(),
16 CvarName: reader.TryReadString(), 16 CvarName: reader.TryReadString(),
17 } 17 }
18 writer.TempAppendLine("\t\tCookie: %d", svcGetCvarValue.Cookie) 18 demo.Writer.TempAppendLine("\t\tCookie: %d", svcGetCvarValue.Cookie)
19 writer.TempAppendLine("\t\tCvar: \"%s\"", svcGetCvarValue.CvarName) 19 demo.Writer.TempAppendLine("\t\tCvar: \"%s\"", svcGetCvarValue.CvarName)
20 return svcGetCvarValue 20 return svcGetCvarValue
21} 21}
diff --git a/pkg/messages/types/svcMenu.go b/pkg/messages/types/svcMenu.go
index ffbb86b..b1da594 100644
--- a/pkg/messages/types/svcMenu.go
+++ b/pkg/messages/types/svcMenu.go
@@ -2,22 +2,22 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcMenu struct { 8type SvcMenu struct {
9 Type uint16 9 Type uint16 `json:"type"`
10 Length uint32 10 Length uint32 `json:"length"`
11 Data []byte 11 Data []byte `json:"data"`
12} 12}
13 13
14func ParseSvcMenu(reader *bitreader.Reader) SvcMenu { 14func ParseSvcMenu(reader *bitreader.Reader, demo *types.Demo) SvcMenu {
15 svcMenu := SvcMenu{ 15 svcMenu := SvcMenu{
16 Type: reader.TryReadUInt16(), 16 Type: reader.TryReadUInt16(),
17 Length: reader.TryReadUInt32(), 17 Length: reader.TryReadUInt32(),
18 } 18 }
19 svcMenu.Data = reader.TryReadBitsToSlice(uint64(svcMenu.Length)) 19 svcMenu.Data = reader.TryReadBitsToSlice(uint64(svcMenu.Length))
20 writer.TempAppendLine("\t\tType: %d", svcMenu.Type) 20 demo.Writer.TempAppendLine("\t\tType: %d", svcMenu.Type)
21 writer.TempAppendLine("\t\tData: %v", svcMenu.Data) 21 demo.Writer.TempAppendLine("\t\tData: %v", svcMenu.Data)
22 return svcMenu 22 return svcMenu
23} 23}
diff --git a/pkg/messages/types/svcPacketEntities.go b/pkg/messages/types/svcPacketEntities.go
index 188f827..abef83d 100644
--- a/pkg/messages/types/svcPacketEntities.go
+++ b/pkg/messages/types/svcPacketEntities.go
@@ -2,21 +2,21 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcPacketEntities struct { 8type SvcPacketEntities struct {
9 MaxEntries uint16 9 MaxEntries uint16 `json:"max_entries"`
10 IsDelta bool 10 IsDelta bool `json:"is_delta"`
11 DeltaFrom int32 11 DeltaFrom int32 `json:"delta_from"`
12 BaseLine bool 12 BaseLine bool `json:"base_line"`
13 UpdatedEntries uint16 13 UpdatedEntries uint16 `json:"updated_entries"`
14 Length uint32 14 Length uint32 `json:"length"`
15 UpdatedBaseline bool 15 UpdatedBaseline bool `json:"updated_baseline"`
16 Data []byte 16 Data []byte `json:"data"`
17} 17}
18 18
19func ParseSvcPacketEntities(reader *bitreader.Reader) SvcPacketEntities { 19func ParseSvcPacketEntities(reader *bitreader.Reader, demo *types.Demo) SvcPacketEntities {
20 svcPacketEntities := SvcPacketEntities{ 20 svcPacketEntities := SvcPacketEntities{
21 MaxEntries: uint16(reader.TryReadBits(11)), 21 MaxEntries: uint16(reader.TryReadBits(11)),
22 IsDelta: reader.TryReadBool(), 22 IsDelta: reader.TryReadBool(),
@@ -31,12 +31,12 @@ func ParseSvcPacketEntities(reader *bitreader.Reader) SvcPacketEntities {
31 svcPacketEntities.Length = uint32(reader.TryReadBits(20)) 31 svcPacketEntities.Length = uint32(reader.TryReadBits(20))
32 svcPacketEntities.UpdatedBaseline = reader.TryReadBool() 32 svcPacketEntities.UpdatedBaseline = reader.TryReadBool()
33 svcPacketEntities.Data = reader.TryReadBitsToSlice(uint64(svcPacketEntities.Length)) 33 svcPacketEntities.Data = reader.TryReadBitsToSlice(uint64(svcPacketEntities.Length))
34 writer.TempAppendLine("\t\tMax Entries: %d", svcPacketEntities.MaxEntries) 34 demo.Writer.TempAppendLine("\t\tMax Entries: %d", svcPacketEntities.MaxEntries)
35 writer.TempAppendLine("\t\tIs Delta: %t", svcPacketEntities.IsDelta) 35 demo.Writer.TempAppendLine("\t\tIs Delta: %t", svcPacketEntities.IsDelta)
36 writer.TempAppendLine("\t\tDelta From: %d", svcPacketEntities.DeltaFrom) 36 demo.Writer.TempAppendLine("\t\tDelta From: %d", svcPacketEntities.DeltaFrom)
37 writer.TempAppendLine("\t\tBaseline: %t", svcPacketEntities.BaseLine) 37 demo.Writer.TempAppendLine("\t\tBaseline: %t", svcPacketEntities.BaseLine)
38 writer.TempAppendLine("\t\tUpdated Baseline: %t", svcPacketEntities.UpdatedBaseline) 38 demo.Writer.TempAppendLine("\t\tUpdated Baseline: %t", svcPacketEntities.UpdatedBaseline)
39 writer.TempAppendLine("\t\t%d Updated Entries:", svcPacketEntities.UpdatedEntries) 39 demo.Writer.TempAppendLine("\t\t%d Updated Entries:", svcPacketEntities.UpdatedEntries)
40 writer.TempAppendLine("\t\tData: %v", svcPacketEntities.Data) 40 demo.Writer.TempAppendLine("\t\tData: %v", svcPacketEntities.Data)
41 return svcPacketEntities 41 return svcPacketEntities
42} 42}
diff --git a/pkg/messages/types/svcPaintmapData.go b/pkg/messages/types/svcPaintmapData.go
index 10f8031..2455f83 100644
--- a/pkg/messages/types/svcPaintmapData.go
+++ b/pkg/messages/types/svcPaintmapData.go
@@ -2,19 +2,19 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcPaintmapData struct { 8type SvcPaintmapData struct {
9 Length uint32 9 Length uint32 `json:"length"`
10 Data []byte 10 Data []byte `json:"data"`
11} 11}
12 12
13func ParseSvcPaintmapData(reader *bitreader.Reader) SvcPaintmapData { 13func ParseSvcPaintmapData(reader *bitreader.Reader, demo *types.Demo) SvcPaintmapData {
14 svcPaintmapData := SvcPaintmapData{ 14 svcPaintmapData := SvcPaintmapData{
15 Length: reader.TryReadUInt32(), 15 Length: reader.TryReadUInt32(),
16 } 16 }
17 svcPaintmapData.Data = reader.TryReadBitsToSlice(uint64(svcPaintmapData.Length)) 17 svcPaintmapData.Data = reader.TryReadBitsToSlice(uint64(svcPaintmapData.Length))
18 writer.TempAppendLine("\t\tData: %v", svcPaintmapData.Data) 18 demo.Writer.TempAppendLine("\t\tData: %v", svcPaintmapData.Data)
19 return svcPaintmapData 19 return svcPaintmapData
20} 20}
diff --git a/pkg/messages/types/svcPrefetch.go b/pkg/messages/types/svcPrefetch.go
index 6aa39aa..55b6713 100644
--- a/pkg/messages/types/svcPrefetch.go
+++ b/pkg/messages/types/svcPrefetch.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcPrefetch struct { 8type SvcPrefetch struct {
9 SoundIndex int16 9 SoundIndex int16 `json:"sound_index"`
10} 10}
11 11
12func ParseSvcPrefetch(reader *bitreader.Reader) SvcPrefetch { 12func ParseSvcPrefetch(reader *bitreader.Reader, demo *types.Demo) SvcPrefetch {
13 svcPrefetch := SvcPrefetch{ 13 svcPrefetch := SvcPrefetch{
14 SoundIndex: int16(reader.TryReadBits(13)), 14 SoundIndex: int16(reader.TryReadBits(13)),
15 } 15 }
16 writer.TempAppendLine("\t\tSound Index: %d", svcPrefetch.SoundIndex) 16 demo.Writer.TempAppendLine("\t\tSound Index: %d", svcPrefetch.SoundIndex)
17 return svcPrefetch 17 return svcPrefetch
18} 18}
diff --git a/pkg/messages/types/svcPrint.go b/pkg/messages/types/svcPrint.go
index 56f0d08..0db7ffd 100644
--- a/pkg/messages/types/svcPrint.go
+++ b/pkg/messages/types/svcPrint.go
@@ -4,18 +4,18 @@ import (
4 "strings" 4 "strings"
5 5
6 "github.com/pektezol/bitreader" 6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/sdp.go/pkg/writer" 7 "github.com/pektezol/sdp.go/pkg/types"
8) 8)
9 9
10type SvcPrint struct { 10type SvcPrint struct {
11 Message string 11 Message string `json:"message"`
12} 12}
13 13
14func ParseSvcPrint(reader *bitreader.Reader) SvcPrint { 14func ParseSvcPrint(reader *bitreader.Reader, demo *types.Demo) SvcPrint {
15 svcPrint := SvcPrint{ 15 svcPrint := SvcPrint{
16 Message: reader.TryReadString(), 16 Message: reader.TryReadString(),
17 } 17 }
18 // common psycopath behaviour 18 // common psycopath behaviour
19 writer.TempAppendLine("\t\t%s", strings.Replace(strings.ReplaceAll(strings.ReplaceAll(svcPrint.Message, "\n", "\n\t\t"), "\n\t\t\n\t\t", ""), "\n\t\t", "", 1)) 19 demo.Writer.TempAppendLine("\t\t%s", strings.Replace(strings.ReplaceAll(strings.ReplaceAll(svcPrint.Message, "\n", "\n\t\t"), "\n\t\t\n\t\t", ""), "\n\t\t", "", 1))
20 return svcPrint 20 return svcPrint
21} 21}
diff --git a/pkg/messages/types/svcSendTable.go b/pkg/messages/types/svcSendTable.go
index d0def36..fc98eb6 100644
--- a/pkg/messages/types/svcSendTable.go
+++ b/pkg/messages/types/svcSendTable.go
@@ -2,23 +2,23 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcSendTable struct { 8type SvcSendTable struct {
9 NeedsDecoder bool 9 NeedsDecoder bool `json:"needs_decoder"`
10 Length uint8 10 Length uint8 `json:"length"`
11 Props uint32 11 Props uint32 `json:"props"`
12} 12}
13 13
14func ParseSvcSendTable(reader *bitreader.Reader) SvcSendTable { 14func ParseSvcSendTable(reader *bitreader.Reader, demo *types.Demo) SvcSendTable {
15 svcSendTable := SvcSendTable{ 15 svcSendTable := SvcSendTable{
16 NeedsDecoder: reader.TryReadBool(), 16 NeedsDecoder: reader.TryReadBool(),
17 Length: reader.TryReadUInt8(), 17 Length: reader.TryReadUInt8(),
18 } 18 }
19 svcSendTable.Props = uint32(reader.TryReadBits(uint64(svcSendTable.Length))) 19 svcSendTable.Props = uint32(reader.TryReadBits(uint64(svcSendTable.Length)))
20 writer.TempAppendLine("\t\tNeeds Decoder: %t", svcSendTable.NeedsDecoder) 20 demo.Writer.TempAppendLine("\t\tNeeds Decoder: %t", svcSendTable.NeedsDecoder)
21 writer.TempAppendLine("\t\tLength: %d", svcSendTable.Length) 21 demo.Writer.TempAppendLine("\t\tLength: %d", svcSendTable.Length)
22 writer.TempAppendLine("\t\tProps: %d", svcSendTable.Props) 22 demo.Writer.TempAppendLine("\t\tProps: %d", svcSendTable.Props)
23 return svcSendTable 23 return svcSendTable
24} 24}
diff --git a/pkg/messages/types/svcServerInfo.go b/pkg/messages/types/svcServerInfo.go
index 9e3113c..2aabccd 100644
--- a/pkg/messages/types/svcServerInfo.go
+++ b/pkg/messages/types/svcServerInfo.go
@@ -2,29 +2,29 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcServerInfo struct { 8type SvcServerInfo struct {
9 Protocol uint16 9 Protocol uint16 `json:"protocol"`
10 ServerCount uint32 10 ServerCount uint32 `json:"server_count"`
11 IsHltv bool 11 IsHltv bool `json:"is_hltv"`
12 IsDedicated bool 12 IsDedicated bool `json:"is_dedicated"`
13 ClientCrc int32 13 ClientCrc int32 `json:"client_crc"`
14 StringTableCrc uint32 14 StringTableCrc uint32 `json:"string_table_crc"`
15 MaxServerClasses uint16 15 MaxServerClasses uint16 `json:"max_server_classes"`
16 MapCrc uint32 16 MapCrc uint32 `json:"map_crc"`
17 PlayerCount uint8 17 PlayerCount uint8 `json:"player_count"`
18 MaxClients uint8 18 MaxClients uint8 `json:"max_clients"`
19 TickInterval float32 19 TickInterval float32 `json:"tick_interval"`
20 Platform string 20 Platform string `json:"platform"`
21 GameDir string 21 GameDir string `json:"game_dir"`
22 MapName string 22 MapName string `json:"map_name"`
23 SkyName string 23 SkyName string `json:"sky_name"`
24 HostName string 24 HostName string `json:"host_name"`
25} 25}
26 26
27func ParseSvcServerInfo(reader *bitreader.Reader) SvcServerInfo { 27func ParseSvcServerInfo(reader *bitreader.Reader, demo *types.Demo) SvcServerInfo {
28 svcServerInfo := SvcServerInfo{ 28 svcServerInfo := SvcServerInfo{
29 Protocol: reader.TryReadUInt16(), 29 Protocol: reader.TryReadUInt16(),
30 ServerCount: reader.TryReadUInt32(), 30 ServerCount: reader.TryReadUInt32(),
@@ -43,21 +43,21 @@ func ParseSvcServerInfo(reader *bitreader.Reader) SvcServerInfo {
43 SkyName: reader.TryReadString(), 43 SkyName: reader.TryReadString(),
44 HostName: reader.TryReadString(), 44 HostName: reader.TryReadString(),
45 } 45 }
46 writer.TempAppendLine("\t\tNetwork Protocol: %d", svcServerInfo.Protocol) 46 demo.Writer.TempAppendLine("\t\tNetwork Protocol: %d", svcServerInfo.Protocol)
47 writer.TempAppendLine("\t\tServer Count: %d", svcServerInfo.ServerCount) 47 demo.Writer.TempAppendLine("\t\tServer Count: %d", svcServerInfo.ServerCount)
48 writer.TempAppendLine("\t\tIs Hltv: %t", svcServerInfo.IsHltv) 48 demo.Writer.TempAppendLine("\t\tIs Hltv: %t", svcServerInfo.IsHltv)
49 writer.TempAppendLine("\t\tIs Dedicated: %t", svcServerInfo.IsDedicated) 49 demo.Writer.TempAppendLine("\t\tIs Dedicated: %t", svcServerInfo.IsDedicated)
50 writer.TempAppendLine("\t\tServer Client CRC: %d", svcServerInfo.ClientCrc) 50 demo.Writer.TempAppendLine("\t\tServer Client CRC: %d", svcServerInfo.ClientCrc)
51 writer.TempAppendLine("\t\tString Table CRC: %d", svcServerInfo.StringTableCrc) 51 demo.Writer.TempAppendLine("\t\tString Table CRC: %d", svcServerInfo.StringTableCrc)
52 writer.TempAppendLine("\t\tMax Server Classes: %d", svcServerInfo.MaxServerClasses) 52 demo.Writer.TempAppendLine("\t\tMax Server Classes: %d", svcServerInfo.MaxServerClasses)
53 writer.TempAppendLine("\t\tServer Map CRC: %d", svcServerInfo.MapCrc) 53 demo.Writer.TempAppendLine("\t\tServer Map CRC: %d", svcServerInfo.MapCrc)
54 writer.TempAppendLine("\t\tCurrent Player Count: %d", svcServerInfo.PlayerCount) 54 demo.Writer.TempAppendLine("\t\tCurrent Player Count: %d", svcServerInfo.PlayerCount)
55 writer.TempAppendLine("\t\tMax Player Count: %d", svcServerInfo.MaxClients) 55 demo.Writer.TempAppendLine("\t\tMax Player Count: %d", svcServerInfo.MaxClients)
56 writer.TempAppendLine("\t\tInterval Per Tick: %f", svcServerInfo.TickInterval) 56 demo.Writer.TempAppendLine("\t\tInterval Per Tick: %f", svcServerInfo.TickInterval)
57 writer.TempAppendLine("\t\tPlatform: %s", svcServerInfo.Platform) 57 demo.Writer.TempAppendLine("\t\tPlatform: %s", svcServerInfo.Platform)
58 writer.TempAppendLine("\t\tGame Directory: %s", svcServerInfo.GameDir) 58 demo.Writer.TempAppendLine("\t\tGame Directory: %s", svcServerInfo.GameDir)
59 writer.TempAppendLine("\t\tMap Name: %s", svcServerInfo.MapName) 59 demo.Writer.TempAppendLine("\t\tMap Name: %s", svcServerInfo.MapName)
60 writer.TempAppendLine("\t\tSky Name: %s", svcServerInfo.SkyName) 60 demo.Writer.TempAppendLine("\t\tSky Name: %s", svcServerInfo.SkyName)
61 writer.TempAppendLine("\t\tHost Name: %s", svcServerInfo.HostName) 61 demo.Writer.TempAppendLine("\t\tHost Name: %s", svcServerInfo.HostName)
62 return svcServerInfo 62 return svcServerInfo
63} 63}
diff --git a/pkg/messages/types/svcSetPause.go b/pkg/messages/types/svcSetPause.go
index b69779f..ad9f2d5 100644
--- a/pkg/messages/types/svcSetPause.go
+++ b/pkg/messages/types/svcSetPause.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcSetPause struct { 8type SvcSetPause struct {
9 Paused bool 9 Paused bool `json:"paused"`
10} 10}
11 11
12func ParseSvcSetPause(reader *bitreader.Reader) SvcSetPause { 12func ParseSvcSetPause(reader *bitreader.Reader, demo *types.Demo) SvcSetPause {
13 svcSetPause := SvcSetPause{ 13 svcSetPause := SvcSetPause{
14 Paused: reader.TryReadBool(), 14 Paused: reader.TryReadBool(),
15 } 15 }
16 writer.TempAppendLine("\t\tPaused: %t", svcSetPause.Paused) 16 demo.Writer.TempAppendLine("\t\tPaused: %t", svcSetPause.Paused)
17 return svcSetPause 17 return svcSetPause
18} 18}
diff --git a/pkg/messages/types/svcSetView.go b/pkg/messages/types/svcSetView.go
index a392d36..55b2065 100644
--- a/pkg/messages/types/svcSetView.go
+++ b/pkg/messages/types/svcSetView.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcSetView struct { 8type SvcSetView struct {
9 EntityIndex uint16 9 EntityIndex uint16 `json:"entity_index"`
10} 10}
11 11
12func ParseSvcSetView(reader *bitreader.Reader) SvcSetView { 12func ParseSvcSetView(reader *bitreader.Reader, demo *types.Demo) SvcSetView {
13 svcSetView := SvcSetView{ 13 svcSetView := SvcSetView{
14 EntityIndex: uint16(reader.TryReadBits(11)), 14 EntityIndex: uint16(reader.TryReadBits(11)),
15 } 15 }
16 writer.TempAppendLine("\t\tEntity Index: %d", svcSetView.EntityIndex) 16 demo.Writer.TempAppendLine("\t\tEntity Index: %d", svcSetView.EntityIndex)
17 return svcSetView 17 return svcSetView
18} 18}
diff --git a/pkg/messages/types/svcSounds.go b/pkg/messages/types/svcSounds.go
index 5391af1..cc155e5 100644
--- a/pkg/messages/types/svcSounds.go
+++ b/pkg/messages/types/svcSounds.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcSounds struct { 8type SvcSounds struct {
9 ReliableSound bool 9 ReliableSound bool `json:"reliable_sound"`
10 SoundCount uint8 10 SoundCount uint8 `json:"sound_count"`
11 Length uint16 11 Length uint16 `json:"length"`
12 Data []byte 12 Data []byte `json:"data"`
13} 13}
14 14
15func ParseSvcSounds(reader *bitreader.Reader) SvcSounds { 15func ParseSvcSounds(reader *bitreader.Reader, demo *types.Demo) SvcSounds {
16 svcSounds := SvcSounds{ 16 svcSounds := SvcSounds{
17 ReliableSound: reader.TryReadBool(), 17 ReliableSound: reader.TryReadBool(),
18 } 18 }
@@ -24,8 +24,8 @@ func ParseSvcSounds(reader *bitreader.Reader) SvcSounds {
24 svcSounds.Length = reader.TryReadUInt16() 24 svcSounds.Length = reader.TryReadUInt16()
25 } 25 }
26 svcSounds.Data = reader.TryReadBitsToSlice(uint64(svcSounds.Length)) 26 svcSounds.Data = reader.TryReadBitsToSlice(uint64(svcSounds.Length))
27 writer.TempAppendLine("\t\tReliable Sound: %t", svcSounds.ReliableSound) 27 demo.Writer.TempAppendLine("\t\tReliable Sound: %t", svcSounds.ReliableSound)
28 writer.TempAppendLine("\t\tSound Count: %d", svcSounds.SoundCount) 28 demo.Writer.TempAppendLine("\t\tSound Count: %d", svcSounds.SoundCount)
29 writer.TempAppendLine("\t\tData: %v", svcSounds.Data) 29 demo.Writer.TempAppendLine("\t\tData: %v", svcSounds.Data)
30 return svcSounds 30 return svcSounds
31} 31}
diff --git a/pkg/messages/types/svcSplitScreen.go b/pkg/messages/types/svcSplitScreen.go
index e7f77c0..a4d4e48 100644
--- a/pkg/messages/types/svcSplitScreen.go
+++ b/pkg/messages/types/svcSplitScreen.go
@@ -2,22 +2,22 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcSplitScreen struct { 8type SvcSplitScreen struct {
9 RemoveUser bool 9 RemoveUser bool `json:"remove_user"`
10 Length uint16 10 Length uint16 `json:"length"`
11 Data []byte 11 Data []byte `json:"data"`
12} 12}
13 13
14func ParseSvcSplitScreen(reader *bitreader.Reader) SvcSplitScreen { 14func ParseSvcSplitScreen(reader *bitreader.Reader, demo *types.Demo) SvcSplitScreen {
15 svcSplitScreen := SvcSplitScreen{ 15 svcSplitScreen := SvcSplitScreen{
16 RemoveUser: reader.TryReadBool(), 16 RemoveUser: reader.TryReadBool(),
17 Length: uint16(reader.TryReadBits(11)), 17 Length: uint16(reader.TryReadBits(11)),
18 } 18 }
19 svcSplitScreen.Data = reader.TryReadBitsToSlice(uint64(svcSplitScreen.Length)) 19 svcSplitScreen.Data = reader.TryReadBitsToSlice(uint64(svcSplitScreen.Length))
20 writer.TempAppendLine("\t\tRemove User: %t", svcSplitScreen.RemoveUser) 20 demo.Writer.TempAppendLine("\t\tRemove User: %t", svcSplitScreen.RemoveUser)
21 writer.TempAppendLine("\t\tData: %v", svcSplitScreen.Data) 21 demo.Writer.TempAppendLine("\t\tData: %v", svcSplitScreen.Data)
22 return svcSplitScreen 22 return svcSplitScreen
23} 23}
diff --git a/pkg/messages/types/svcTempEntities.go b/pkg/messages/types/svcTempEntities.go
index 08c0af4..452e712 100644
--- a/pkg/messages/types/svcTempEntities.go
+++ b/pkg/messages/types/svcTempEntities.go
@@ -2,22 +2,22 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcTempEntities struct { 8type SvcTempEntities struct {
9 NumEntries uint8 9 NumEntries uint8 `json:"num_entries"`
10 Length uint32 10 Length uint32 `json:"length"`
11 Data []byte 11 Data []byte `json:"data"`
12} 12}
13 13
14func ParseSvcTempEntities(reader *bitreader.Reader) SvcTempEntities { 14func ParseSvcTempEntities(reader *bitreader.Reader, demo *types.Demo) SvcTempEntities {
15 svcTempEntities := SvcTempEntities{ 15 svcTempEntities := SvcTempEntities{
16 NumEntries: reader.TryReadUInt8(), 16 NumEntries: reader.TryReadUInt8(),
17 Length: uint32(reader.TryReadBits(17)), 17 Length: uint32(reader.TryReadBits(17)),
18 } 18 }
19 svcTempEntities.Data = reader.TryReadBitsToSlice(uint64(svcTempEntities.Length)) 19 svcTempEntities.Data = reader.TryReadBitsToSlice(uint64(svcTempEntities.Length))
20 writer.TempAppendLine("\t\tNumber Of Entries: %d", svcTempEntities.NumEntries) 20 demo.Writer.TempAppendLine("\t\tNumber Of Entries: %d", svcTempEntities.NumEntries)
21 writer.TempAppendLine("\t\tData: %v", svcTempEntities.Data) 21 demo.Writer.TempAppendLine("\t\tData: %v", svcTempEntities.Data)
22 return svcTempEntities 22 return svcTempEntities
23} 23}
diff --git a/pkg/messages/types/svcUpdateStringTable.go b/pkg/messages/types/svcUpdateStringTable.go
index 11e63d4..7e15cd2 100644
--- a/pkg/messages/types/svcUpdateStringTable.go
+++ b/pkg/messages/types/svcUpdateStringTable.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcUpdateStringTable struct { 8type SvcUpdateStringTable struct {
9 TableId uint8 9 TableId uint8 `json:"table_id"`
10 NumChangedEntries uint16 10 NumChangedEntries uint16 `json:"num_changed_entries"`
11 Length int32 11 Length int32 `json:"length"`
12 Data []byte 12 Data []byte `json:"data"`
13} 13}
14 14
15func ParseSvcUpdateStringTable(reader *bitreader.Reader) SvcUpdateStringTable { 15func ParseSvcUpdateStringTable(reader *bitreader.Reader, demo *types.Demo) SvcUpdateStringTable {
16 svcUpdateStringTable := SvcUpdateStringTable{ 16 svcUpdateStringTable := SvcUpdateStringTable{
17 TableId: uint8(reader.TryReadBits(5)), 17 TableId: uint8(reader.TryReadBits(5)),
18 } 18 }
@@ -21,7 +21,7 @@ func ParseSvcUpdateStringTable(reader *bitreader.Reader) SvcUpdateStringTable {
21 } 21 }
22 svcUpdateStringTable.Length = int32(reader.TryReadBits(20)) 22 svcUpdateStringTable.Length = int32(reader.TryReadBits(20))
23 svcUpdateStringTable.Data = reader.TryReadBitsToSlice(uint64(svcUpdateStringTable.Length)) 23 svcUpdateStringTable.Data = reader.TryReadBitsToSlice(uint64(svcUpdateStringTable.Length))
24 writer.TempAppendLine("\t\tTable ID: %d", svcUpdateStringTable.TableId) 24 demo.Writer.TempAppendLine("\t\tTable ID: %d", svcUpdateStringTable.TableId)
25 writer.TempAppendLine("\t\tNumber Of Changed Entries: %d", svcUpdateStringTable.NumChangedEntries) 25 demo.Writer.TempAppendLine("\t\tNumber Of Changed Entries: %d", svcUpdateStringTable.NumChangedEntries)
26 return svcUpdateStringTable 26 return svcUpdateStringTable
27} 27}
diff --git a/pkg/messages/types/svcUserMessage.go b/pkg/messages/types/svcUserMessage.go
index 138f8d3..1bb0e0e 100644
--- a/pkg/messages/types/svcUserMessage.go
+++ b/pkg/messages/types/svcUserMessage.go
@@ -5,134 +5,134 @@ import (
5 "math" 5 "math"
6 6
7 "github.com/pektezol/bitreader" 7 "github.com/pektezol/bitreader"
8 "github.com/pektezol/sdp.go/pkg/writer" 8 "github.com/pektezol/sdp.go/pkg/types"
9) 9)
10 10
11type SvcUserMessage struct { 11type SvcUserMessage struct {
12 Type int8 12 Type int8 `json:"type"`
13 Length int16 13 Length int16 `json:"length"`
14 Data any 14 Data any `json:"data"`
15} 15}
16 16
17func ParseSvcUserMessage(reader *bitreader.Reader) SvcUserMessage { 17func ParseSvcUserMessage(reader *bitreader.Reader, demo *types.Demo) SvcUserMessage {
18 svcUserMessage := SvcUserMessage{ 18 svcUserMessage := SvcUserMessage{
19 Type: int8(reader.TryReadBits(8)), 19 Type: int8(reader.TryReadBits(8)),
20 Length: int16(reader.TryReadBits(12)), 20 Length: int16(reader.TryReadBits(12)),
21 } 21 }
22 svcUserMessage.Data = reader.TryReadBitsToSlice(uint64(svcUserMessage.Length)) 22 svcUserMessage.Data = reader.TryReadBitsToSlice(uint64(svcUserMessage.Length))
23 userMessageReader := bitreader.NewReaderFromBytes(svcUserMessage.Data.([]byte), true) 23 userMessageReader := bitreader.NewReaderFromBytes(svcUserMessage.Data.([]byte), true)
24 writer.TempAppendLine("\t\t%s (%d):", UserMessageType(svcUserMessage.Type).String(), svcUserMessage.Type) 24 demo.Writer.TempAppendLine("\t\t%s (%d):", UserMessageType(svcUserMessage.Type).String(), svcUserMessage.Type)
25 switch UserMessageType(svcUserMessage.Type) { 25 switch UserMessageType(svcUserMessage.Type) {
26 case EUserMessageTypeGeiger: 26 case EUserMessageTypeGeiger:
27 svcUserMessage.parseGeiger(userMessageReader) 27 svcUserMessage.parseGeiger(userMessageReader, demo)
28 case EUserMessageTypeTrain: 28 case EUserMessageTypeTrain:
29 svcUserMessage.parseTrain(userMessageReader) 29 svcUserMessage.parseTrain(userMessageReader, demo)
30 case EUserMessageTypeHudText: 30 case EUserMessageTypeHudText:
31 svcUserMessage.parseHUDText(userMessageReader) 31 svcUserMessage.parseHUDText(userMessageReader, demo)
32 case EUserMessageTypeSayText: 32 case EUserMessageTypeSayText:
33 svcUserMessage.parseSayText(userMessageReader) 33 svcUserMessage.parseSayText(userMessageReader, demo)
34 case EUserMessageTypeSayText2: 34 case EUserMessageTypeSayText2:
35 svcUserMessage.parseSayText2(userMessageReader) 35 svcUserMessage.parseSayText2(userMessageReader, demo)
36 case EUserMessageTypeTextMsg: 36 case EUserMessageTypeTextMsg:
37 svcUserMessage.parseTextMsg(userMessageReader) 37 svcUserMessage.parseTextMsg(userMessageReader, demo)
38 case EUserMessageTypeHUDMsg: 38 case EUserMessageTypeHUDMsg:
39 svcUserMessage.parseHUDMsg(userMessageReader) 39 svcUserMessage.parseHUDMsg(userMessageReader, demo)
40 case EUserMessageTypeResetHUD: 40 case EUserMessageTypeResetHUD:
41 svcUserMessage.parseResetHUD(userMessageReader) 41 svcUserMessage.parseResetHUD(userMessageReader, demo)
42 case EUserMessageTypeShake: 42 case EUserMessageTypeShake:
43 svcUserMessage.parseShake(userMessageReader) 43 svcUserMessage.parseShake(userMessageReader, demo)
44 case EUserMessageTypeFade: 44 case EUserMessageTypeFade:
45 svcUserMessage.parseFade(userMessageReader) 45 svcUserMessage.parseFade(userMessageReader, demo)
46 case EUserMessageTypeVGUIMenu: 46 case EUserMessageTypeVGUIMenu:
47 svcUserMessage.parseVguiMenu(userMessageReader) 47 svcUserMessage.parseVguiMenu(userMessageReader, demo)
48 case EUserMessageTypeRumble: 48 case EUserMessageTypeRumble:
49 svcUserMessage.parseRumble(userMessageReader) 49 svcUserMessage.parseRumble(userMessageReader, demo)
50 case EUserMessageTypeBattery: 50 case EUserMessageTypeBattery:
51 svcUserMessage.parseBattery(userMessageReader) 51 svcUserMessage.parseBattery(userMessageReader, demo)
52 case EUserMessageTypeDamage: 52 case EUserMessageTypeDamage:
53 svcUserMessage.parseDamage(userMessageReader) 53 svcUserMessage.parseDamage(userMessageReader, demo)
54 case EUserMessageTypeVoiceMask: 54 case EUserMessageTypeVoiceMask:
55 svcUserMessage.parseVoiceMask(userMessageReader) 55 svcUserMessage.parseVoiceMask(userMessageReader, demo)
56 case EUserMessageTypeCloseCaption: 56 case EUserMessageTypeCloseCaption:
57 svcUserMessage.parseCloseCaption(userMessageReader) 57 svcUserMessage.parseCloseCaption(userMessageReader, demo)
58 case EUserMessageTypeKeyHintText: 58 case EUserMessageTypeKeyHintText:
59 svcUserMessage.parseKeyHintText(userMessageReader) 59 svcUserMessage.parseKeyHintText(userMessageReader, demo)
60 case EUserMessageTypeLogoTimeMsg: 60 case EUserMessageTypeLogoTimeMsg:
61 svcUserMessage.parseLogoTimeMsg(userMessageReader) 61 svcUserMessage.parseLogoTimeMsg(userMessageReader, demo)
62 case EUserMessageTypeAchievementEvent: 62 case EUserMessageTypeAchievementEvent:
63 svcUserMessage.parseAchivementEvent(userMessageReader) 63 svcUserMessage.parseAchivementEvent(userMessageReader, demo)
64 case EUserMessageTypeCurrentTimescale: 64 case EUserMessageTypeCurrentTimescale:
65 svcUserMessage.parseCurrentTimescale(userMessageReader) 65 svcUserMessage.parseCurrentTimescale(userMessageReader, demo)
66 case EUserMessageTypeDesiredTimescale: 66 case EUserMessageTypeDesiredTimescale:
67 svcUserMessage.parseDesiredTimescale(userMessageReader) 67 svcUserMessage.parseDesiredTimescale(userMessageReader, demo)
68 case EUserMessageTypeMPMapCompleted: 68 case EUserMessageTypeMPMapCompleted:
69 svcUserMessage.parseMpMapCompleted(userMessageReader) 69 svcUserMessage.parseMpMapCompleted(userMessageReader, demo)
70 case EUserMessageTypeMPMapIncomplete: 70 case EUserMessageTypeMPMapIncomplete:
71 svcUserMessage.parseMpMapIncomplete(userMessageReader) 71 svcUserMessage.parseMpMapIncomplete(userMessageReader, demo)
72 case EUserMessageTypeMPTauntEarned: 72 case EUserMessageTypeMPTauntEarned:
73 svcUserMessage.parseMpTauntEarned(userMessageReader) 73 svcUserMessage.parseMpTauntEarned(userMessageReader, demo)
74 case EUserMessageTypeMPTauntLocked: 74 case EUserMessageTypeMPTauntLocked:
75 svcUserMessage.parseMpTauntLocked(userMessageReader) 75 svcUserMessage.parseMpTauntLocked(userMessageReader, demo)
76 case EUserMessageTypePortalFX_Surface: 76 case EUserMessageTypePortalFX_Surface:
77 svcUserMessage.parsePortalFxSurface(userMessageReader) 77 svcUserMessage.parsePortalFxSurface(userMessageReader, demo)
78 case EUserMessageTypePaintWorld: 78 case EUserMessageTypePaintWorld:
79 svcUserMessage.parsePaintWorld(userMessageReader) 79 svcUserMessage.parsePaintWorld(userMessageReader, demo)
80 case EUserMessageTypeTransitionFade: 80 case EUserMessageTypeTransitionFade:
81 svcUserMessage.parseTransitionFade(userMessageReader) 81 svcUserMessage.parseTransitionFade(userMessageReader, demo)
82 case EUserMessageTypeScoreboardTempUpdate: 82 case EUserMessageTypeScoreboardTempUpdate:
83 svcUserMessage.parseScoreboardTempUpdate(userMessageReader) 83 svcUserMessage.parseScoreboardTempUpdate(userMessageReader, demo)
84 default: 84 default:
85 writer.TempAppendLine("\t\t\tData: %v", svcUserMessage.Data) 85 demo.Writer.TempAppendLine("\t\t\tData: %v", svcUserMessage.Data)
86 } 86 }
87 return svcUserMessage 87 return svcUserMessage
88} 88}
89 89
90func (svcUserMessage *SvcUserMessage) parseGeiger(reader *bitreader.Reader) { 90func (svcUserMessage *SvcUserMessage) parseGeiger(reader *bitreader.Reader, demo *types.Demo) {
91 geiger := struct{ Range uint8 }{ 91 geiger := struct{ Range uint8 }{
92 Range: reader.TryReadUInt8(), 92 Range: reader.TryReadUInt8(),
93 } 93 }
94 svcUserMessage.Data = geiger 94 svcUserMessage.Data = geiger
95 writer.TempAppendLine("\t\t\tGeiger Range: %d", geiger.Range) 95 demo.Writer.TempAppendLine("\t\t\tGeiger Range: %d", geiger.Range)
96} 96}
97 97
98func (svcUserMessage *SvcUserMessage) parseTrain(reader *bitreader.Reader) { 98func (svcUserMessage *SvcUserMessage) parseTrain(reader *bitreader.Reader, demo *types.Demo) {
99 train := struct{ Pos uint8 }{ 99 train := struct{ Pos uint8 }{
100 Pos: reader.TryReadUInt8(), 100 Pos: reader.TryReadUInt8(),
101 } 101 }
102 svcUserMessage.Data = train 102 svcUserMessage.Data = train
103 writer.TempAppendLine("\t\t\tPos: %d", train.Pos) 103 demo.Writer.TempAppendLine("\t\t\tPos: %d", train.Pos)
104} 104}
105 105
106func (svcUserMessage *SvcUserMessage) parseHUDText(reader *bitreader.Reader) { 106func (svcUserMessage *SvcUserMessage) parseHUDText(reader *bitreader.Reader, demo *types.Demo) {
107 hudText := struct{ Text string }{ 107 hudText := struct{ Text string }{
108 Text: reader.TryReadString(), 108 Text: reader.TryReadString(),
109 } 109 }
110 svcUserMessage.Data = hudText 110 svcUserMessage.Data = hudText
111 writer.TempAppendLine("\t\t\tText: %s", hudText.Text) 111 demo.Writer.TempAppendLine("\t\t\tText: %s", hudText.Text)
112} 112}
113 113
114func (svcUserMessage *SvcUserMessage) parseSayText(reader *bitreader.Reader) { 114func (svcUserMessage *SvcUserMessage) parseSayText(reader *bitreader.Reader, demo *types.Demo) {
115 sayText := struct { 115 sayText := struct {
116 Client uint8 116 Client uint8 `json:"client"`
117 Message string 117 Message string `json:"message"`
118 WantsToChat bool 118 WantsToChat bool `json:"wants_to_chat"`
119 }{ 119 }{
120 Client: reader.TryReadUInt8(), 120 Client: reader.TryReadUInt8(),
121 Message: reader.TryReadString(), 121 Message: reader.TryReadString(),
122 WantsToChat: reader.TryReadUInt8() != 0, 122 WantsToChat: reader.TryReadUInt8() != 0,
123 } 123 }
124 svcUserMessage.Data = sayText 124 svcUserMessage.Data = sayText
125 writer.TempAppendLine("\t\t\tClient: %d", sayText.Client) 125 demo.Writer.TempAppendLine("\t\t\tClient: %d", sayText.Client)
126 writer.TempAppendLine("\t\t\tMessage: %s", sayText.Message) 126 demo.Writer.TempAppendLine("\t\t\tMessage: %s", sayText.Message)
127 writer.TempAppendLine("\t\t\tWants To Chat: %t", sayText.WantsToChat) 127 demo.Writer.TempAppendLine("\t\t\tWants To Chat: %t", sayText.WantsToChat)
128} 128}
129 129
130func (svcUserMessage *SvcUserMessage) parseSayText2(reader *bitreader.Reader) { 130func (svcUserMessage *SvcUserMessage) parseSayText2(reader *bitreader.Reader, demo *types.Demo) {
131 sayText2 := struct { 131 sayText2 := struct {
132 Client uint8 132 Client uint8 `json:"client"`
133 WantsToChat bool 133 WantsToChat bool `json:"wants_to_chat"`
134 MessageName string 134 MessageName string `json:"message_name"`
135 Messages []string 135 Messages []string `json:"messages"`
136 }{ 136 }{
137 Client: reader.TryReadUInt8(), 137 Client: reader.TryReadUInt8(),
138 WantsToChat: reader.TryReadUInt8() != 0, 138 WantsToChat: reader.TryReadUInt8() != 0,
@@ -140,15 +140,15 @@ func (svcUserMessage *SvcUserMessage) parseSayText2(reader *bitreader.Reader) {
140 Messages: []string{reader.TryReadString(), reader.TryReadString(), reader.TryReadString()}, 140 Messages: []string{reader.TryReadString(), reader.TryReadString(), reader.TryReadString()},
141 } 141 }
142 svcUserMessage.Data = sayText2 142 svcUserMessage.Data = sayText2
143 writer.TempAppendLine("\t\t\tClient: %d", sayText2.Client) 143 demo.Writer.TempAppendLine("\t\t\tClient: %d", sayText2.Client)
144 writer.TempAppendLine("\t\t\tWants To Chat: %t", sayText2.WantsToChat) 144 demo.Writer.TempAppendLine("\t\t\tWants To Chat: %t", sayText2.WantsToChat)
145 writer.TempAppendLine("\t\t\tName: %s", sayText2.MessageName) 145 demo.Writer.TempAppendLine("\t\t\tName: %s", sayText2.MessageName)
146 for index, message := range sayText2.Messages { 146 for index, message := range sayText2.Messages {
147 writer.TempAppendLine("\t\t\tMessage %d: %s", index, message) 147 demo.Writer.TempAppendLine("\t\t\tMessage %d: %s", index, message)
148 } 148 }
149} 149}
150 150
151func (svcUserMessage *SvcUserMessage) parseTextMsg(reader *bitreader.Reader) { 151func (svcUserMessage *SvcUserMessage) parseTextMsg(reader *bitreader.Reader, demo *types.Demo) {
152 const MessageCount int = 5 152 const MessageCount int = 5
153 textMsg := struct { 153 textMsg := struct {
154 Destination uint8 154 Destination uint8
@@ -161,47 +161,57 @@ func (svcUserMessage *SvcUserMessage) parseTextMsg(reader *bitreader.Reader) {
161 textMsg.Messages[i] = reader.TryReadString() 161 textMsg.Messages[i] = reader.TryReadString()
162 } 162 }
163 svcUserMessage.Data = textMsg 163 svcUserMessage.Data = textMsg
164 writer.TempAppendLine("\t\t\tDestination: %d", textMsg.Destination) 164 demo.Writer.TempAppendLine("\t\t\tDestination: %d", textMsg.Destination)
165 for i := 0; i < MessageCount; i++ { 165 for i := 0; i < MessageCount; i++ {
166 writer.TempAppendLine("\t\t\tMessage %d: %s", i+1, textMsg.Messages) 166 demo.Writer.TempAppendLine("\t\t\tMessage %d: %s", i+1, textMsg.Messages)
167 } 167 }
168} 168}
169 169
170func (svcUserMessage *SvcUserMessage) parseHUDMsg(reader *bitreader.Reader) { 170func (svcUserMessage *SvcUserMessage) parseHUDMsg(reader *bitreader.Reader, demo *types.Demo) {
171 const MaxNetMessage uint8 = 6 171 const MaxNetMessage uint8 = 6
172 hudMsg := struct { 172 hudMsg := struct {
173 Channel uint8 173 Channel uint8 `json:"channel"`
174 Info struct { 174 Info struct {
175 X, Y float32 // 0-1 & resolution independent, -1 means center in each dimension 175 X float32 `json:"x"` // 0-1 & resolution independent, -1 means center in each dimension
176 R1, G1, B1, A1 uint8 176 Y float32 `json:"y"`
177 R2, G2, B2, A2 uint8 177 R1 uint8 `json:"r_1"`
178 Effect uint8 178 G1 uint8 `json:"g_1"`
179 FadeIn, FadeOut, HoldTime, FxTime float32 // the fade times seem to be per character 179 B1 uint8 `json:"b_1"`
180 Message string 180 A1 uint8 `json:"a_1"`
181 } 181 R2 uint8 `json:"r_2"`
182 G2 uint8 `json:"g_2"`
183 B2 uint8 `json:"b_2"`
184 A2 uint8 `json:"a_2"`
185 Effect uint8 `json:"effect"`
186 FadeIn float32 `json:"fade_in"` // the fade times seem to be per character
187 FadeOut float32 `json:"fade_out"`
188 HoldTime float32 `json:"hold_time"`
189 FxTime float32 `json:"fx_time"`
190 Message string `json:"message"`
191 } `json:"info"`
182 }{ 192 }{
183 Channel: reader.TryReadUInt8() % MaxNetMessage, 193 Channel: reader.TryReadUInt8() % MaxNetMessage,
184 } 194 }
185 svcUserMessage.Data = hudMsg 195 svcUserMessage.Data = hudMsg
186 writer.TempAppendLine("\t\t\tChannel: %d", hudMsg.Channel) 196 demo.Writer.TempAppendLine("\t\t\tChannel: %d", hudMsg.Channel)
187 if reader.TryReadRemainingBits() >= 148 { 197 if reader.TryReadRemainingBits() >= 148 {
188 hudMsg.Info = struct { 198 hudMsg.Info = struct {
189 X float32 199 X float32 `json:"x"`
190 Y float32 200 Y float32 `json:"y"`
191 R1 uint8 201 R1 uint8 `json:"r_1"`
192 G1 uint8 202 G1 uint8 `json:"g_1"`
193 B1 uint8 203 B1 uint8 `json:"b_1"`
194 A1 uint8 204 A1 uint8 `json:"a_1"`
195 R2 uint8 205 R2 uint8 `json:"r_2"`
196 G2 uint8 206 G2 uint8 `json:"g_2"`
197 B2 uint8 207 B2 uint8 `json:"b_2"`
198 A2 uint8 208 A2 uint8 `json:"a_2"`
199 Effect uint8 209 Effect uint8 `json:"effect"`
200 FadeIn float32 210 FadeIn float32 `json:"fade_in"`
201 FadeOut float32 211 FadeOut float32 `json:"fade_out"`
202 HoldTime float32 212 HoldTime float32 `json:"hold_time"`
203 FxTime float32 213 FxTime float32 `json:"fx_time"`
204 Message string 214 Message string `json:"message"`
205 }{ 215 }{
206 X: reader.TryReadFloat32(), 216 X: reader.TryReadFloat32(),
207 Y: reader.TryReadFloat32(), 217 Y: reader.TryReadFloat32(),
@@ -221,27 +231,27 @@ func (svcUserMessage *SvcUserMessage) parseHUDMsg(reader *bitreader.Reader) {
221 Message: reader.TryReadString(), 231 Message: reader.TryReadString(),
222 } 232 }
223 svcUserMessage.Data = hudMsg 233 svcUserMessage.Data = hudMsg
224 writer.TempAppendLine("\t\t\tX: %f, Y: %f", hudMsg.Info.X, hudMsg.Info.Y) 234 demo.Writer.TempAppendLine("\t\t\tX: %f, Y: %f", hudMsg.Info.X, hudMsg.Info.Y)
225 writer.TempAppendLine("\t\t\tRGBA1: %3d %3d %3d %3d", hudMsg.Info.R1, hudMsg.Info.G1, hudMsg.Info.B1, hudMsg.Info.A1) 235 demo.Writer.TempAppendLine("\t\t\tRGBA1: %3d %3d %3d %3d", hudMsg.Info.R1, hudMsg.Info.G1, hudMsg.Info.B1, hudMsg.Info.A1)
226 writer.TempAppendLine("\t\t\tRGBA2: %3d %3d %3d %3d", hudMsg.Info.R2, hudMsg.Info.G2, hudMsg.Info.B2, hudMsg.Info.A2) 236 demo.Writer.TempAppendLine("\t\t\tRGBA2: %3d %3d %3d %3d", hudMsg.Info.R2, hudMsg.Info.G2, hudMsg.Info.B2, hudMsg.Info.A2)
227 writer.TempAppendLine("\t\t\tEffect: %d", hudMsg.Info.Effect) 237 demo.Writer.TempAppendLine("\t\t\tEffect: %d", hudMsg.Info.Effect)
228 writer.TempAppendLine("\t\t\tFade In: %f", hudMsg.Info.FadeIn) 238 demo.Writer.TempAppendLine("\t\t\tFade In: %f", hudMsg.Info.FadeIn)
229 writer.TempAppendLine("\t\t\tFade Out: %f", hudMsg.Info.FadeOut) 239 demo.Writer.TempAppendLine("\t\t\tFade Out: %f", hudMsg.Info.FadeOut)
230 writer.TempAppendLine("\t\t\tHold Time: %f", hudMsg.Info.HoldTime) 240 demo.Writer.TempAppendLine("\t\t\tHold Time: %f", hudMsg.Info.HoldTime)
231 writer.TempAppendLine("\t\t\tFX Time: %f", hudMsg.Info.FxTime) 241 demo.Writer.TempAppendLine("\t\t\tFX Time: %f", hudMsg.Info.FxTime)
232 writer.TempAppendLine("\t\t\tMessage: %s", hudMsg.Info.Message) 242 demo.Writer.TempAppendLine("\t\t\tMessage: %s", hudMsg.Info.Message)
233 } 243 }
234} 244}
235 245
236func (svcUserMessage *SvcUserMessage) parseResetHUD(reader *bitreader.Reader) { 246func (svcUserMessage *SvcUserMessage) parseResetHUD(reader *bitreader.Reader, demo *types.Demo) {
237 resetHUD := struct{ Unknown uint8 }{ 247 resetHUD := struct{ Unknown uint8 }{
238 Unknown: reader.TryReadUInt8(), 248 Unknown: reader.TryReadUInt8(),
239 } 249 }
240 svcUserMessage.Data = resetHUD 250 svcUserMessage.Data = resetHUD
241 writer.TempAppendLine("\t\t\tUnknown: %d", resetHUD.Unknown) 251 demo.Writer.TempAppendLine("\t\t\tUnknown: %d", resetHUD.Unknown)
242} 252}
243 253
244func (svcUserMessage *SvcUserMessage) parseShake(reader *bitreader.Reader) { 254func (svcUserMessage *SvcUserMessage) parseShake(reader *bitreader.Reader, demo *types.Demo) {
245 type ShakeCommand uint8 255 type ShakeCommand uint8
246 const ( 256 const (
247 Start ShakeCommand = iota // Starts the screen shake for all players within the radius. 257 Start ShakeCommand = iota // Starts the screen shake for all players within the radius.
@@ -252,10 +262,10 @@ func (svcUserMessage *SvcUserMessage) parseShake(reader *bitreader.Reader) {
252 NoRumble // Starts a shake that does NOT rumble the controller. 262 NoRumble // Starts a shake that does NOT rumble the controller.
253 ) 263 )
254 shake := struct { 264 shake := struct {
255 Command uint8 265 Command uint8 `json:"command"`
256 Amplitude float32 266 Amplitude float32 `json:"amplitude"`
257 Frequency float32 267 Frequency float32 `json:"frequency"`
258 Duration float32 268 Duration float32 `json:"duration"`
259 }{ 269 }{
260 Command: reader.TryReadUInt8(), 270 Command: reader.TryReadUInt8(),
261 Amplitude: reader.TryReadFloat32(), 271 Amplitude: reader.TryReadFloat32(),
@@ -281,13 +291,13 @@ func (svcUserMessage *SvcUserMessage) parseShake(reader *bitreader.Reader) {
281 } 291 }
282 } 292 }
283 svcUserMessage.Data = shake 293 svcUserMessage.Data = shake
284 writer.TempAppendLine("\t\t\tCommand: %s", shakeCommandToString(ShakeCommand(shake.Command))) 294 demo.Writer.TempAppendLine("\t\t\tCommand: %s", shakeCommandToString(ShakeCommand(shake.Command)))
285 writer.TempAppendLine("\t\t\tAmplitude: %f", shake.Amplitude) 295 demo.Writer.TempAppendLine("\t\t\tAmplitude: %f", shake.Amplitude)
286 writer.TempAppendLine("\t\t\tFrequency: %f", shake.Frequency) 296 demo.Writer.TempAppendLine("\t\t\tFrequency: %f", shake.Frequency)
287 writer.TempAppendLine("\t\t\tDuration: %f", shake.Duration) 297 demo.Writer.TempAppendLine("\t\t\tDuration: %f", shake.Duration)
288} 298}
289 299
290func (svcUserMessage *SvcUserMessage) parseFade(reader *bitreader.Reader) { 300func (svcUserMessage *SvcUserMessage) parseFade(reader *bitreader.Reader, demo *types.Demo) {
291 type FadeFlag uint16 301 type FadeFlag uint16
292 const ( 302 const (
293 None FadeFlag = 0 303 None FadeFlag = 0
@@ -298,13 +308,13 @@ func (svcUserMessage *SvcUserMessage) parseFade(reader *bitreader.Reader) {
298 Purge FadeFlag = 1 << 4 // Purges all other fades, replacing them with this one 308 Purge FadeFlag = 1 << 4 // Purges all other fades, replacing them with this one
299 ) 309 )
300 fade := struct { 310 fade := struct {
301 Duration float32 311 Duration float32 `json:"duration"`
302 HoldTime uint16 312 HoldTime uint16 `json:"hold_time"`
303 Flags uint16 313 Flags uint16 `json:"flags"`
304 R uint8 314 R uint8 `json:"r"`
305 G uint8 315 G uint8 `json:"g"`
306 B uint8 316 B uint8 `json:"b"`
307 A uint8 317 A uint8 `json:"a"`
308 }{ 318 }{
309 Duration: float32(reader.TryReadUInt16()) / float32(1<<9), // might be useful: #define SCREENFADE_FRACBITS 9 319 Duration: float32(reader.TryReadUInt16()) / float32(1<<9), // might be useful: #define SCREENFADE_FRACBITS 9
310 HoldTime: reader.TryReadUInt16(), 320 HoldTime: reader.TryReadUInt16(),
@@ -334,17 +344,17 @@ func (svcUserMessage *SvcUserMessage) parseFade(reader *bitreader.Reader) {
334 return flagStrings 344 return flagStrings
335 } 345 }
336 svcUserMessage.Data = fade 346 svcUserMessage.Data = fade
337 writer.TempAppendLine("\t\t\tDuration: %f", fade.Duration) 347 demo.Writer.TempAppendLine("\t\t\tDuration: %f", fade.Duration)
338 writer.TempAppendLine("\t\t\tHold Time: %d", fade.HoldTime) 348 demo.Writer.TempAppendLine("\t\t\tHold Time: %d", fade.HoldTime)
339 writer.TempAppendLine("\t\t\tFlags: %v", getFlags(FadeFlag(fade.Flags))) 349 demo.Writer.TempAppendLine("\t\t\tFlags: %v", getFlags(FadeFlag(fade.Flags)))
340 writer.TempAppendLine("\t\t\tRGBA: %3d %3d %3d %3d", fade.R, fade.G, fade.B, fade.A) 350 demo.Writer.TempAppendLine("\t\t\tRGBA: %3d %3d %3d %3d", fade.R, fade.G, fade.B, fade.A)
341} 351}
342 352
343func (svcUserMessage *SvcUserMessage) parseVguiMenu(reader *bitreader.Reader) { 353func (svcUserMessage *SvcUserMessage) parseVguiMenu(reader *bitreader.Reader, demo *types.Demo) {
344 vguiMenu := struct { 354 vguiMenu := struct {
345 Message string 355 Message string `json:"message"`
346 Show bool 356 Show bool `json:"show"`
347 KeyValues []map[string]string 357 KeyValues []map[string]string `json:"key_values"`
348 }{ 358 }{
349 Message: reader.TryReadString(), 359 Message: reader.TryReadString(),
350 Show: reader.TryReadUInt8() != 0, 360 Show: reader.TryReadUInt8() != 0,
@@ -354,19 +364,19 @@ func (svcUserMessage *SvcUserMessage) parseVguiMenu(reader *bitreader.Reader) {
354 vguiMenu.KeyValues = append(vguiMenu.KeyValues, map[string]string{"Key": reader.TryReadString(), "Value": reader.TryReadString()}) 364 vguiMenu.KeyValues = append(vguiMenu.KeyValues, map[string]string{"Key": reader.TryReadString(), "Value": reader.TryReadString()})
355 } 365 }
356 svcUserMessage.Data = vguiMenu 366 svcUserMessage.Data = vguiMenu
357 writer.TempAppendLine("\t\t\tMessage: %s", vguiMenu.Message) 367 demo.Writer.TempAppendLine("\t\t\tMessage: %s", vguiMenu.Message)
358 writer.TempAppendLine("\t\t\tShow: %t", vguiMenu.Show) 368 demo.Writer.TempAppendLine("\t\t\tShow: %t", vguiMenu.Show)
359 if len(vguiMenu.KeyValues) > 0 { 369 if len(vguiMenu.KeyValues) > 0 {
360 writer.TempAppendLine("\t\t\t%d Key Value Pairs:", len(vguiMenu.KeyValues)) 370 demo.Writer.TempAppendLine("\t\t\t%d Key Value Pairs:", len(vguiMenu.KeyValues))
361 for _, kv := range vguiMenu.KeyValues { 371 for _, kv := range vguiMenu.KeyValues {
362 writer.TempAppendLine("\t\t\t\t%s: %s", kv["Key"], kv["Value"]) 372 demo.Writer.TempAppendLine("\t\t\t\t%s: %s", kv["Key"], kv["Value"])
363 } 373 }
364 } else { 374 } else {
365 writer.TempAppendLine("\t\t\tNo Key Value Pairs") 375 demo.Writer.TempAppendLine("\t\t\tNo Key Value Pairs")
366 } 376 }
367} 377}
368 378
369func (svcUserMessage *SvcUserMessage) parseRumble(reader *bitreader.Reader) { 379func (svcUserMessage *SvcUserMessage) parseRumble(reader *bitreader.Reader, demo *types.Demo) {
370 type RumbleLookup int8 380 type RumbleLookup int8
371 const ( 381 const (
372 RumbleInvalid RumbleLookup = -1 382 RumbleInvalid RumbleLookup = -1
@@ -418,9 +428,9 @@ func (svcUserMessage *SvcUserMessage) parseRumble(reader *bitreader.Reader) {
418 InitialScale RumbleFlag = 1 << 4 // Data is the initial scale to start this effect ( * 100 ) 428 InitialScale RumbleFlag = 1 << 4 // Data is the initial scale to start this effect ( * 100 )
419 ) 429 )
420 rumble := struct { 430 rumble := struct {
421 Type int8 431 Type int8 `json:"type"`
422 Scale float32 432 Scale float32 `json:"scale"`
423 Flags uint8 433 Flags uint8 `json:"flags"`
424 }{ 434 }{
425 Type: reader.TryReadSInt8(), 435 Type: reader.TryReadSInt8(),
426 Scale: float32(reader.TryReadUInt8()) / 100, 436 Scale: float32(reader.TryReadUInt8()) / 100,
@@ -452,25 +462,25 @@ func (svcUserMessage *SvcUserMessage) parseRumble(reader *bitreader.Reader) {
452 return flagStrings 462 return flagStrings
453 } 463 }
454 svcUserMessage.Data = rumble 464 svcUserMessage.Data = rumble
455 writer.TempAppendLine("\t\t\tType: %s", getRumbleLookup(RumbleLookup(rumble.Type))) 465 demo.Writer.TempAppendLine("\t\t\tType: %s", getRumbleLookup(RumbleLookup(rumble.Type)))
456 writer.TempAppendLine("\t\t\tScale: %f", rumble.Scale) 466 demo.Writer.TempAppendLine("\t\t\tScale: %f", rumble.Scale)
457 writer.TempAppendLine("\t\t\tFlags: %v", getFlags(RumbleFlag(rumble.Flags))) 467 demo.Writer.TempAppendLine("\t\t\tFlags: %v", getFlags(RumbleFlag(rumble.Flags)))
458} 468}
459 469
460func (svcUserMessage *SvcUserMessage) parseBattery(reader *bitreader.Reader) { 470func (svcUserMessage *SvcUserMessage) parseBattery(reader *bitreader.Reader, demo *types.Demo) {
461 battery := struct{ BatteryVal uint16 }{ 471 battery := struct{ BatteryVal uint16 }{
462 BatteryVal: reader.TryReadUInt16(), 472 BatteryVal: reader.TryReadUInt16(),
463 } 473 }
464 svcUserMessage.Data = battery 474 svcUserMessage.Data = battery
465 writer.TempAppendLine("\t\t\tBattery: %d", battery.BatteryVal) 475 demo.Writer.TempAppendLine("\t\t\tBattery: %d", battery.BatteryVal)
466} 476}
467 477
468func (svcUserMessage *SvcUserMessage) parseDamage(reader *bitreader.Reader) { 478func (svcUserMessage *SvcUserMessage) parseDamage(reader *bitreader.Reader, demo *types.Demo) {
469 damage := struct { 479 damage := struct {
470 Armor uint8 480 Armor uint8 `json:"armor"`
471 DamageTaken uint8 481 DamageTaken uint8 `json:"damage_taken"`
472 BitsDamage int32 482 BitsDamage int32 `json:"bits_damage"`
473 VecFrom []float32 483 VecFrom []float32 `json:"vec_from"`
474 }{ 484 }{
475 Armor: reader.TryReadUInt8(), 485 Armor: reader.TryReadUInt8(),
476 DamageTaken: reader.TryReadUInt8(), 486 DamageTaken: reader.TryReadUInt8(),
@@ -478,24 +488,24 @@ func (svcUserMessage *SvcUserMessage) parseDamage(reader *bitreader.Reader) {
478 VecFrom: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 488 VecFrom: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
479 } 489 }
480 svcUserMessage.Data = damage 490 svcUserMessage.Data = damage
481 writer.TempAppendLine("\t\t\tArmor: %d", damage.Armor) 491 demo.Writer.TempAppendLine("\t\t\tArmor: %d", damage.Armor)
482 writer.TempAppendLine("\t\t\tDamage Taken: %d", damage.DamageTaken) 492 demo.Writer.TempAppendLine("\t\t\tDamage Taken: %d", damage.DamageTaken)
483 writer.TempAppendLine("\t\t\tBits Damage: %d", damage.BitsDamage) 493 demo.Writer.TempAppendLine("\t\t\tBits Damage: %d", damage.BitsDamage)
484 writer.TempAppendLine("\t\t\tVecFrom: %v", damage.VecFrom) 494 demo.Writer.TempAppendLine("\t\t\tVecFrom: %v", damage.VecFrom)
485} 495}
486 496
487func (svcUserMessage *SvcUserMessage) parseVoiceMask(reader *bitreader.Reader) { 497func (svcUserMessage *SvcUserMessage) parseVoiceMask(reader *bitreader.Reader, demo *types.Demo) {
488 // const VoiceMaxPlayers = 2 498 // const VoiceMaxPlayers = 2
489 voiceMask := struct { 499 voiceMask := struct {
490 PlayerMasks []struct { 500 PlayerMasks []struct {
491 GameRulesMask int32 501 GameRulesMask int32 `json:"game_rules_mask"`
492 BanMask int32 502 BanMask int32 `json:"ban_mask"`
493 } 503 } `json:"player_masks"`
494 PlayerModEnable bool 504 PlayerModEnable bool `json:"player_mod_enable"`
495 }{ 505 }{
496 PlayerMasks: []struct { 506 PlayerMasks: []struct {
497 GameRulesMask int32 507 GameRulesMask int32 `json:"game_rules_mask"`
498 BanMask int32 508 BanMask int32 `json:"ban_mask"`
499 }{ 509 }{
500 { 510 {
501 GameRulesMask: reader.TryReadSInt32(), 511 GameRulesMask: reader.TryReadSInt32(),
@@ -509,15 +519,15 @@ func (svcUserMessage *SvcUserMessage) parseVoiceMask(reader *bitreader.Reader) {
509 PlayerModEnable: reader.TryReadUInt8() != 0, 519 PlayerModEnable: reader.TryReadUInt8() != 0,
510 } 520 }
511 svcUserMessage.Data = voiceMask 521 svcUserMessage.Data = voiceMask
512 writer.TempAppendLine("\t\t\tPlayer Masks:") 522 demo.Writer.TempAppendLine("\t\t\tPlayer Masks:")
513 writer.TempAppendLine("\t\t\t\t[0] Game Rules Mask: %d", voiceMask.PlayerMasks[0].GameRulesMask) 523 demo.Writer.TempAppendLine("\t\t\t\t[0] Game Rules Mask: %d", voiceMask.PlayerMasks[0].GameRulesMask)
514 writer.TempAppendLine("\t\t\t\t[0] Ban Mask: %d", voiceMask.PlayerMasks[0].BanMask) 524 demo.Writer.TempAppendLine("\t\t\t\t[0] Ban Mask: %d", voiceMask.PlayerMasks[0].BanMask)
515 writer.TempAppendLine("\t\t\t\t[1] Game Rules Mask: %d", voiceMask.PlayerMasks[1].GameRulesMask) 525 demo.Writer.TempAppendLine("\t\t\t\t[1] Game Rules Mask: %d", voiceMask.PlayerMasks[1].GameRulesMask)
516 writer.TempAppendLine("\t\t\t\t[1] Ban Mask: %d", voiceMask.PlayerMasks[1].BanMask) 526 demo.Writer.TempAppendLine("\t\t\t\t[1] Ban Mask: %d", voiceMask.PlayerMasks[1].BanMask)
517 writer.TempAppendLine("\t\t\t\tPlayer Mod Enable: %t", voiceMask.PlayerModEnable) 527 demo.Writer.TempAppendLine("\t\t\t\tPlayer Mod Enable: %t", voiceMask.PlayerModEnable)
518} 528}
519 529
520func (svcUserMessage *SvcUserMessage) parseCloseCaption(reader *bitreader.Reader) { 530func (svcUserMessage *SvcUserMessage) parseCloseCaption(reader *bitreader.Reader, demo *types.Demo) {
521 type CloseCaptionFlag uint8 531 type CloseCaptionFlag uint8
522 const ( 532 const (
523 None CloseCaptionFlag = 0 533 None CloseCaptionFlag = 0
@@ -527,9 +537,9 @@ func (svcUserMessage *SvcUserMessage) parseCloseCaption(reader *bitreader.Reader
527 GenderFemale CloseCaptionFlag = 1 << 3 537 GenderFemale CloseCaptionFlag = 1 << 3
528 ) 538 )
529 closeCaption := struct { 539 closeCaption := struct {
530 TokenName string 540 TokenName string `json:"token_name"`
531 Duration float32 541 Duration float32 `json:"duration"`
532 Flags uint8 542 Flags uint8 `json:"flags"`
533 }{ 543 }{
534 TokenName: reader.TryReadString(), 544 TokenName: reader.TryReadString(),
535 Duration: float32(reader.TryReadSInt16()) * 0.1, 545 Duration: float32(reader.TryReadSInt16()) * 0.1,
@@ -552,54 +562,58 @@ func (svcUserMessage *SvcUserMessage) parseCloseCaption(reader *bitreader.Reader
552 return flagStrings 562 return flagStrings
553 } 563 }
554 svcUserMessage.Data = closeCaption 564 svcUserMessage.Data = closeCaption
555 writer.TempAppendLine("\t\t\tToken Name: %s", closeCaption.TokenName) 565 demo.Writer.TempAppendLine("\t\t\tToken Name: %s", closeCaption.TokenName)
556 writer.TempAppendLine("\t\t\tDuration: %f", closeCaption.Duration) 566 demo.Writer.TempAppendLine("\t\t\tDuration: %f", closeCaption.Duration)
557 writer.TempAppendLine("\t\t\tFlags: %v", getFlags(CloseCaptionFlag(closeCaption.Flags))) 567 demo.Writer.TempAppendLine("\t\t\tFlags: %v", getFlags(CloseCaptionFlag(closeCaption.Flags)))
558} 568}
559 569
560func (svcUserMessage *SvcUserMessage) parseKeyHintText(reader *bitreader.Reader) { 570func (svcUserMessage *SvcUserMessage) parseKeyHintText(reader *bitreader.Reader, demo *types.Demo) {
561 keyHintText := struct { 571 keyHintText := struct {
562 Count uint8 572 Count uint8 `json:"count"`
563 KeyString string 573 KeyString string `json:"key_string"`
564 }{ 574 }{
565 Count: reader.TryReadUInt8(), 575 Count: reader.TryReadUInt8(),
566 KeyString: reader.TryReadString(), 576 KeyString: reader.TryReadString(),
567 } 577 }
568 svcUserMessage.Data = keyHintText 578 svcUserMessage.Data = keyHintText
569 writer.TempAppendLine("\t\t\tCount: %d", keyHintText.Count) 579 demo.Writer.TempAppendLine("\t\t\tCount: %d", keyHintText.Count)
570 writer.TempAppendLine("\t\t\tString: %s", keyHintText.KeyString) 580 demo.Writer.TempAppendLine("\t\t\tString: %s", keyHintText.KeyString)
571} 581}
572 582
573func (svcUserMessage *SvcUserMessage) parseLogoTimeMsg(reader *bitreader.Reader) { 583func (svcUserMessage *SvcUserMessage) parseLogoTimeMsg(reader *bitreader.Reader, demo *types.Demo) {
574 logoTimeMsg := struct{ Time float32 }{ 584 logoTimeMsg := struct {
585 Time float32 `json:"time"`
586 }{
575 Time: reader.TryReadFloat32(), 587 Time: reader.TryReadFloat32(),
576 } 588 }
577 svcUserMessage.Data = logoTimeMsg 589 svcUserMessage.Data = logoTimeMsg
578 writer.TempAppendLine("\t\t\tTime: %f", logoTimeMsg.Time) 590 demo.Writer.TempAppendLine("\t\t\tTime: %f", logoTimeMsg.Time)
579} 591}
580 592
581func (svcUserMessage *SvcUserMessage) parseAchivementEvent(reader *bitreader.Reader) { 593func (svcUserMessage *SvcUserMessage) parseAchivementEvent(reader *bitreader.Reader, demo *types.Demo) {
582 achivementEvent := struct{ AchivementID int32 }{ 594 achivementEvent := struct{ AchivementID int32 }{
583 AchivementID: reader.TryReadSInt32(), 595 AchivementID: reader.TryReadSInt32(),
584 } 596 }
585 svcUserMessage.Data = achivementEvent 597 svcUserMessage.Data = achivementEvent
586 writer.TempAppendLine("\t\t\tAchivement ID: %d", achivementEvent.AchivementID) 598 demo.Writer.TempAppendLine("\t\t\tAchivement ID: %d", achivementEvent.AchivementID)
587} 599}
588 600
589func (svcUserMessage *SvcUserMessage) parseCurrentTimescale(reader *bitreader.Reader) { 601func (svcUserMessage *SvcUserMessage) parseCurrentTimescale(reader *bitreader.Reader, demo *types.Demo) {
590 currentTimescale := struct{ Timescale float32 }{ 602 currentTimescale := struct {
603 Timescale float32 `json:"timescale"`
604 }{
591 Timescale: reader.TryReadFloat32(), 605 Timescale: reader.TryReadFloat32(),
592 } 606 }
593 svcUserMessage.Data = currentTimescale 607 svcUserMessage.Data = currentTimescale
594 writer.TempAppendLine("\t\t\tTimescale: %f", currentTimescale.Timescale) 608 demo.Writer.TempAppendLine("\t\t\tTimescale: %f", currentTimescale.Timescale)
595} 609}
596 610
597func (svcUserMessage *SvcUserMessage) parseDesiredTimescale(reader *bitreader.Reader) { 611func (svcUserMessage *SvcUserMessage) parseDesiredTimescale(reader *bitreader.Reader, demo *types.Demo) {
598 desiredTimescale := struct { 612 desiredTimescale := struct {
599 Unk1 float32 613 Unk1 float32 `json:"unk_1"`
600 Unk2 float32 614 Unk2 float32 `json:"unk_2"`
601 Unk3 uint8 615 Unk3 uint8 `json:"unk_3"`
602 Unk4 float32 616 Unk4 float32 `json:"unk_4"`
603 }{ 617 }{
604 Unk1: reader.TryReadFloat32(), 618 Unk1: reader.TryReadFloat32(),
605 Unk2: reader.TryReadFloat32(), 619 Unk2: reader.TryReadFloat32(),
@@ -607,49 +621,52 @@ func (svcUserMessage *SvcUserMessage) parseDesiredTimescale(reader *bitreader.Re
607 Unk4: reader.TryReadFloat32(), 621 Unk4: reader.TryReadFloat32(),
608 } 622 }
609 svcUserMessage.Data = desiredTimescale 623 svcUserMessage.Data = desiredTimescale
610 writer.TempAppendLine("\t\t\tUnk1: %f", desiredTimescale.Unk1) 624 demo.Writer.TempAppendLine("\t\t\tUnk1: %f", desiredTimescale.Unk1)
611 writer.TempAppendLine("\t\t\tUnk2: %f", desiredTimescale.Unk2) 625 demo.Writer.TempAppendLine("\t\t\tUnk2: %f", desiredTimescale.Unk2)
612 writer.TempAppendLine("\t\t\tUnk3: %d", desiredTimescale.Unk3) 626 demo.Writer.TempAppendLine("\t\t\tUnk3: %d", desiredTimescale.Unk3)
613 writer.TempAppendLine("\t\t\tUnk4: %f", desiredTimescale.Unk4) 627 demo.Writer.TempAppendLine("\t\t\tUnk4: %f", desiredTimescale.Unk4)
614} 628}
615 629
616func (svcUserMessage *SvcUserMessage) parseMpMapCompleted(reader *bitreader.Reader) { 630func (svcUserMessage *SvcUserMessage) parseMpMapCompleted(reader *bitreader.Reader, demo *types.Demo) {
617 mpMapCompleted := struct { 631 mpMapCompleted := struct {
618 Branch uint8 632 Branch uint8 `json:"branch"`
619 Level uint8 633 Level uint8 `json:"level"`
620 }{ 634 }{
621 Branch: reader.TryReadUInt8(), 635 Branch: reader.TryReadUInt8(),
622 Level: reader.TryReadUInt8(), 636 Level: reader.TryReadUInt8(),
623 } 637 }
624 svcUserMessage.Data = mpMapCompleted 638 svcUserMessage.Data = mpMapCompleted
625 writer.TempAppendLine("\t\t\tBranch: %d", mpMapCompleted.Branch) 639 demo.Writer.TempAppendLine("\t\t\tBranch: %d", mpMapCompleted.Branch)
626 writer.TempAppendLine("\t\t\tLevel: %d", mpMapCompleted.Level) 640 demo.Writer.TempAppendLine("\t\t\tLevel: %d", mpMapCompleted.Level)
627} 641}
628 642
629func (svcUserMessage *SvcUserMessage) parseMpMapIncomplete(reader *bitreader.Reader) {} 643func (svcUserMessage *SvcUserMessage) parseMpMapIncomplete(reader *bitreader.Reader, demo *types.Demo) {
644}
630 645
631func (svcUserMessage *SvcUserMessage) parseMpTauntEarned(reader *bitreader.Reader) { 646func (svcUserMessage *SvcUserMessage) parseMpTauntEarned(reader *bitreader.Reader, demo *types.Demo) {
632 mpTauntEarned := struct { 647 mpTauntEarned := struct {
633 TauntName string 648 TauntName string `json:"taunt_name"`
634 AwardSilently bool 649 AwardSilently bool `json:"award_silently"`
635 }{ 650 }{
636 TauntName: reader.TryReadString(), 651 TauntName: reader.TryReadString(),
637 AwardSilently: reader.TryReadBool(), 652 AwardSilently: reader.TryReadBool(),
638 } 653 }
639 svcUserMessage.Data = mpTauntEarned 654 svcUserMessage.Data = mpTauntEarned
640 writer.TempAppendLine("\t\t\tTaunt Name: %s", mpTauntEarned.TauntName) 655 demo.Writer.TempAppendLine("\t\t\tTaunt Name: %s", mpTauntEarned.TauntName)
641 writer.TempAppendLine("\t\t\tAward Silently: %t", mpTauntEarned.AwardSilently) 656 demo.Writer.TempAppendLine("\t\t\tAward Silently: %t", mpTauntEarned.AwardSilently)
642} 657}
643 658
644func (svcUserMessage *SvcUserMessage) parseMpTauntLocked(reader *bitreader.Reader) { 659func (svcUserMessage *SvcUserMessage) parseMpTauntLocked(reader *bitreader.Reader, demo *types.Demo) {
645 mpTauntLocked := struct{ TauntName string }{ 660 mpTauntLocked := struct {
661 TauntName string `json:"taunt_name"`
662 }{
646 TauntName: reader.TryReadString(), 663 TauntName: reader.TryReadString(),
647 } 664 }
648 svcUserMessage.Data = mpTauntLocked 665 svcUserMessage.Data = mpTauntLocked
649 writer.TempAppendLine("\t\t\tTaunt Name: %s", mpTauntLocked.TauntName) 666 demo.Writer.TempAppendLine("\t\t\tTaunt Name: %s", mpTauntLocked.TauntName)
650} 667}
651 668
652func (svcUserMessage *SvcUserMessage) parsePortalFxSurface(reader *bitreader.Reader) { 669func (svcUserMessage *SvcUserMessage) parsePortalFxSurface(reader *bitreader.Reader, demo *types.Demo) {
653 type PortalFizzleType int8 670 type PortalFizzleType int8
654 const ( 671 const (
655 PortalFizzleSuccess PortalFizzleType = iota // Placed fine (no fizzle) 672 PortalFizzleSuccess PortalFizzleType = iota // Placed fine (no fizzle)
@@ -693,13 +710,13 @@ func (svcUserMessage *SvcUserMessage) parsePortalFxSurface(reader *bitreader.Rea
693 } 710 }
694 } 711 }
695 portalFxSurface := struct { 712 portalFxSurface := struct {
696 PortalEnt uint16 713 PortalEnt uint16 `json:"portal_ent"`
697 OwnerEnt uint16 714 OwnerEnt uint16 `json:"owner_ent"`
698 Team uint8 715 Team uint8 `json:"team"`
699 PortalNum uint8 716 PortalNum uint8 `json:"portal_num"`
700 Effect uint8 717 Effect uint8 `json:"effect"`
701 Origin []float32 718 Origin []float32 `json:"origin"`
702 Angles []float32 719 Angles []float32 `json:"angles"`
703 }{ 720 }{
704 PortalEnt: reader.TryReadUInt16(), 721 PortalEnt: reader.TryReadUInt16(),
705 OwnerEnt: reader.TryReadUInt16(), 722 OwnerEnt: reader.TryReadUInt16(),
@@ -743,23 +760,23 @@ func (svcUserMessage *SvcUserMessage) parsePortalFxSurface(reader *bitreader.Rea
743 } 760 }
744 svcUserMessage.Data = portalFxSurface 761 svcUserMessage.Data = portalFxSurface
745 _ = getPortalFizzleType(PortalFizzleType(2)) 762 _ = getPortalFizzleType(PortalFizzleType(2))
746 writer.TempAppendLine("\t\t\tPortal Entity: %d", portalFxSurface.PortalEnt) 763 demo.Writer.TempAppendLine("\t\t\tPortal Entity: %d", portalFxSurface.PortalEnt)
747 writer.TempAppendLine("\t\t\tOwner Entity: %d", portalFxSurface.OwnerEnt) 764 demo.Writer.TempAppendLine("\t\t\tOwner Entity: %d", portalFxSurface.OwnerEnt)
748 writer.TempAppendLine("\t\t\tTeam: %d", portalFxSurface.Team) 765 demo.Writer.TempAppendLine("\t\t\tTeam: %d", portalFxSurface.Team)
749 writer.TempAppendLine("\t\t\tPortal Number: %d", portalFxSurface.PortalNum) 766 demo.Writer.TempAppendLine("\t\t\tPortal Number: %d", portalFxSurface.PortalNum)
750 writer.TempAppendLine("\t\t\tEffect: %s", getPortalFizzleType(PortalFizzleType(portalFxSurface.Effect))) 767 demo.Writer.TempAppendLine("\t\t\tEffect: %s", getPortalFizzleType(PortalFizzleType(portalFxSurface.Effect)))
751 writer.TempAppendLine("\t\t\tOrigin: %v", portalFxSurface.Origin) 768 demo.Writer.TempAppendLine("\t\t\tOrigin: %v", portalFxSurface.Origin)
752 writer.TempAppendLine("\t\t\tAngles: %v", portalFxSurface.Angles) 769 demo.Writer.TempAppendLine("\t\t\tAngles: %v", portalFxSurface.Angles)
753} 770}
754 771
755func (svcUserMessage *SvcUserMessage) parsePaintWorld(reader *bitreader.Reader) { 772func (svcUserMessage *SvcUserMessage) parsePaintWorld(reader *bitreader.Reader, demo *types.Demo) {
756 paintWorld := struct { 773 paintWorld := struct {
757 Type uint8 774 Type uint8 `json:"type"`
758 EHandle uint32 775 EHandle uint32 `json:"e_handle"`
759 UnkHf1 float32 776 UnkHf1 float32 `json:"unk_hf_1"`
760 UnkHf2 float32 777 UnkHf2 float32 `json:"unk_hf_2"`
761 Center []float32 778 Center []float32 `json:"center"`
762 Positions [][]float32 779 Positions [][]float32 `json:"positions"`
763 }{ 780 }{
764 Type: reader.TryReadUInt8(), 781 Type: reader.TryReadUInt8(),
765 EHandle: reader.TryReadUInt32(), 782 EHandle: reader.TryReadUInt32(),
@@ -775,37 +792,37 @@ func (svcUserMessage *SvcUserMessage) parsePaintWorld(reader *bitreader.Reader)
775 paintWorld.Positions[i] = []float32{paintWorld.Center[0] + float32(reader.TryReadSInt16()), paintWorld.Center[1] + float32(reader.TryReadSInt16()), paintWorld.Center[2] + float32(reader.TryReadSInt16())} 792 paintWorld.Positions[i] = []float32{paintWorld.Center[0] + float32(reader.TryReadSInt16()), paintWorld.Center[1] + float32(reader.TryReadSInt16()), paintWorld.Center[2] + float32(reader.TryReadSInt16())}
776 } 793 }
777 svcUserMessage.Data = paintWorld 794 svcUserMessage.Data = paintWorld
778 writer.TempAppendLine("\t\t\tType: %d", paintWorld.Type) 795 demo.Writer.TempAppendLine("\t\t\tType: %d", paintWorld.Type)
779 writer.TempAppendLine("\t\t\tEHandle: %d", paintWorld.EHandle) 796 demo.Writer.TempAppendLine("\t\t\tEHandle: %d", paintWorld.EHandle)
780 writer.TempAppendLine("\t\t\tUnkHf1: %f", paintWorld.UnkHf1) 797 demo.Writer.TempAppendLine("\t\t\tUnkHf1: %f", paintWorld.UnkHf1)
781 writer.TempAppendLine("\t\t\tUnkHf2: %f", paintWorld.UnkHf2) 798 demo.Writer.TempAppendLine("\t\t\tUnkHf2: %f", paintWorld.UnkHf2)
782 writer.TempAppendLine("\t\t\tCenter: %v", paintWorld.Center) 799 demo.Writer.TempAppendLine("\t\t\tCenter: %v", paintWorld.Center)
783 writer.TempAppendLine("\t\t\tPositions: %v", paintWorld.Positions) 800 demo.Writer.TempAppendLine("\t\t\tPositions: %v", paintWorld.Positions)
784} 801}
785 802
786func (svcUserMessage *SvcUserMessage) parseTransitionFade(reader *bitreader.Reader) { 803func (svcUserMessage *SvcUserMessage) parseTransitionFade(reader *bitreader.Reader, demo *types.Demo) {
787 transitionFade := struct { 804 transitionFade := struct {
788 Seconds float32 805 Seconds float32 `json:"seconds"`
789 }{ 806 }{
790 Seconds: reader.TryReadFloat32(), 807 Seconds: reader.TryReadFloat32(),
791 } 808 }
792 svcUserMessage.Data = transitionFade 809 svcUserMessage.Data = transitionFade
793 writer.TempAppendLine("\t\t\tSeconds: %f", transitionFade.Seconds) 810 demo.Writer.TempAppendLine("\t\t\tSeconds: %f", transitionFade.Seconds)
794} 811}
795 812
796func (svcUserMessage *SvcUserMessage) parseScoreboardTempUpdate(reader *bitreader.Reader) { 813func (svcUserMessage *SvcUserMessage) parseScoreboardTempUpdate(reader *bitreader.Reader, demo *types.Demo) {
797 scoreboardTempUpdate := struct { 814 scoreboardTempUpdate := struct {
798 NumPortals int32 815 NumPortals int32 `json:"num_portals"`
799 TimeTaken int32 816 TimeTaken int32 `json:"time_taken"`
800 }{ 817 }{
801 NumPortals: reader.TryReadSInt32(), 818 NumPortals: reader.TryReadSInt32(),
802 TimeTaken: reader.TryReadSInt32(), 819 TimeTaken: reader.TryReadSInt32(),
803 } 820 }
804 svcUserMessage.Data = scoreboardTempUpdate 821 svcUserMessage.Data = scoreboardTempUpdate
805 writer.TempAppendLine("\t\t\tPortal Count: %d", scoreboardTempUpdate.NumPortals) 822 demo.Writer.TempAppendLine("\t\t\tPortal Count: %d", scoreboardTempUpdate.NumPortals)
806 writer.TempAppendLine("\t\t\tTime Taken: %.2f", float32(scoreboardTempUpdate.TimeTaken)/100.0) 823 demo.Writer.TempAppendLine("\t\t\tTime Taken: %.2f", float32(scoreboardTempUpdate.TimeTaken)/100.0)
807 824
808 writer.TempAppendLine("\t\t\tTicks Taken: %d", int(math.Round(float64((float32(scoreboardTempUpdate.TimeTaken)/100.0)/float32(1.0/60.0))))) 825 demo.Writer.TempAppendLine("\t\t\tTicks Taken: %d", int(math.Round(float64((float32(scoreboardTempUpdate.TimeTaken)/100.0)/float32(1.0/60.0)))))
809} 826}
810 827
811type UserMessageType uint8 828type UserMessageType uint8
diff --git a/pkg/messages/types/svcVoiceData.go b/pkg/messages/types/svcVoiceData.go
index 30436eb..dbc07a6 100644
--- a/pkg/messages/types/svcVoiceData.go
+++ b/pkg/messages/types/svcVoiceData.go
@@ -2,17 +2,17 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcVoiceData struct { 8type SvcVoiceData struct {
9 FromClient uint8 9 FromClient uint8 `json:"from_client"`
10 Proximity bool 10 Proximity bool `json:"proximity"`
11 Length int16 11 Length int16 `json:"length"`
12 Data []byte 12 Data []byte `json:"data"`
13} 13}
14 14
15func ParseSvcVoiceData(reader *bitreader.Reader) SvcVoiceData { 15func ParseSvcVoiceData(reader *bitreader.Reader, demo *types.Demo) SvcVoiceData {
16 svcVoiceData := SvcVoiceData{ 16 svcVoiceData := SvcVoiceData{
17 FromClient: reader.TryReadUInt8(), 17 FromClient: reader.TryReadUInt8(),
18 } 18 }
@@ -21,8 +21,8 @@ func ParseSvcVoiceData(reader *bitreader.Reader) SvcVoiceData {
21 svcVoiceData.Proximity = true 21 svcVoiceData.Proximity = true
22 } 22 }
23 svcVoiceData.Data = reader.TryReadBitsToSlice(uint64(svcVoiceData.Length)) 23 svcVoiceData.Data = reader.TryReadBitsToSlice(uint64(svcVoiceData.Length))
24 writer.TempAppendLine("\t\tFrom Client: %d", svcVoiceData.FromClient) 24 demo.Writer.TempAppendLine("\t\tFrom Client: %d", svcVoiceData.FromClient)
25 writer.TempAppendLine("\t\tProximity: %t", svcVoiceData.Proximity) 25 demo.Writer.TempAppendLine("\t\tProximity: %t", svcVoiceData.Proximity)
26 writer.TempAppendLine("\t\tData: %v", svcVoiceData.Data) 26 demo.Writer.TempAppendLine("\t\tData: %v", svcVoiceData.Data)
27 return svcVoiceData 27 return svcVoiceData
28} 28}
diff --git a/pkg/messages/types/svcVoiceInit.go b/pkg/messages/types/svcVoiceInit.go
index bdab51a..1baa971 100644
--- a/pkg/messages/types/svcVoiceInit.go
+++ b/pkg/messages/types/svcVoiceInit.go
@@ -2,16 +2,16 @@ package messages
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type SvcVoiceInit struct { 8type SvcVoiceInit struct {
9 Codec string 9 Codec string `json:"codec"`
10 Quality uint8 10 Quality uint8 `json:"quality"`
11 SampleRate int32 11 SampleRate int32 `json:"sample_rate"`
12} 12}
13 13
14func ParseSvcVoiceInit(reader *bitreader.Reader) SvcVoiceInit { 14func ParseSvcVoiceInit(reader *bitreader.Reader, demo *types.Demo) SvcVoiceInit {
15 svcVoiceInit := SvcVoiceInit{ 15 svcVoiceInit := SvcVoiceInit{
16 Codec: reader.TryReadString(), 16 Codec: reader.TryReadString(),
17 Quality: reader.TryReadUInt8(), 17 Quality: reader.TryReadUInt8(),
@@ -25,8 +25,8 @@ func ParseSvcVoiceInit(reader *bitreader.Reader) SvcVoiceInit {
25 svcVoiceInit.SampleRate = 11025 25 svcVoiceInit.SampleRate = 11025
26 } 26 }
27 } 27 }
28 writer.TempAppendLine("\t\tCodec: %s", svcVoiceInit.Codec) 28 demo.Writer.TempAppendLine("\t\tCodec: %s", svcVoiceInit.Codec)
29 writer.TempAppendLine("\t\tQuality: %d", svcVoiceInit.Quality) 29 demo.Writer.TempAppendLine("\t\tQuality: %d", svcVoiceInit.Quality)
30 writer.TempAppendLine("\t\tSample Rate: %d", svcVoiceInit.SampleRate) 30 demo.Writer.TempAppendLine("\t\tSample Rate: %d", svcVoiceInit.SampleRate)
31 return svcVoiceInit 31 return svcVoiceInit
32} 32}
diff --git a/pkg/packets/headers.go b/pkg/packets/headers.go
index 6c5ab10..bee8ddf 100644
--- a/pkg/packets/headers.go
+++ b/pkg/packets/headers.go
@@ -2,25 +2,11 @@ package packets
2 2
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/writer" 5 "github.com/pektezol/sdp.go/pkg/types"
6) 6)
7 7
8type Headers struct { 8func ParseHeaders(reader *bitreader.Reader, demo *types.Demo) types.Headers {
9 DemoFileStamp string 9 headers := types.Headers{
10 DemoProtocol int32
11 NetworkProtocol int32
12 ServerName string
13 ClientName string
14 MapName string
15 GameDirectory string
16 PlaybackTime float32
17 PlaybackTicks int32
18 PlaybackFrames int32
19 SignOnLength int32
20}
21
22func ParseHeaders(reader *bitreader.Reader) Headers {
23 headers := Headers{
24 DemoFileStamp: reader.TryReadString(), 10 DemoFileStamp: reader.TryReadString(),
25 DemoProtocol: int32(reader.TryReadSInt32()), 11 DemoProtocol: int32(reader.TryReadSInt32()),
26 NetworkProtocol: int32(reader.TryReadSInt32()), 12 NetworkProtocol: int32(reader.TryReadSInt32()),
@@ -42,16 +28,16 @@ func ParseHeaders(reader *bitreader.Reader) Headers {
42 if headers.NetworkProtocol != 2001 { 28 if headers.NetworkProtocol != 2001 {
43 panic("this parser only supports demos from portal 2") 29 panic("this parser only supports demos from portal 2")
44 } 30 }
45 writer.AppendLine("\nDemo File Stamp: %s", headers.DemoFileStamp) 31 demo.Writer.AppendLine("\nDemo File Stamp: %s", headers.DemoFileStamp)
46 writer.AppendLine("Demo Protocol: %d", headers.DemoProtocol) 32 demo.Writer.AppendLine("Demo Protocol: %d", headers.DemoProtocol)
47 writer.AppendLine("Network Protocol: %d", headers.NetworkProtocol) 33 demo.Writer.AppendLine("Network Protocol: %d", headers.NetworkProtocol)
48 writer.AppendLine("Server Name: %s", headers.ServerName) 34 demo.Writer.AppendLine("Server Name: %s", headers.ServerName)
49 writer.AppendLine("Client Name: %s", headers.ClientName) 35 demo.Writer.AppendLine("Client Name: %s", headers.ClientName)
50 writer.AppendLine("Map Name: %s", headers.MapName) 36 demo.Writer.AppendLine("Map Name: %s", headers.MapName)
51 writer.AppendLine("Game Directory: %s", headers.GameDirectory) 37 demo.Writer.AppendLine("Game Directory: %s", headers.GameDirectory)
52 writer.AppendLine("Playback Time: %f", headers.PlaybackTime) 38 demo.Writer.AppendLine("Playback Time: %f", headers.PlaybackTime)
53 writer.AppendLine("Playback Ticks: %d", headers.PlaybackTicks) 39 demo.Writer.AppendLine("Playback Ticks: %d", headers.PlaybackTicks)
54 writer.AppendLine("Playback Frames: %d", headers.PlaybackFrames) 40 demo.Writer.AppendLine("Playback Frames: %d", headers.PlaybackFrames)
55 writer.AppendLine("Sign On Length: %d\n", headers.SignOnLength) 41 demo.Writer.AppendLine("Sign On Length: %d\n", headers.SignOnLength)
56 return headers 42 return headers
57} 43}
diff --git a/pkg/packets/packets.go b/pkg/packets/packets.go
index 1bf3f57..6ae8a44 100644
--- a/pkg/packets/packets.go
+++ b/pkg/packets/packets.go
@@ -3,100 +3,55 @@ package packets
3import ( 3import (
4 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
5 "github.com/pektezol/sdp.go/pkg/classes" 5 "github.com/pektezol/sdp.go/pkg/classes"
6 "github.com/pektezol/sdp.go/pkg/writer" 6 "github.com/pektezol/sdp.go/pkg/types"
7) 7)
8 8
9type MessageType uint8 9func ParseMessage(reader *bitreader.Reader, demo *types.Demo) types.Message {
10 10 message := types.Message{
11const ( 11 PacketType: types.MessageType(reader.TryReadUInt8()),
12 SignOn MessageType = iota + 1
13 Packet
14 SyncTick
15 ConsoleCmd
16 UserCmd
17 DataTables
18 Stop
19 CustomData
20 StringTables
21)
22
23type Message struct {
24 PacketType MessageType
25 TickNumber int32
26 SlotNumber uint8
27 Data any
28}
29
30func ParseMessage(reader *bitreader.Reader) Message {
31 message := Message{
32 PacketType: MessageType(reader.TryReadUInt8()),
33 TickNumber: reader.TryReadSInt32(), 12 TickNumber: reader.TryReadSInt32(),
34 SlotNumber: reader.TryReadUInt8(), 13 SlotNumber: reader.TryReadUInt8(),
35 } 14 }
36 writer.AppendLine("[%d] %s (%d):", message.TickNumber, message.PacketType.String(), message.PacketType) 15 demo.Writer.AppendLine("[%d] %s (%d):", message.TickNumber, message.PacketType.String(), message.PacketType)
37 switch message.PacketType { 16 switch message.PacketType {
38 case SignOn: 17 case types.SignOn:
39 signOn := classes.SignOn{} 18 signOn := classes.SignOn{}
40 signOn.ParseSignOn(reader) 19 signOn.ParseSignOn(reader, demo)
41 message.Data = signOn 20 message.Data = signOn
42 case Packet: 21 case types.Packet:
43 packet := classes.Packet{} 22 packet := classes.Packet{}
44 packet.ParsePacket(reader) 23 packet.ParsePacket(reader, demo)
45 message.Data = packet 24 message.Data = packet
46 case SyncTick: 25 case types.SyncTick:
47 syncTick := classes.SyncTick{} 26 syncTick := classes.SyncTick{}
48 syncTick.ParseSyncTick() 27 syncTick.ParseSyncTick()
49 message.Data = syncTick 28 message.Data = syncTick
50 case ConsoleCmd: 29 case types.ConsoleCmd:
51 consoleCmd := classes.ConsoleCmd{} 30 consoleCmd := classes.ConsoleCmd{}
52 consoleCmd.ParseConsoleCmd(reader) 31 consoleCmd.ParseConsoleCmd(reader, demo)
53 message.Data = consoleCmd 32 message.Data = consoleCmd
54 case UserCmd: 33 case types.UserCmd:
55 userCmd := classes.UserCmd{} 34 userCmd := classes.UserCmd{}
56 userCmd.ParseUserCmd(reader) 35 userCmd.ParseUserCmd(reader, demo)
57 message.Data = userCmd 36 message.Data = userCmd
58 case DataTables: 37 case types.DataTables:
59 dataTables := classes.DataTables{} 38 dataTables := classes.DataTables{}
60 dataTables.ParseDataTables(reader) 39 dataTables.ParseDataTables(reader, demo)
61 message.Data = dataTables 40 message.Data = dataTables
62 case Stop: 41 case types.Stop:
63 stop := classes.Stop{} 42 stop := classes.Stop{}
64 stop.ParseStop(reader) 43 stop.ParseStop(reader, demo)
65 message.Data = stop 44 message.Data = stop
66 case CustomData: // TODO: not sar data 45 case types.CustomData: // TODO: not sar data
67 customData := classes.CustomData{} 46 customData := classes.CustomData{}
68 customData.ParseCustomData(reader, message.TickNumber, uint8(message.PacketType)) 47 customData.ParseCustomData(reader, message.TickNumber, uint8(message.PacketType), demo)
69 message.Data = customData 48 message.Data = customData
70 case StringTables: // TODO: parsing string table data 49 case types.StringTables: // TODO: parsing string table data
71 stringTables := classes.StringTables{} 50 stringTables := classes.StringTables{}
72 stringTables.ParseStringTables(reader) 51 stringTables.ParseStringTables(reader, demo)
73 message.Data = stringTables 52 message.Data = stringTables
74 default: 53 default:
75 panic("invalid packet type") 54 panic("invalid packet type")
76 } 55 }
77 return message 56 return message
78} 57}
79
80func (t MessageType) String() string {
81 switch t {
82 case SignOn:
83 return "SIGNON"
84 case Packet:
85 return "PACKET"
86 case SyncTick:
87 return "SYNCTICK"
88 case ConsoleCmd:
89 return "CONSOLECMD"
90 case UserCmd:
91 return "USERCMD"
92 case DataTables:
93 return "DATATABLES"
94 case Stop:
95 return "STOP"
96 case CustomData:
97 return "CUSTOMDATA"
98 case StringTables:
99 return "STRINGTABLES"
100 }
101 return "INVALID"
102}
diff --git a/pkg/types/gameevent.go b/pkg/types/gameevent.go
new file mode 100644
index 0000000..4f00bc0
--- /dev/null
+++ b/pkg/types/gameevent.go
@@ -0,0 +1,80 @@
1package types
2
3import (
4 "fmt"
5
6 "github.com/pektezol/bitreader"
7)
8
9type SvcGameEventList struct {
10 Events int16 `json:"events"`
11 Length int32 `json:"length"`
12 GameEventDescriptor []GameEventDescriptor `json:"game_event_descriptor"`
13}
14
15type GameEventDescriptor struct {
16 EventID uint32 `json:"event_id"`
17 Name string `json:"name"`
18 Keys []GameEventDescriptorKey `json:"keys"`
19}
20
21type GameEventDescriptorKey struct {
22 Name string `json:"name"`
23 Type EventDescriptor `json:"type"`
24}
25
26type EventDescriptor uint8
27
28func (svcGameEventList *SvcGameEventList) ParseGameEventDescriptor(reader *bitreader.Reader, demo *Demo) {
29 svcGameEventList.GameEventDescriptor = make([]GameEventDescriptor, svcGameEventList.Events)
30 for event := 0; event < int(svcGameEventList.Events); event++ {
31 svcGameEventList.GameEventDescriptor[event] = GameEventDescriptor{
32 EventID: uint32(reader.TryReadBits(9)),
33 Name: reader.TryReadString(),
34 }
35 demo.Writer.TempAppendLine("\t\t\t%d: %s", svcGameEventList.GameEventDescriptor[event].EventID, svcGameEventList.GameEventDescriptor[event].Name)
36 for {
37 descriptorType := reader.TryReadBits(3)
38 if descriptorType == 0 {
39 break
40 }
41 KeyName := reader.TryReadString()
42 svcGameEventList.GameEventDescriptor[event].Keys = append(svcGameEventList.GameEventDescriptor[event].Keys, GameEventDescriptorKey{
43 Name: KeyName,
44 Type: EventDescriptor(descriptorType),
45 })
46 }
47 demo.Writer.TempAppendLine("\t\t\t\tKeys: %v", svcGameEventList.GameEventDescriptor[event].Keys)
48 }
49}
50
51const (
52 EventDescriptorString EventDescriptor = iota + 1
53 EventDescriptorFloat
54 EventDescriptorInt32
55 EventDescriptorInt16
56 EventDescriptorInt8
57 EventDescriptorBool
58 EventDescriptorUInt64
59)
60
61func (eventDescriptor EventDescriptor) String() string {
62 switch eventDescriptor {
63 case EventDescriptorString:
64 return "String"
65 case EventDescriptorFloat:
66 return "Float"
67 case EventDescriptorInt32:
68 return "Int32"
69 case EventDescriptorInt16:
70 return "Int16"
71 case EventDescriptorInt8:
72 return "Int8"
73 case EventDescriptorBool:
74 return "Bool"
75 case EventDescriptorUInt64:
76 return "UInt64"
77 default:
78 return fmt.Sprintf("%d", eventDescriptor)
79 }
80}
diff --git a/pkg/types/types.go b/pkg/types/types.go
new file mode 100644
index 0000000..341e875
--- /dev/null
+++ b/pkg/types/types.go
@@ -0,0 +1,71 @@
1package types
2
3import (
4 "github.com/pektezol/sdp.go/pkg/writer"
5)
6
7type Demo struct {
8 Headers Headers `json:"headers"`
9 Messages []Message `json:"messages"`
10 Writer *writer.Writer `json:"-"`
11 GameEventList *SvcGameEventList `json:"-"`
12}
13
14type Headers struct {
15 DemoFileStamp string `json:"demo_file_stamp"`
16 DemoProtocol int32 `json:"demo_protocol"`
17 NetworkProtocol int32 `json:"network_protocol"`
18 ServerName string `json:"server_name"`
19 ClientName string `json:"client_name"`
20 MapName string `json:"map_name"`
21 GameDirectory string `json:"game_directory"`
22 PlaybackTime float32 `json:"playback_time"`
23 PlaybackTicks int32 `json:"playback_ticks"`
24 PlaybackFrames int32 `json:"playback_frames"`
25 SignOnLength int32 `json:"sign_on_length"`
26}
27
28type Message struct {
29 PacketType MessageType `json:"packet_type"`
30 TickNumber int32 `json:"tick_number"`
31 SlotNumber uint8 `json:"slot_number"`
32 Data any `json:"data"`
33}
34
35type MessageType uint8
36
37const (
38 SignOn MessageType = iota + 1
39 Packet
40 SyncTick
41 ConsoleCmd
42 UserCmd
43 DataTables
44 Stop
45 CustomData
46 StringTables
47)
48
49func (t MessageType) String() string {
50 switch t {
51 case SignOn:
52 return "SIGNON"
53 case Packet:
54 return "PACKET"
55 case SyncTick:
56 return "SYNCTICK"
57 case ConsoleCmd:
58 return "CONSOLECMD"
59 case UserCmd:
60 return "USERCMD"
61 case DataTables:
62 return "DATATABLES"
63 case Stop:
64 return "STOP"
65 case CustomData:
66 return "CUSTOMDATA"
67 case StringTables:
68 return "STRINGTABLES"
69 }
70 return "INVALID"
71}
diff --git a/pkg/writer/writer.go b/pkg/writer/writer.go
index f3af2fc..abfbf3d 100644
--- a/pkg/writer/writer.go
+++ b/pkg/writer/writer.go
@@ -5,43 +5,51 @@ import (
5 "strings" 5 "strings"
6) 6)
7 7
8var output strings.Builder 8type Writer struct {
9 output strings.Builder
10 temp strings.Builder
11}
9 12
10var temp strings.Builder 13func NewWriter() *Writer {
14 return &Writer{
15 output: strings.Builder{},
16 temp: strings.Builder{},
17 }
18}
11 19
12func Append(str string, a ...any) { 20func (w *Writer) Append(str string, a ...any) {
13 _, err := output.WriteString(fmt.Sprintf(str, a...)) 21 _, err := w.output.WriteString(fmt.Sprintf(str, a...))
14 if err != nil { 22 if err != nil {
15 output.WriteString(err.Error()) 23 w.output.WriteString(err.Error())
16 } 24 }
17} 25}
18 26
19func AppendLine(str string, a ...any) { 27func (w *Writer) AppendLine(str string, a ...any) {
20 Append(str, a...) 28 w.Append(str, a...)
21 output.WriteString("\n") 29 w.output.WriteString("\n")
22} 30}
23 31
24func GetWriter() strings.Builder { 32func (w *Writer) GetOutputString() string {
25 return output 33 return w.output.String()
26} 34}
27 35
28func TempAppend(str string, a ...any) { 36func (w *Writer) TempAppend(str string, a ...any) {
29 _, err := temp.WriteString(fmt.Sprintf(str, a...)) 37 _, err := w.temp.WriteString(fmt.Sprintf(str, a...))
30 if err != nil { 38 if err != nil {
31 temp.WriteString(err.Error()) 39 w.temp.WriteString(err.Error())
32 } 40 }
33} 41}
34 42
35func TempAppendLine(str string, a ...any) { 43func (w *Writer) TempAppendLine(str string, a ...any) {
36 TempAppend(str, a...) 44 w.TempAppend(str, a...)
37 temp.WriteString("\n") 45 w.temp.WriteString("\n")
38} 46}
39 47
40func TempGetString() string { 48func (w *Writer) TempGetString() string {
41 return temp.String() 49 return w.temp.String()
42} 50}
43 51
44func AppendOutputFromTemp() { 52func (w *Writer) AppendOutputFromTemp() {
45 output.WriteString(temp.String()) 53 w.output.WriteString(w.temp.String())
46 temp.Reset() 54 w.temp.Reset()
47} 55}