aboutsummaryrefslogtreecommitdiff
path: root/pkg/packets
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/packets')
-rw-r--r--pkg/packets/headers.go48
-rw-r--r--pkg/packets/packets.go125
-rw-r--r--pkg/packets/types.go53
3 files changed, 226 insertions, 0 deletions
diff --git a/pkg/packets/headers.go b/pkg/packets/headers.go
new file mode 100644
index 0000000..543476b
--- /dev/null
+++ b/pkg/packets/headers.go
@@ -0,0 +1,48 @@
1package packets
2
3import (
4 "fmt"
5
6 "github.com/pektezol/bitreader"
7)
8
9type Headers struct {
10 DemoFileStamp string
11 DemoProtocol int32
12 NetworkProtocol int32
13 ServerName string
14 ClientName string
15 MapName string
16 GameDirectory string
17 PlaybackTime float32
18 PlaybackTicks int32
19 PlaybackFrames int32
20 SignOnLength int32
21}
22
23func ParseHeaders(reader *bitreader.ReaderType) Headers {
24 headers := Headers{
25 DemoFileStamp: reader.TryReadString(),
26 DemoProtocol: int32(reader.TryReadInt32()),
27 NetworkProtocol: int32(reader.TryReadInt32()),
28 ServerName: reader.TryReadStringLen(260),
29 ClientName: reader.TryReadStringLen(260),
30 MapName: reader.TryReadStringLen(260),
31 GameDirectory: reader.TryReadStringLen(260),
32 PlaybackTime: reader.TryReadFloat32(),
33 PlaybackTicks: int32(reader.TryReadInt32()),
34 PlaybackFrames: int32(reader.TryReadInt32()),
35 SignOnLength: int32(reader.TryReadInt32()),
36 }
37 if headers.DemoFileStamp != "HL2DEMO" {
38 panic("invalid demo file stamp")
39 }
40 if headers.DemoProtocol != 4 {
41 panic("this parser only supports demos from new engine")
42 }
43 if headers.NetworkProtocol != 2001 {
44 panic("this parser only supports demos from portal 2")
45 }
46 fmt.Printf("Headers: %+v\n", headers)
47 return headers
48}
diff --git a/pkg/packets/packets.go b/pkg/packets/packets.go
new file mode 100644
index 0000000..a84da21
--- /dev/null
+++ b/pkg/packets/packets.go
@@ -0,0 +1,125 @@
1package packets
2
3import (
4 "bytes"
5
6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/demoparser/pkg/classes"
8 "github.com/pektezol/demoparser/pkg/messages"
9)
10
11type PacketMessageInfo struct {
12 PacketType int8
13 TickNumber int32
14 SlotNumber int8
15 Data any
16}
17
18const MSSC = 2
19
20func ParsePackets(reader *bitreader.ReaderType) PacketMessageInfo {
21 packetType := reader.TryReadBits(8)
22 tickNumber := reader.TryReadBits(32)
23 slotNumber := reader.TryReadBits(8)
24 var packetData any
25 switch packetType {
26 case 1: // SignOn
27 signOn := SignOn{}
28 for count := 0; count < MSSC; count++ {
29 signOn.PacketInfo = append(signOn.PacketInfo, classes.ParseCmdInfo(reader))
30 }
31 signOn.InSequence = int32(reader.TryReadBits(32))
32 signOn.OutSequence = int32(reader.TryReadBits(32))
33 signOn.Size = int32(reader.TryReadInt32())
34 data := reader.TryReadBytesToSlice(int(signOn.Size))
35 packetReader := bitreader.Reader(bytes.NewReader(data), true)
36 for {
37 messageType, err := packetReader.ReadBits(6)
38 if err != nil {
39 break
40 }
41 signOn.Data = append(signOn.Data, messages.ParseMessages(int(messageType), packetReader))
42 }
43 packetData = signOn
44 case 2: // Packet
45 packet := Packet{}
46 for count := 0; count < MSSC; count++ {
47 packet.PacketInfo = append(packet.PacketInfo, classes.ParseCmdInfo(reader))
48 }
49 packet.InSequence = int32(reader.TryReadBits(32))
50 packet.OutSequence = int32(reader.TryReadBits(32))
51 packet.Size = int32(reader.TryReadInt32())
52 data := reader.TryReadBytesToSlice(int(packet.Size))
53 packetReader := bitreader.Reader(bytes.NewReader(data), true)
54 for {
55 messageType, err := packetReader.ReadBits(6)
56 if err != nil {
57 break
58 }
59 packet.Data = append(packet.Data, messages.ParseMessages(int(messageType), packetReader))
60 }
61 packetData = packet
62 case 3: // SyncTick
63 syncTick := SyncTick{}
64 packetData = syncTick
65 case 4: // ConsoleCmd
66 size := reader.TryReadInt32()
67 consoleCmd := ConsoleCmd{
68 Size: int32(size),
69 Data: reader.TryReadStringLen(int(size)),
70 }
71 packetData = consoleCmd
72 case 5: // UserCmd
73 userCmd := UserCmd{}
74 userCmd.Cmd = int32(reader.TryReadInt32())
75 userCmd.Size = int32(reader.TryReadInt32())
76 data := reader.TryReadBytesToSlice(int(userCmd.Size))
77 userCmd.Data = classes.ParseUserCmdInfo(data)
78 packetData = userCmd
79 case 6: // DataTables
80 dataTables := DataTables{}
81 dataTables.Size = int32(reader.TryReadInt32())
82 data := reader.TryReadBytesToSlice(int(dataTables.Size))
83 dataTableReader := bitreader.Reader(bytes.NewReader(data), true)
84 count := 0
85 for dataTableReader.TryReadBool() {
86 count++
87 dataTables.SendTable = append(dataTables.SendTable, classes.ParseSendTable(dataTableReader))
88 }
89 numOfClasses := dataTableReader.TryReadBits(16)
90 for count = 0; count < int(numOfClasses); count++ {
91 dataTables.ServerClassInfo = append(dataTables.ServerClassInfo, classes.ParseServerClassInfo(dataTableReader, count, int(numOfClasses)))
92 }
93 packetData = dataTables
94 case 7: // Stop
95 stop := Stop{}
96 if reader.TryReadBool() {
97 // read remaining data
98 stop.RemainingData = []byte{}
99 }
100 packetData = stop
101 case 8: // CustomData
102 customData := CustomData{
103 Unknown: int32(reader.TryReadBits(32)),
104 Size: int32(reader.TryReadBits(32)),
105 }
106 customData.Data = string(reader.TryReadBytesToSlice(int(customData.Size)))
107 packetData = customData
108 case 9: // StringTables
109 stringTables := StringTables{
110 Size: int32(reader.TryReadInt32()),
111 }
112 data := reader.TryReadBytesToSlice(int(stringTables.Size))
113 stringTableReader := bitreader.Reader(bytes.NewReader(data), true)
114 stringTables.Data = classes.ParseStringTables(stringTableReader)
115 packetData = stringTables
116 default: // invalid
117 panic("invalid packet type")
118 }
119 return PacketMessageInfo{
120 PacketType: int8(packetType),
121 TickNumber: int32(tickNumber),
122 SlotNumber: int8(slotNumber),
123 Data: packetData,
124 }
125}
diff --git a/pkg/packets/types.go b/pkg/packets/types.go
new file mode 100644
index 0000000..6297b01
--- /dev/null
+++ b/pkg/packets/types.go
@@ -0,0 +1,53 @@
1package packets
2
3import "github.com/pektezol/demoparser/pkg/classes"
4
5type SignOn struct {
6 PacketInfo []classes.CmdInfo
7 InSequence int32
8 OutSequence int32
9 Size int32
10 Data []any
11}
12
13type Packet struct {
14 PacketInfo []classes.CmdInfo
15 InSequence int32
16 OutSequence int32
17 Size int32
18 Data []any
19}
20
21type SyncTick struct{}
22
23type ConsoleCmd struct {
24 Size int32
25 Data string
26}
27
28type UserCmd struct {
29 Cmd int32
30 Size int32
31 Data classes.UserCmdInfo
32}
33
34type DataTables struct {
35 Size int32
36 SendTable []classes.SendTable
37 ServerClassInfo []classes.ServerClassInfo
38}
39
40type Stop struct {
41 RemainingData []byte
42}
43
44type CustomData struct {
45 Unknown int32
46 Size int32
47 Data string
48}
49
50type StringTables struct {
51 Size int32
52 Data []classes.StringTable
53}