aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-09-12 20:53:09 +0300
committerArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-09-16 21:39:42 +0300
commit82871ba1bac1d62f69e1933b66659e62d2e5e063 (patch)
treea906310fba89b670bcfda9625a6d776553d482f6
parentnet/svc messages finally getting parsed correctly (diff)
downloadsdp.go-82871ba1bac1d62f69e1933b66659e62d2e5e063.tar.gz
sdp.go-82871ba1bac1d62f69e1933b66659e62d2e5e063.tar.bz2
sdp.go-82871ba1bac1d62f69e1933b66659e62d2e5e063.zip
another rewrite, v1.0.0
-rw-r--r--cmd/parser.go50
-rw-r--r--go.mod4
-rw-r--r--go.sum4
-rw-r--r--main.go49
-rw-r--r--packets/classes/cmdinfo.go61
-rw-r--r--packets/classes/datatable.go66
-rw-r--r--packets/classes/stringtable.go51
-rw-r--r--packets/header.go33
-rw-r--r--packets/messages/message.go94
-rw-r--r--packets/messages/types/NetNop.go3
-rw-r--r--packets/messages/types/NetSignOnState.go27
-rw-r--r--packets/messages/types/NetTick.go17
-rw-r--r--packets/messages/types/SvcClassInfo.go47
-rw-r--r--packets/messages/types/SvcCmdKeyValues.go14
-rw-r--r--packets/messages/types/SvcCreateStringTable.go34
-rw-r--r--packets/messages/types/SvcEntityMessage.go20
-rw-r--r--packets/messages/types/SvcFixAngle.go21
-rw-r--r--packets/messages/types/SvcGameEvent.go15
-rw-r--r--packets/messages/types/SvcGameEventList.go17
-rw-r--r--packets/messages/types/SvcMenu.go17
-rw-r--r--packets/messages/types/SvcPacketEntities.go39
-rw-r--r--packets/messages/types/SvcPaintmapData.go14
-rw-r--r--packets/messages/types/SvcSendTable.go17
-rw-r--r--packets/messages/types/SvcServerInfo.go43
-rw-r--r--packets/messages/types/SvcSounds.go30
-rw-r--r--packets/messages/types/SvcSplitScreen.go17
-rw-r--r--packets/messages/types/SvcTempEntities.go20
-rw-r--r--packets/messages/types/SvcUpdateStringTable.go21
-rw-r--r--packets/messages/types/SvcUserMessage.go19
-rw-r--r--packets/messages/types/SvcVoiceData.go19
-rw-r--r--packets/packet.go87
-rw-r--r--pkg/classes/cmdInfo.go27
-rw-r--r--pkg/classes/sendTable.go106
-rw-r--r--pkg/classes/serverClassInfo.go30
-rw-r--r--pkg/classes/stringTable.go82
-rw-r--r--pkg/classes/userCmdInfo.go (renamed from packets/classes/usercmd.go)32
-rw-r--r--pkg/messages/messages.go87
-rw-r--r--pkg/messages/types/netDisconnect.go (renamed from packets/messages/types/NetDisconnect.go)6
-rw-r--r--pkg/messages/types/netFile.go (renamed from packets/messages/types/NetFile.go)6
-rw-r--r--pkg/messages/types/netNop.go9
-rw-r--r--pkg/messages/types/netSetConVar.go (renamed from packets/messages/types/NetSetConVar.go)17
-rw-r--r--pkg/messages/types/netSignOnState.go26
-rw-r--r--pkg/messages/types/netSplitScreenUser.go (renamed from packets/messages/types/NetSplitScreenUser.go)6
-rw-r--r--pkg/messages/types/netStringCmd.go (renamed from packets/messages/types/NetStringCmd.go)2
-rw-r--r--pkg/messages/types/netTick.go17
-rw-r--r--pkg/messages/types/svcBspDecal.go61
-rw-r--r--pkg/messages/types/svcClassInfo.go40
-rw-r--r--pkg/messages/types/svcCmdKeyValues.go16
-rw-r--r--pkg/messages/types/svcCreateStringTable.go36
-rw-r--r--pkg/messages/types/svcCrosshairAngle.go (renamed from packets/messages/types/SvcCrosshairAngle.go)8
-rw-r--r--pkg/messages/types/svcEntityMessage.go20
-rw-r--r--pkg/messages/types/svcFixAngle.go15
-rw-r--r--pkg/messages/types/svcGameEvent.go16
-rw-r--r--pkg/messages/types/svcGameEventList.go21
-rw-r--r--pkg/messages/types/svcGetCvarValue.go (renamed from packets/messages/types/SvcGetCvarValue.go)7
-rw-r--r--pkg/messages/types/svcMenu.go18
-rw-r--r--pkg/messages/types/svcPacketEntities.go30
-rw-r--r--pkg/messages/types/svcPaintmapData.go16
-rw-r--r--pkg/messages/types/svcPrefetch.go (renamed from packets/messages/types/SvcPrefetch.go)2
-rw-r--r--pkg/messages/types/svcPrint.go (renamed from packets/messages/types/SvcPrint.go)2
-rw-r--r--pkg/messages/types/svcSendTable.go17
-rw-r--r--pkg/messages/types/svcServerInfo.go43
-rw-r--r--pkg/messages/types/svcSetPause.go (renamed from packets/messages/types/SvcSetPause.go)10
-rw-r--r--pkg/messages/types/svcSetView.go (renamed from packets/messages/types/SvcSetView.go)2
-rw-r--r--pkg/messages/types/svcSounds.go25
-rw-r--r--pkg/messages/types/svcSplitScreen.go18
-rw-r--r--pkg/messages/types/svcTempEntities.go18
-rw-r--r--pkg/messages/types/svcUpdateStringTable.go22
-rw-r--r--pkg/messages/types/svcUserMessage.go18
-rw-r--r--pkg/messages/types/svcVoiceData.go20
-rw-r--r--pkg/messages/types/svcVoiceInit.go (renamed from packets/messages/types/SvcVoiceInit.go)12
-rw-r--r--pkg/packets/headers.go48
-rw-r--r--pkg/packets/packets.go125
-rw-r--r--pkg/packets/types.go (renamed from packets/types.go)35
74 files changed, 1147 insertions, 997 deletions
diff --git a/cmd/parser.go b/cmd/parser.go
new file mode 100644
index 0000000..d03fa9c
--- /dev/null
+++ b/cmd/parser.go
@@ -0,0 +1,50 @@
1package main
2
3import (
4 "fmt"
5 "os"
6 "reflect"
7
8 "github.com/pektezol/bitreader"
9 "github.com/pektezol/demoparser/pkg/packets"
10)
11
12func main() {
13 if len(os.Args) != 2 {
14 panic("specify file in command line arguments")
15 }
16 files, err := os.ReadDir(os.Args[1])
17 if err != nil { // If it's not a directory
18 file, err := os.Open(os.Args[1])
19 if err != nil {
20 panic(err)
21 }
22 reader := bitreader.Reader(file, true)
23 demoParserHandler(reader)
24 defer file.Close()
25 }
26 for _, fileinfo := range files { // If it is a directory
27 file, err := os.Open(os.Args[1] + fileinfo.Name())
28 if err != nil {
29 panic(err)
30 }
31 reader := bitreader.Reader(file, true)
32 demoParserHandler(reader)
33 defer file.Close()
34 }
35 // fmt.Scanln()
36}
37
38func demoParserHandler(reader *bitreader.ReaderType) {
39 packets.ParseHeaders(reader)
40 for {
41 packet := packets.ParsePackets(reader)
42 if packet.PacketType == 7 {
43 break
44 }
45 // if packet.PacketType != 5 {
46 // continue
47 // }
48 fmt.Printf("[%d] %s (%d):\n\t%+v\n", packet.TickNumber, reflect.ValueOf(packet.Data).Type(), packet.PacketType, packet.Data)
49 }
50}
diff --git a/go.mod b/go.mod
index d1b68cc..408c7e3 100644
--- a/go.mod
+++ b/go.mod
@@ -1,5 +1,5 @@
1module github.com/pektezol/demoparser 1module github.com/pektezol/demoparser
2 2
3go 1.19 3go 1.21.0
4 4
5require github.com/pektezol/bitreader v1.2.9 5require github.com/pektezol/bitreader v1.3.0
diff --git a/go.sum b/go.sum
index 4cccb6e..190a8a8 100644
--- a/go.sum
+++ b/go.sum
@@ -1,2 +1,2 @@
1github.com/pektezol/bitreader v1.2.9 h1:DnCe5vDt6vC9zRVaeX47XjlcgK1i0jDPhYd8cimyPvo= 1github.com/pektezol/bitreader v1.3.0 h1:VOj1M+vw0+xuBUlD4HPHdkjnVdUrHw2nwa5Ccxxm2ek=
2github.com/pektezol/bitreader v1.2.9/go.mod h1:RKAUiA//jCPJzO10P+VSkBq4wfY38TaNjpCjQ+DmbcQ= 2github.com/pektezol/bitreader v1.3.0/go.mod h1:RKAUiA//jCPJzO10P+VSkBq4wfY38TaNjpCjQ+DmbcQ=
diff --git a/main.go b/main.go
deleted file mode 100644
index 8f05c2b..0000000
--- a/main.go
+++ /dev/null
@@ -1,49 +0,0 @@
1package main
2
3import (
4 "fmt"
5 "io/ioutil"
6 "log"
7 "os"
8
9 "github.com/pektezol/bitreader"
10 "github.com/pektezol/demoparser/packets"
11)
12
13func main() {
14 if len(os.Args) != 2 {
15 log.Fatal("Specify file in command line arguments.")
16 }
17 files, err := ioutil.ReadDir(os.Args[1])
18 if err != nil { // If it's not a directory
19 file, err := os.Open(os.Args[1])
20 if err != nil {
21 panic(err)
22 }
23 reader := bitreader.Reader(file, true)
24 packets.ParseHeader(reader)
25 for {
26 code := packets.ParsePacket(reader)
27 if code == 7 {
28 break
29 }
30 }
31 defer file.Close()
32 }
33 for _, fileinfo := range files { // If it is a directory
34 file, err := os.Open(os.Args[1] + fileinfo.Name())
35 if err != nil {
36 panic(err)
37 }
38 /*messages.ParseHeader(file)
39 for {
40 code := messages.ParseMessage(file)
41 if code == 7 {
42 messages.ParseMessage(file)
43 break
44 }
45 }*/
46 defer file.Close()
47 }
48 fmt.Scanln()
49}
diff --git a/packets/classes/cmdinfo.go b/packets/classes/cmdinfo.go
deleted file mode 100644
index d11bebc..0000000
--- a/packets/classes/cmdinfo.go
+++ /dev/null
@@ -1,61 +0,0 @@
1package classes
2
3import "github.com/pektezol/bitreader"
4
5type CmdInfo struct {
6 Flags int32
7 ViewOrigin []float32
8 ViewAngles []float32
9 LocalViewAngles []float32
10 ViewOrigin2 []float32
11 ViewAngles2 []float32
12 LocalViewAngles2 []float32
13}
14
15func ParseCmdInfo(reader *bitreader.ReaderType, MSSC int) []CmdInfo {
16 var out []CmdInfo
17 for i := 0; i < MSSC; i++ {
18 flags := int32(reader.TryReadInt32())
19 viewOrigin := []float32{
20 reader.TryReadFloat32(),
21 reader.TryReadFloat32(),
22 reader.TryReadFloat32(),
23 }
24 viewAngles := []float32{
25 reader.TryReadFloat32(),
26 reader.TryReadFloat32(),
27 reader.TryReadFloat32(),
28 }
29 localViewAngles := []float32{
30 reader.TryReadFloat32(),
31 reader.TryReadFloat32(),
32 reader.TryReadFloat32(),
33 }
34 viewOrigin2 := []float32{
35 reader.TryReadFloat32(),
36 reader.TryReadFloat32(),
37 reader.TryReadFloat32(),
38 }
39 viewAngles2 := []float32{
40 reader.TryReadFloat32(),
41 reader.TryReadFloat32(),
42 reader.TryReadFloat32(),
43 }
44 localViewAngles2 := []float32{
45 reader.TryReadFloat32(),
46 reader.TryReadFloat32(),
47 reader.TryReadFloat32(),
48 }
49 cmdInfo := CmdInfo{
50 Flags: flags,
51 ViewOrigin: viewOrigin,
52 ViewAngles: viewAngles,
53 LocalViewAngles: localViewAngles,
54 ViewOrigin2: viewOrigin2,
55 ViewAngles2: viewAngles2,
56 LocalViewAngles2: localViewAngles2,
57 }
58 out = append(out, cmdInfo)
59 }
60 return out
61}
diff --git a/packets/classes/datatable.go b/packets/classes/datatable.go
deleted file mode 100644
index 405dae6..0000000
--- a/packets/classes/datatable.go
+++ /dev/null
@@ -1,66 +0,0 @@
1package classes
2
3import (
4 "bytes"
5 "fmt"
6
7 "github.com/pektezol/bitreader"
8)
9
10type DataTable struct {
11 SendTable []SendTable
12 ServerClassInfo []ServerClassInfo
13}
14
15type SendTable struct {
16 NeedsDecoder bool
17 NetTableName string
18 NumOfProps uint16
19 SendPropType int8
20 SendPropName string
21 SendPropFlags int16
22}
23
24type ServerClassInfo struct {
25 ClassId int16
26 ClassName string
27 DataTableName string
28}
29
30func ParseDataTable(data []byte) DataTable {
31 reader := bitreader.Reader(bytes.NewReader(data), true)
32 sendtable := parseSendTable(reader)
33 serverclassinfo := parseServerClassInfo(reader)
34 return DataTable{
35 SendTable: sendtable,
36 ServerClassInfo: serverclassinfo,
37 }
38}
39
40func parseSendTable(reader *bitreader.ReaderType) []SendTable {
41 var sendtables []SendTable
42 for reader.TryReadBool() {
43 sendtables = append(sendtables, SendTable{
44 NeedsDecoder: reader.TryReadBool(),
45 NetTableName: reader.TryReadString(),
46 NumOfProps: uint16(reader.TryReadBits(10)),
47 SendPropType: int8(reader.TryReadBits(5)),
48 SendPropName: reader.TryReadString(),
49 SendPropFlags: int16(reader.TryReadInt16()),
50 })
51 }
52 return sendtables
53}
54func parseServerClassInfo(reader *bitreader.ReaderType) []ServerClassInfo {
55 var serverclassinfo []ServerClassInfo
56 numofclasses := reader.TryReadInt16()
57 fmt.Println(numofclasses)
58 for i := 0; i < int(numofclasses); i++ {
59 serverclassinfo = append(serverclassinfo, ServerClassInfo{
60 ClassId: int16(reader.TryReadInt16()),
61 ClassName: reader.TryReadString(),
62 DataTableName: reader.TryReadString(),
63 })
64 }
65 return serverclassinfo
66}
diff --git a/packets/classes/stringtable.go b/packets/classes/stringtable.go
deleted file mode 100644
index a1432f9..0000000
--- a/packets/classes/stringtable.go
+++ /dev/null
@@ -1,51 +0,0 @@
1package classes
2
3import (
4 "bytes"
5
6 "github.com/pektezol/bitreader"
7)
8
9type StringTable struct {
10 TableName string
11 NumOfEntries int16
12 EntryName string
13 EntrySize int16
14 EntryData []byte
15 NumOfClientEntries int16
16 ClientEntryName string
17 ClientEntrySize int16
18 ClientEntryData []byte
19}
20
21func ParseStringTable(data []byte) []StringTable {
22 reader := bitreader.Reader(bytes.NewReader(data), true)
23 var stringTables []StringTable
24 numOfTables := reader.TryReadInt8()
25 for i := 0; i < int(numOfTables); i++ {
26 var stringTable StringTable
27 stringTable.TableName = reader.TryReadString()
28 stringTable.NumOfEntries = int16(reader.TryReadInt16())
29 stringTable.EntryName = reader.TryReadString()
30 if reader.TryReadBool() {
31 stringTable.EntrySize = int16(reader.TryReadInt16())
32 }
33 if reader.TryReadBool() {
34 stringTable.EntryData = reader.TryReadBytesToSlice(int(stringTable.EntrySize))
35 }
36 if reader.TryReadBool() {
37 stringTable.NumOfClientEntries = int16(reader.TryReadInt16())
38 }
39 if reader.TryReadBool() {
40 stringTable.ClientEntryName = reader.TryReadString()
41 }
42 if reader.TryReadBool() {
43 stringTable.ClientEntrySize = int16(reader.TryReadInt16())
44 }
45 if reader.TryReadBool() {
46 stringTable.ClientEntryData = reader.TryReadBytesToSlice(int(stringTable.ClientEntrySize))
47 }
48 stringTables = append(stringTables, stringTable)
49 }
50 return stringTables
51}
diff --git a/packets/header.go b/packets/header.go
deleted file mode 100644
index c4172d9..0000000
--- a/packets/header.go
+++ /dev/null
@@ -1,33 +0,0 @@
1package packets
2
3import (
4 "fmt"
5
6 "github.com/pektezol/bitreader"
7)
8
9func ParseHeader(reader *bitreader.ReaderType) {
10 header := Header{
11 DemoFileStamp: reader.TryReadStringLen(8),
12 DemoProtocol: uint32(reader.TryReadInt32()),
13 NetworkProtocol: uint32(reader.TryReadInt32()),
14 ServerName: reader.TryReadStringLen(260),
15 ClientName: reader.TryReadStringLen(260),
16 MapName: reader.TryReadStringLen(260),
17 GameDirectory: reader.TryReadStringLen(260),
18 PlaybackTime: reader.TryReadFloat32(),
19 PlaybackTicks: int32(reader.TryReadInt32()),
20 PlaybackFrames: int32(reader.TryReadInt32()),
21 SignOnLength: uint32(reader.TryReadInt32()),
22 }
23 if header.DemoFileStamp != "HL2DEMO" {
24 panic("Invalid demo file stamp. Make sure a valid demo file is given.")
25 }
26 if header.DemoProtocol != 4 {
27 panic("Given demo is from old engine. This parser is only supported for new engine.")
28 }
29 if header.NetworkProtocol != 2001 {
30 panic("Given demo is not from Portal2. This parser currently only supports Portal 2.")
31 }
32 fmt.Println(header)
33}
diff --git a/packets/messages/message.go b/packets/messages/message.go
deleted file mode 100644
index 4a00212..0000000
--- a/packets/messages/message.go
+++ /dev/null
@@ -1,94 +0,0 @@
1package messages
2
3import (
4 "bytes"
5
6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/demoparser/packets/messages/types"
8)
9
10func ParseMessage(data []byte) []Message {
11 reader := bitreader.Reader(bytes.NewReader(data), true)
12 var messages []Message
13 for {
14 messageType, err := reader.ReadBits(6)
15 if err != nil {
16 break
17 }
18 switch messageType {
19 case 0:
20 messages = append(messages, Message{Data: types.NetNop{}})
21 case 1:
22 messages = append(messages, Message{Data: types.ParseNetDisconnect(reader)})
23 case 2:
24 messages = append(messages, Message{Data: types.ParseNetFile(reader)})
25 case 3:
26 messages = append(messages, Message{Data: types.ParseNetSplitScreenUser(reader)})
27 case 4:
28 messages = append(messages, Message{Data: types.ParseNetTick(reader)})
29 case 5:
30 messages = append(messages, Message{Data: types.ParseNetStringCmd(reader)})
31 case 6:
32 messages = append(messages, Message{Data: types.ParseNetSetConVar(reader)})
33 case 7:
34 messages = append(messages, Message{Data: types.ParseNetSignOnState(reader)})
35 case 8:
36 messages = append(messages, Message{Data: types.ParseSvcServerInfo(reader)})
37 case 9:
38 messages = append(messages, Message{Data: types.ParseSvcSendTable(reader)})
39 case 10:
40 messages = append(messages, Message{Data: types.ParseSvcClassInfo(reader)})
41 case 11:
42 messages = append(messages, Message{Data: types.ParseSvcSetPause(reader)})
43 case 12:
44 messages = append(messages, Message{Data: types.ParseSvcCreateStringTable(reader)})
45 case 13:
46 messages = append(messages, Message{Data: types.ParseSvcUpdateStringTable(reader)})
47 case 14:
48 messages = append(messages, Message{Data: types.ParseSvcVoiceInit(reader)})
49 case 15:
50 messages = append(messages, Message{Data: types.ParseSvcVoiceData(reader)})
51 case 16:
52 messages = append(messages, Message{Data: types.ParseSvcPrint(reader)})
53 case 17:
54 messages = append(messages, Message{Data: types.ParseSvcSounds(reader)})
55 case 18:
56 messages = append(messages, Message{Data: types.ParseSvcSetView(reader)})
57 case 19:
58 messages = append(messages, Message{Data: types.ParseSvcFixAngle(reader)})
59 case 20:
60 messages = append(messages, Message{Data: types.ParseSvcCrosshairAngle(reader)})
61 case 21:
62 // TODO: SvcBspDecal
63 case 22:
64 messages = append(messages, Message{Data: types.ParseSvcSplitScreen(reader)})
65 case 23:
66 messages = append(messages, Message{Data: types.ParseSvcUserMessage(reader)})
67 case 24:
68 messages = append(messages, Message{Data: types.ParseSvcEntityMessage(reader)})
69 case 25:
70 messages = append(messages, Message{Data: types.ParseSvcGameEvent(reader)})
71 case 26:
72 messages = append(messages, Message{Data: types.ParseSvcPacketEntities(reader)})
73 case 27:
74 messages = append(messages, Message{Data: types.ParseSvcTempEntities(reader)})
75 case 28:
76 messages = append(messages, Message{Data: types.ParseSvcPrefetch(reader)})
77 case 29:
78 messages = append(messages, Message{Data: types.ParseSvcMenu(reader)})
79 case 30:
80 messages = append(messages, Message{Data: types.ParseSvcGameEventList(reader)})
81 case 31:
82 messages = append(messages, Message{Data: types.ParseSvcGetCvarValue(reader)})
83 case 32:
84 messages = append(messages, Message{Data: types.ParseSvcCmdKeyValues(reader)})
85 case 33:
86 messages = append(messages, Message{Data: types.ParseSvcPaintmapData(reader)})
87 }
88 }
89 return messages
90}
91
92type Message struct {
93 Data any
94}
diff --git a/packets/messages/types/NetNop.go b/packets/messages/types/NetNop.go
deleted file mode 100644
index d0a1f7a..0000000
--- a/packets/messages/types/NetNop.go
+++ /dev/null
@@ -1,3 +0,0 @@
1package types
2
3type NetNop struct{}
diff --git a/packets/messages/types/NetSignOnState.go b/packets/messages/types/NetSignOnState.go
deleted file mode 100644
index a8f3add..0000000
--- a/packets/messages/types/NetSignOnState.go
+++ /dev/null
@@ -1,27 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type NetSignOnState struct {
8 SignonState int8
9 SpawnCount uint32
10 NumServerPlayers uint32
11 PlayersNetworkIds []byte
12 MapNameLength uint32
13 MapName string
14}
15
16func ParseNetSignOnState(reader *bitreader.ReaderType) NetSignOnState {
17 netsignonstate := NetSignOnState{
18 SignonState: int8(reader.TryReadInt8()),
19 SpawnCount: reader.TryReadInt32(),
20 NumServerPlayers: reader.TryReadInt32(),
21 }
22 length := reader.TryReadInt32()
23 netsignonstate.PlayersNetworkIds = reader.TryReadBytesToSlice(int(length))
24 netsignonstate.MapNameLength = reader.TryReadInt32()
25 netsignonstate.MapName = reader.TryReadStringLen(int(netsignonstate.MapNameLength))
26 return netsignonstate
27}
diff --git a/packets/messages/types/NetTick.go b/packets/messages/types/NetTick.go
deleted file mode 100644
index 9dae14b..0000000
--- a/packets/messages/types/NetTick.go
+++ /dev/null
@@ -1,17 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type NetTick struct {
6 Tick uint32
7 HostFrameTime float32
8 HostFrameTimeStdDeviation float32
9}
10
11func ParseNetTick(reader *bitreader.ReaderType) NetTick {
12 return NetTick{
13 Tick: reader.TryReadInt32(),
14 HostFrameTime: float32(reader.TryReadInt16()) / 1e5,
15 HostFrameTimeStdDeviation: float32(reader.TryReadInt16()) / 1e5,
16 }
17}
diff --git a/packets/messages/types/SvcClassInfo.go b/packets/messages/types/SvcClassInfo.go
deleted file mode 100644
index df17bfc..0000000
--- a/packets/messages/types/SvcClassInfo.go
+++ /dev/null
@@ -1,47 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcClassInfo struct {
8 CreateOnClient bool
9 ServerClasses []ServerClass
10}
11
12type ServerClass struct {
13 ClassId int32
14 ClassName string
15 DataTableName string
16}
17
18func ParseSvcClassInfo(reader *bitreader.ReaderType) SvcClassInfo {
19 length := reader.TryReadInt16()
20 createonclient := reader.TryReadBool()
21 var serverclasses []ServerClass
22 if !createonclient {
23 serverclasses := make([]ServerClass, length)
24 for i := 0; i < int(length); i++ {
25 id, err := reader.ReadBits(HighestBitIndex(uint(length)) + 1)
26 if err != nil {
27 panic(err)
28 }
29 serverclasses[i] = ServerClass{
30 ClassId: int32(id),
31 ClassName: reader.TryReadString(),
32 DataTableName: reader.TryReadString(),
33 }
34 }
35 }
36 return SvcClassInfo{
37 CreateOnClient: createonclient,
38 ServerClasses: serverclasses,
39 }
40}
41
42func HighestBitIndex(i uint) int {
43 var j int
44 for j = 31; j >= 0 && (i&(1<<j)) == 0; j-- {
45 }
46 return j
47}
diff --git a/packets/messages/types/SvcCmdKeyValues.go b/packets/messages/types/SvcCmdKeyValues.go
deleted file mode 100644
index 06504a2..0000000
--- a/packets/messages/types/SvcCmdKeyValues.go
+++ /dev/null
@@ -1,14 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcCmdKeyValues struct {
6 Data []byte
7}
8
9func ParseSvcCmdKeyValues(reader *bitreader.ReaderType) SvcCmdKeyValues {
10 length := reader.TryReadInt32()
11 return SvcCmdKeyValues{
12 Data: reader.TryReadBytesToSlice(int(length)),
13 }
14}
diff --git a/packets/messages/types/SvcCreateStringTable.go b/packets/messages/types/SvcCreateStringTable.go
deleted file mode 100644
index 72ab1a7..0000000
--- a/packets/messages/types/SvcCreateStringTable.go
+++ /dev/null
@@ -1,34 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcCreateStringTable struct {
8 Name string
9 MaxEntries uint16
10 NumEntries uint8
11 UserDataFixedSize bool
12 UserDataSize uint16
13 UserDataSizeBits uint8
14 Flags uint8
15 StringData []byte
16}
17
18func ParseSvcCreateStringTable(reader *bitreader.ReaderType) SvcCreateStringTable {
19 svccreatestringtable := SvcCreateStringTable{
20 Name: reader.TryReadString(),
21 MaxEntries: reader.TryReadInt16(),
22 }
23 svccreatestringtable.NumEntries = uint8(reader.TryReadBits(HighestBitIndex(uint(svccreatestringtable.MaxEntries)) + 1))
24 length := reader.TryReadBits(20)
25 svccreatestringtable.UserDataFixedSize = reader.TryReadBool()
26 if svccreatestringtable.UserDataFixedSize {
27 svccreatestringtable.UserDataSize = uint16(reader.TryReadBits(12))
28 svccreatestringtable.UserDataSizeBits = uint8(reader.TryReadBits(4))
29 }
30 svccreatestringtable.Flags = uint8(reader.TryReadBits(2))
31 svccreatestringtable.StringData = reader.TryReadBitsToSlice(int(length))
32 return svccreatestringtable
33
34}
diff --git a/packets/messages/types/SvcEntityMessage.go b/packets/messages/types/SvcEntityMessage.go
deleted file mode 100644
index f4fb518..0000000
--- a/packets/messages/types/SvcEntityMessage.go
+++ /dev/null
@@ -1,20 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcEntityMessage struct {
6 EntityIndex int16
7 ClassId int16
8 Data []byte
9}
10
11func ParseSvcEntityMessage(reader *bitreader.ReaderType) SvcEntityMessage {
12 entityindex := reader.TryReadBits(11)
13 classid := reader.TryReadBits(9)
14 length := reader.TryReadBits(11)
15 return SvcEntityMessage{
16 EntityIndex: int16(entityindex),
17 ClassId: int16(classid),
18 Data: reader.TryReadBytesToSlice(int(length / 8)),
19 }
20}
diff --git a/packets/messages/types/SvcFixAngle.go b/packets/messages/types/SvcFixAngle.go
deleted file mode 100644
index d98dedd..0000000
--- a/packets/messages/types/SvcFixAngle.go
+++ /dev/null
@@ -1,21 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcFixAngle struct {
6 Relative bool
7 Angle []int16
8}
9
10func ParseSvcFixAngle(reader *bitreader.ReaderType) SvcFixAngle {
11 relative := reader.TryReadBool()
12 angles := []int16{
13 int16(reader.TryReadInt16()),
14 int16(reader.TryReadInt16()),
15 int16(reader.TryReadInt16()),
16 }
17 return SvcFixAngle{
18 Relative: relative,
19 Angle: angles,
20 }
21}
diff --git a/packets/messages/types/SvcGameEvent.go b/packets/messages/types/SvcGameEvent.go
deleted file mode 100644
index 1d6b0ea..0000000
--- a/packets/messages/types/SvcGameEvent.go
+++ /dev/null
@@ -1,15 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcGameEvent struct {
8 Data []byte
9}
10
11func ParseSvcGameEvent(reader *bitreader.ReaderType) SvcGameEvent {
12 length := reader.TryReadBits(11)
13 reader.SkipBits(int(length))
14 return SvcGameEvent{} // TODO: Parse SvcGameEvent
15}
diff --git a/packets/messages/types/SvcGameEventList.go b/packets/messages/types/SvcGameEventList.go
deleted file mode 100644
index fea0be4..0000000
--- a/packets/messages/types/SvcGameEventList.go
+++ /dev/null
@@ -1,17 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcGameEventList struct {
6 Events int16
7 Data []byte
8}
9
10func ParseSvcGameEventList(reader *bitreader.ReaderType) SvcGameEventList {
11 events := reader.TryReadBits(9)
12 length := reader.TryReadBits(20)
13 return SvcGameEventList{
14 Events: int16(events),
15 Data: reader.TryReadBitsToSlice(int(length)),
16 }
17}
diff --git a/packets/messages/types/SvcMenu.go b/packets/messages/types/SvcMenu.go
deleted file mode 100644
index 312115a..0000000
--- a/packets/messages/types/SvcMenu.go
+++ /dev/null
@@ -1,17 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcMenu struct {
6 MenuType int16
7 Data []byte
8}
9
10func ParseSvcMenu(reader *bitreader.ReaderType) SvcMenu {
11 menutype := reader.TryReadInt16()
12 length := reader.TryReadInt32()
13 return SvcMenu{
14 MenuType: int16(menutype),
15 Data: reader.TryReadBytesToSlice(int(length / 8)),
16 }
17}
diff --git a/packets/messages/types/SvcPacketEntities.go b/packets/messages/types/SvcPacketEntities.go
deleted file mode 100644
index 9d8a8b0..0000000
--- a/packets/messages/types/SvcPacketEntities.go
+++ /dev/null
@@ -1,39 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcPacketEntities struct {
8 MaxEntries uint16
9 IsDelta bool
10 DeltaFrom int32
11 BaseLine bool
12 UpdatedEntries uint16
13 UpdateBaseline bool
14 Data []byte
15}
16
17func ParseSvcPacketEntities(reader *bitreader.ReaderType) SvcPacketEntities {
18 maxentries := reader.TryReadBits(11)
19 isdelta := reader.TryReadBool()
20 var deltafrom int32
21 if isdelta {
22 deltafrom = int32(reader.TryReadInt32())
23 } else {
24 deltafrom = -1
25 }
26 baseline := reader.TryReadBool()
27 updatedentries := reader.TryReadBits(11)
28 length := reader.TryReadBits(20)
29 updatebaseline := reader.TryReadBool()
30 return SvcPacketEntities{
31 MaxEntries: uint16(maxentries),
32 IsDelta: isdelta,
33 DeltaFrom: deltafrom,
34 BaseLine: baseline,
35 UpdatedEntries: uint16(updatedentries),
36 UpdateBaseline: updatebaseline,
37 Data: reader.TryReadBitsToSlice(int(length)),
38 }
39}
diff --git a/packets/messages/types/SvcPaintmapData.go b/packets/messages/types/SvcPaintmapData.go
deleted file mode 100644
index f3bd1a3..0000000
--- a/packets/messages/types/SvcPaintmapData.go
+++ /dev/null
@@ -1,14 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcPaintmapData struct {
6 Data []byte
7}
8
9func ParseSvcPaintmapData(reader *bitreader.ReaderType) SvcPaintmapData {
10 length := reader.TryReadInt32()
11 return SvcPaintmapData{
12 Data: reader.TryReadBytesToSlice(int(length / 8)),
13 }
14}
diff --git a/packets/messages/types/SvcSendTable.go b/packets/messages/types/SvcSendTable.go
deleted file mode 100644
index f76aadb..0000000
--- a/packets/messages/types/SvcSendTable.go
+++ /dev/null
@@ -1,17 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcSendTable struct {
6 NeedsDecoder bool
7 Length uint8
8 Props int32
9}
10
11func ParseSvcSendTable(reader *bitreader.ReaderType) SvcSendTable {
12 return SvcSendTable{
13 NeedsDecoder: reader.TryReadBool(),
14 Length: reader.TryReadInt8(),
15 }
16 // No one cares about SvcSendTable
17}
diff --git a/packets/messages/types/SvcServerInfo.go b/packets/messages/types/SvcServerInfo.go
deleted file mode 100644
index 9d2648b..0000000
--- a/packets/messages/types/SvcServerInfo.go
+++ /dev/null
@@ -1,43 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcServerInfo struct {
6 Protocol uint16
7 ServerCount uint32
8 IsHltv bool
9 IsDedicated bool
10 ClientCrc int32
11 MaxClasses uint16
12 MapCrc uint32
13 PlayerSlot uint8
14 MaxClients uint8
15 Unk uint32
16 TickInterval float32
17 COs byte
18 GameDir string
19 MapName string
20 SkyName string
21 HostName string
22}
23
24func ParseSvcServerInfo(reader *bitreader.ReaderType) SvcServerInfo {
25 return SvcServerInfo{
26 Protocol: reader.TryReadInt16(),
27 ServerCount: reader.TryReadInt32(),
28 IsHltv: reader.TryReadBool(),
29 IsDedicated: reader.TryReadBool(),
30 ClientCrc: int32(reader.TryReadInt32()),
31 MaxClasses: reader.TryReadInt16(),
32 MapCrc: reader.TryReadInt32(),
33 PlayerSlot: reader.TryReadInt8(),
34 MaxClients: reader.TryReadInt8(),
35 Unk: reader.TryReadInt32(),
36 TickInterval: reader.TryReadFloat32(),
37 COs: reader.TryReadInt8(),
38 GameDir: reader.TryReadString(),
39 MapName: reader.TryReadString(),
40 SkyName: reader.TryReadString(),
41 HostName: reader.TryReadString(),
42 }
43}
diff --git a/packets/messages/types/SvcSounds.go b/packets/messages/types/SvcSounds.go
deleted file mode 100644
index 2dc7974..0000000
--- a/packets/messages/types/SvcSounds.go
+++ /dev/null
@@ -1,30 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcSounds struct {
6 ReliableSound bool
7 Size int8
8 Data []byte
9}
10
11func ParseSvcSounds(reader *bitreader.ReaderType) SvcSounds {
12 reliablesound := reader.TryReadBool()
13 var size int8
14 var length int16
15 if reliablesound {
16 size = 1
17 } else {
18 size = int8(reader.TryReadInt8())
19 }
20 if reliablesound {
21 length = int16(reader.TryReadInt8())
22 } else {
23 length = int16(reader.TryReadInt16())
24 }
25 return SvcSounds{
26 ReliableSound: reliablesound,
27 Size: size,
28 Data: reader.TryReadBitsToSlice(int(length)),
29 }
30}
diff --git a/packets/messages/types/SvcSplitScreen.go b/packets/messages/types/SvcSplitScreen.go
deleted file mode 100644
index 6727558..0000000
--- a/packets/messages/types/SvcSplitScreen.go
+++ /dev/null
@@ -1,17 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcSplitScreen struct {
6 Unk bool
7 Data []byte
8}
9
10func ParseSvcSplitScreen(reader *bitreader.ReaderType) SvcSplitScreen {
11 unk := reader.TryReadBool()
12 length := reader.TryReadBits(11)
13 return SvcSplitScreen{
14 Unk: unk,
15 Data: reader.TryReadBytesToSlice(int(length / 8)),
16 }
17}
diff --git a/packets/messages/types/SvcTempEntities.go b/packets/messages/types/SvcTempEntities.go
deleted file mode 100644
index 3bfae0c..0000000
--- a/packets/messages/types/SvcTempEntities.go
+++ /dev/null
@@ -1,20 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcTempEntities struct {
8 NumEntries uint8
9 Data []byte
10}
11
12func ParseSvcTempEntities(reader *bitreader.ReaderType) SvcTempEntities {
13 numentries := reader.TryReadInt8()
14 length := reader.TryReadBits(17)
15 //reader.SkipBits(int(length)) // TODO: Read data properly
16 return SvcTempEntities{
17 NumEntries: numentries,
18 Data: reader.TryReadBitsToSlice(int(length)),
19 }
20}
diff --git a/packets/messages/types/SvcUpdateStringTable.go b/packets/messages/types/SvcUpdateStringTable.go
deleted file mode 100644
index 9f178a5..0000000
--- a/packets/messages/types/SvcUpdateStringTable.go
+++ /dev/null
@@ -1,21 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcUpdateStringTable struct {
6 TableId int8
7 NumChangedEntries int16
8 Data []byte
9}
10
11func ParseSvcUpdateStringTable(reader *bitreader.ReaderType) SvcUpdateStringTable {
12 svcupdatestringtable := SvcUpdateStringTable{
13 TableId: int8(reader.TryReadBits(5)),
14 }
15 if reader.TryReadBool() {
16 svcupdatestringtable.NumChangedEntries = int16(reader.TryReadInt16())
17 }
18 length := reader.TryReadBits(20)
19 svcupdatestringtable.Data = reader.TryReadBitsToSlice(int(length))
20 return svcupdatestringtable
21}
diff --git a/packets/messages/types/SvcUserMessage.go b/packets/messages/types/SvcUserMessage.go
deleted file mode 100644
index c7b0566..0000000
--- a/packets/messages/types/SvcUserMessage.go
+++ /dev/null
@@ -1,19 +0,0 @@
1package types
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcUserMessage struct {
8 MsgType uint8
9 Data []byte
10}
11
12func ParseSvcUserMessage(reader *bitreader.ReaderType) SvcUserMessage {
13 msgtype := reader.TryReadInt8()
14 length := reader.TryReadBits(12)
15 return SvcUserMessage{
16 MsgType: msgtype,
17 Data: reader.TryReadBitsToSlice(int(length)),
18 }
19}
diff --git a/packets/messages/types/SvcVoiceData.go b/packets/messages/types/SvcVoiceData.go
deleted file mode 100644
index f99db38..0000000
--- a/packets/messages/types/SvcVoiceData.go
+++ /dev/null
@@ -1,19 +0,0 @@
1package types
2
3import "github.com/pektezol/bitreader"
4
5type SvcVoiceData struct {
6 Client int8
7 Proximity int8
8 Data []byte
9}
10
11func ParseSvcVoiceData(reader *bitreader.ReaderType) SvcVoiceData {
12 svcvoicedata := SvcVoiceData{
13 Client: int8(reader.TryReadInt8()),
14 Proximity: int8(reader.TryReadInt8()),
15 }
16 length := reader.TryReadInt16()
17 svcvoicedata.Data = reader.TryReadBytesToSlice(int(length / 8))
18 return svcvoicedata
19}
diff --git a/packets/packet.go b/packets/packet.go
deleted file mode 100644
index 8f4a262..0000000
--- a/packets/packet.go
+++ /dev/null
@@ -1,87 +0,0 @@
1package packets
2
3import (
4 "fmt"
5
6 "github.com/pektezol/bitreader"
7 "github.com/pektezol/demoparser/packets/classes"
8 "github.com/pektezol/demoparser/packets/messages"
9)
10
11const MSSC = 2
12
13func ParsePacket(reader *bitreader.ReaderType) (status int) {
14 messageType := reader.TryReadInt8()
15 messageTick := reader.TryReadInt32()
16 messageSlot := reader.TryReadInt8()
17 _ = messageSlot
18 switch messageType {
19 case 1:
20 signOn := SignOn{
21 PacketInfo: classes.ParseCmdInfo(reader, MSSC),
22 InSequence: int32(reader.TryReadInt32()),
23 OutSequence: int32(reader.TryReadInt32()),
24 }
25 size := int(reader.TryReadInt32())
26 signOn.Data = messages.ParseMessage(reader.TryReadBytesToSlice(size))
27 // fmt.Printf("[%d] (%d) {%d} SignOn: %v\n", messageTick, messageType, messageSlot, signOn)
28 return 1
29 case 2:
30 packet := Packet{
31 PacketInfo: classes.ParseCmdInfo(reader, MSSC),
32 InSequence: int32(reader.TryReadInt32()),
33 OutSequence: int32(reader.TryReadInt32()),
34 }
35 size := int(reader.TryReadInt32())
36 packet.Data = messages.ParseMessage(reader.TryReadBytesToSlice(size))
37 // fmt.Printf("[%d] (%d) Packet: %v\n", messageTick, messageType, packet)
38 return 2
39 case 3:
40 syncTick := SyncTick{}
41 fmt.Printf("[%d] (%d) SyncTick: %v\n", messageTick, messageType, syncTick)
42 return 3
43 case 4:
44 size := int(reader.TryReadInt32())
45 var consoleCmd ConsoleCmd
46 consoleCmd.Data = reader.TryReadStringLen(size)
47 // fmt.Printf("[%d] (%d) ConsoleCmd: %s\n", messageTick, messageType, consoleCmd.Data)
48 return 4
49 case 5: // TODO: UserCmd - Buttons
50 userCmd := UserCmd{
51 Cmd: int32(reader.TryReadInt32()),
52 }
53 size := int(reader.TryReadInt32())
54 userCmd.Data = classes.ParseUserCmdInfo(reader.TryReadBytesToSlice(size))
55 // fmt.Printf("[%d] (%d) UserCmd: %v\n", messageTick, messageType, userCmd)
56 return 5
57 case 6: // TODO: DataTables
58 // datatables := DataTables{
59 // Size: int32(reader.TryReadInt32()),
60 // }
61 size := int(reader.TryReadInt32())
62 reader.SkipBytes(size)
63 // datatables.Data = classes.ParseDataTable(reader.TryReadBytesToSlice(int(datatables.Size)))
64 // fmt.Printf("[%d] (%d) DataTables: %v\n", messageTick, messageType, datatables)
65 return 6
66 case 7:
67 stop := Stop{
68 RemainingData: nil,
69 }
70 fmt.Printf("[%d] (%d) Stop: %v\n", messageTick, messageType, stop)
71 return 7
72 case 8: // TODO: CustomData
73 reader.SkipBytes(4)
74 size := int(reader.TryReadInt32())
75 reader.SkipBytes(size)
76 // fmt.Printf("[%d] (%d) CustomData: \n", messageTick, messageType)
77 return 8
78 case 9: // TODO: StringTables - Data
79 var stringTables StringTables
80 size := int(reader.TryReadInt32())
81 stringTables.Data = classes.ParseStringTable(reader.TryReadBytesToSlice(size))
82 // fmt.Printf("[%d] (%d) StringTables: %v\n", messageTick, messageType, stringTables)
83 return 9
84 default:
85 return 0
86 }
87}
diff --git a/pkg/classes/cmdInfo.go b/pkg/classes/cmdInfo.go
new file mode 100644
index 0000000..6e56c41
--- /dev/null
+++ b/pkg/classes/cmdInfo.go
@@ -0,0 +1,27 @@
1package classes
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type CmdInfo struct {
8 Flags int32
9 ViewOrigin []float32
10 ViewAngles []float32
11 LocalViewAngles []float32
12 ViewOrigin2 []float32
13 ViewAngles2 []float32
14 LocalViewAngles2 []float32
15}
16
17func ParseCmdInfo(reader *bitreader.ReaderType) CmdInfo {
18 return CmdInfo{
19 Flags: int32(reader.TryReadBits(32)),
20 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
21 ViewAngles: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
22 LocalViewAngles: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
23 ViewOrigin2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
24 ViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
25 LocalViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
26 }
27}
diff --git a/pkg/classes/sendTable.go b/pkg/classes/sendTable.go
new file mode 100644
index 0000000..4521464
--- /dev/null
+++ b/pkg/classes/sendTable.go
@@ -0,0 +1,106 @@
1package classes
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SendTable struct {
8 NeedsDecoder bool
9 NetTableName string
10 NumOfProps int16
11 Props []prop
12}
13
14type prop struct {
15 SendPropType int8
16 SendPropName string
17 SendPropFlags int32
18 Priority int8
19 ExcludeDtName string
20 LowValue float32
21 HighValue float32
22 NumBits int32
23 NumElements int32
24}
25
26type sendPropFlag int
27
28const (
29 Unsigned sendPropFlag = iota
30 Coord
31 NoScale
32 RoundDown
33 RoundUp
34 Normal
35 Exclude
36 Xyze
37 InsideArray
38 ProxyAlwaysYes
39 IsVectorElem
40 Collapsible
41 CoordMp
42 CoordMpLp // low precision
43 CoordMpInt
44 CellCoord
45 CellCoordLp
46 CellCoordInt
47 ChangesOften
48)
49
50type sendPropType int
51
52const (
53 Int sendPropType = iota
54 Float
55 Vector3
56 Vector2
57 String
58 Array
59 DataTable
60)
61
62func ParseSendTable(reader *bitreader.ReaderType) SendTable {
63 sendTable := SendTable{
64 NeedsDecoder: reader.TryReadBool(),
65 NetTableName: reader.TryReadString(),
66 NumOfProps: int16(reader.TryReadBits(10)),
67 // SendPropType: int8(reader.TryReadBits(5)),
68 // SendPropName: reader.TryReadString(),
69 // SendPropFlags: int16(reader.TryReadBits(16)),
70 }
71 if sendTable.NumOfProps < 0 {
72 return sendTable
73 }
74 for count := 0; count < int(sendTable.NumOfProps); count++ {
75 propType := int8(reader.TryReadBits(5))
76 if propType >= int8(7) {
77 return sendTable
78 }
79 prop := prop{
80 SendPropType: propType,
81 SendPropName: reader.TryReadString(),
82 SendPropFlags: int32(reader.TryReadBits(19)),
83 Priority: int8(reader.TryReadBits(8)),
84 }
85 if propType == int8(DataTable) || CheckBit(int64(prop.SendPropFlags), int(Exclude)) {
86 prop.ExcludeDtName = reader.TryReadString()
87 } else {
88 switch propType {
89 case int8(String), int8(Int), int8(Float), int8(Vector3), int8(Vector2):
90 prop.LowValue = reader.TryReadFloat32()
91 prop.HighValue = reader.TryReadFloat32()
92 prop.NumBits = int32(reader.TryReadBits(7))
93 case int8(Array):
94 prop.NumElements = int32(reader.TryReadBits(10))
95 default:
96 return sendTable
97 }
98 }
99 sendTable.Props = append(sendTable.Props, prop)
100 }
101 return sendTable
102}
103
104func CheckBit(val int64, bit int) bool {
105 return (val & (int64(1) << bit)) != 0
106}
diff --git a/pkg/classes/serverClassInfo.go b/pkg/classes/serverClassInfo.go
new file mode 100644
index 0000000..c60dad1
--- /dev/null
+++ b/pkg/classes/serverClassInfo.go
@@ -0,0 +1,30 @@
1package classes
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type ServerClassInfo struct {
8 ClassId int16
9 ClassName string
10 DataTableName string
11}
12
13func ParseServerClassInfo(reader *bitreader.ReaderType, count int, numOfClasses int) ServerClassInfo {
14 return ServerClassInfo{
15 ClassId: int16(reader.TryReadBits(16)),
16 ClassName: reader.TryReadString(),
17 DataTableName: reader.TryReadString(),
18 }
19}
20
21// func serverClassBits(numOfClasses int) int {
22// return highestBitIndex(uint(numOfClasses)) + 1
23// }
24
25// func highestBitIndex(i uint) int {
26// var j int
27// for j = 31; j >= 0 && (i&(1<<j)) == 0; j-- {
28// }
29// return j
30// }
diff --git a/pkg/classes/stringTable.go b/pkg/classes/stringTable.go
new file mode 100644
index 0000000..c6709f5
--- /dev/null
+++ b/pkg/classes/stringTable.go
@@ -0,0 +1,82 @@
1package classes
2
3import (
4 "bytes"
5
6 "github.com/pektezol/bitreader"
7)
8
9type StringTable struct {
10 Name string
11 TableEntries []StringTableEntry
12 Classes []StringTableClass
13}
14
15type StringTableEntry struct {
16 Name string
17 EntryData StringTableEntryData
18}
19
20type StringTableEntryData struct {
21 // TODO: Parse StringTableEntry
22}
23
24type StringTableClass struct {
25 Name string
26 Data string
27}
28
29func ParseStringTables(reader *bitreader.ReaderType) []StringTable {
30 tableCount := reader.TryReadBits(8)
31 stringTables := make([]StringTable, tableCount)
32 for i := 0; i < int(tableCount); i++ {
33 var table StringTable
34 table.ParseStream(reader)
35 stringTables[i] = table
36 }
37 return stringTables
38}
39
40func (stringTable *StringTable) ParseStream(reader *bitreader.ReaderType) {
41 stringTable.Name = reader.TryReadString()
42 entryCount := reader.TryReadBits(16)
43 stringTable.TableEntries = make([]StringTableEntry, entryCount)
44
45 for i := 0; i < int(entryCount); i++ {
46 var entry StringTableEntry
47 entry.Parse(reader)
48 stringTable.TableEntries[i] = entry
49 }
50
51 if reader.TryReadBool() {
52 classCount := reader.TryReadBits(16)
53 stringTable.Classes = make([]StringTableClass, classCount)
54
55 for i := 0; i < int(classCount); i++ {
56 var class StringTableClass
57 class.Parse(reader)
58 stringTable.Classes[i] = class
59 }
60 }
61}
62
63func (stringTableEntry *StringTableEntry) Parse(reader *bitreader.ReaderType) {
64 stringTableEntry.Name = reader.TryReadString()
65 if reader.TryReadBool() {
66 byteLen, err := reader.ReadBits(16)
67 if err != nil {
68 return
69 }
70 dataBsr := reader.TryReadBytesToSlice(int(byteLen))
71 _ = bitreader.Reader(bytes.NewReader(dataBsr), true) // TODO: Parse StringTableEntry
72 // stringTableEntry.EntryData.ParseStream(entryReader)
73 }
74}
75
76func (stringTableClass *StringTableClass) Parse(reader *bitreader.ReaderType) {
77 stringTableClass.Name = reader.TryReadString()
78 if reader.TryReadBool() {
79 dataLen := reader.TryReadBits(16)
80 stringTableClass.Data = reader.TryReadStringLen(int(dataLen))
81 }
82}
diff --git a/packets/classes/usercmd.go b/pkg/classes/userCmdInfo.go
index d3328fd..a6d9091 100644
--- a/packets/classes/usercmd.go
+++ b/pkg/classes/userCmdInfo.go
@@ -16,21 +16,21 @@ type UserCmdInfo struct {
16 SideMove float32 16 SideMove float32
17 UpMove float32 17 UpMove float32
18 Buttons int32 18 Buttons int32
19 Impulse byte 19 Impulse int8
20 WeaponSelect int 20 WeaponSelect int16
21 WeaponSubtype int 21 WeaponSubType int8
22 MouseDx int16 22 MouseDx int16
23 MouseDy int16 23 MouseDy int16
24} 24}
25 25
26func ParseUserCmdInfo(data []byte) UserCmdInfo { 26func ParseUserCmdInfo(data []byte) UserCmdInfo {
27 reader := bitreader.Reader(bytes.NewReader(data), true) 27 reader := bitreader.Reader(bytes.NewReader(data), true)
28 var userCmdInfo UserCmdInfo 28 userCmdInfo := UserCmdInfo{}
29 if reader.TryReadBool() { 29 if reader.TryReadBool() {
30 userCmdInfo.CommandNumber = int32(reader.TryReadInt32()) 30 userCmdInfo.CommandNumber = int32(reader.TryReadBits(32))
31 } 31 }
32 if reader.TryReadBool() { 32 if reader.TryReadBool() {
33 userCmdInfo.TickCount = int32(reader.TryReadInt32()) 33 userCmdInfo.TickCount = int32(reader.TryReadBits(32))
34 } 34 }
35 if reader.TryReadBool() { 35 if reader.TryReadBool() {
36 userCmdInfo.ViewAnglesX = reader.TryReadFloat32() 36 userCmdInfo.ViewAnglesX = reader.TryReadFloat32()
@@ -51,30 +51,22 @@ func ParseUserCmdInfo(data []byte) UserCmdInfo {
51 userCmdInfo.UpMove = reader.TryReadFloat32() 51 userCmdInfo.UpMove = reader.TryReadFloat32()
52 } 52 }
53 if reader.TryReadBool() { 53 if reader.TryReadBool() {
54 userCmdInfo.Buttons = int32(reader.TryReadInt32()) 54 userCmdInfo.Buttons = int32(reader.TryReadBits(32))
55 } 55 }
56 if reader.TryReadBool() { 56 if reader.TryReadBool() {
57 userCmdInfo.Impulse = reader.TryReadInt8() 57 userCmdInfo.Impulse = int8(reader.TryReadBits(8))
58 } 58 }
59 if reader.TryReadBool() { 59 if reader.TryReadBool() {
60 value, err := reader.ReadBits(11) 60 userCmdInfo.WeaponSelect = int16(reader.TryReadBits(11))
61 if err != nil {
62 panic(err)
63 }
64 userCmdInfo.WeaponSelect = int(value)
65 if reader.TryReadBool() { 61 if reader.TryReadBool() {
66 value, err := reader.ReadBits(6) 62 userCmdInfo.WeaponSubType = int8(reader.TryReadBits(6))
67 if err != nil {
68 panic(err)
69 }
70 userCmdInfo.WeaponSubtype = int(value)
71 } 63 }
72 } 64 }
73 if reader.TryReadBool() { 65 if reader.TryReadBool() {
74 userCmdInfo.MouseDx = int16(reader.TryReadInt16()) 66 userCmdInfo.MouseDx = int16(reader.TryReadBits(16))
75 } 67 }
76 if reader.TryReadBool() { 68 if reader.TryReadBool() {
77 userCmdInfo.MouseDy = int16(reader.TryReadInt16()) 69 userCmdInfo.MouseDy = int16(reader.TryReadBits(16))
78 } 70 }
79 return userCmdInfo 71 return userCmdInfo
80} 72}
diff --git a/pkg/messages/messages.go b/pkg/messages/messages.go
new file mode 100644
index 0000000..39f89e9
--- /dev/null
+++ b/pkg/messages/messages.go
@@ -0,0 +1,87 @@
1package messages
2
3import (
4 "fmt"
5 "reflect"
6
7 "github.com/pektezol/bitreader"
8 messages "github.com/pektezol/demoparser/pkg/messages/types"
9)
10
11func ParseMessages(messageType int, reader *bitreader.ReaderType) any {
12 var messageData any
13 switch messageType {
14 case 0:
15 messageData = messages.ParseNetNop(reader)
16 case 1:
17 messageData = messages.ParseNetDisconnect(reader)
18 case 2:
19 messageData = messages.ParseNetFile(reader)
20 case 3:
21 messageData = messages.ParseNetSplitScreenUser(reader)
22 case 4:
23 messageData = messages.ParseNetTick(reader)
24 case 5:
25 messageData = messages.ParseNetStringCmd(reader)
26 case 6:
27 messageData = messages.ParseNetSetConVar(reader)
28 case 7:
29 messageData = messages.ParseNetSignOnState(reader)
30 case 8:
31 messageData = messages.ParseSvcServerInfo(reader)
32 case 9:
33 messageData = messages.ParseSvcSendTable(reader)
34 case 10:
35 messageData = messages.ParseSvcClassInfo(reader)
36 case 11:
37 messageData = messages.ParseSvcSetPause(reader)
38 case 12:
39 messageData = messages.ParseSvcCreateStringTable(reader)
40 case 13:
41 messageData = messages.ParseSvcUpdateStringTable(reader)
42 case 14:
43 messageData = messages.ParseSvcVoiceInit(reader)
44 case 15:
45 messageData = messages.ParseSvcVoiceData(reader)
46 case 16:
47 messageData = messages.ParseSvcPrint(reader)
48 case 17:
49 messageData = messages.ParseSvcSounds(reader)
50 case 18:
51 messageData = messages.ParseSvcSetView(reader)
52 case 19:
53 messageData = messages.ParseSvcFixAngle(reader)
54 case 20:
55 messageData = messages.ParseSvcCrosshairAngle(reader)
56 case 21:
57 messageData = messages.ParseSvcBspDecal(reader)
58 case 22:
59 messageData = messages.ParseSvcSplitScreen(reader)
60 case 23:
61 messageData = messages.ParseSvcUserMessage(reader)
62 case 24:
63 messageData = messages.ParseSvcEntityMessage(reader)
64 case 25:
65 messageData = messages.ParseSvcGameEvent(reader)
66 case 26:
67 messageData = messages.ParseSvcPacketEntities(reader)
68 case 27:
69 messageData = messages.ParseSvcTempEntities(reader)
70 case 28:
71 messageData = messages.ParseSvcPrefetch(reader)
72 case 29:
73 messageData = messages.ParseSvcMenu(reader)
74 case 30:
75 messageData = messages.ParseSvcGameEventList(reader)
76 case 31:
77 messageData = messages.ParseSvcGetCvarValue(reader)
78 case 32:
79 messageData = messages.ParseSvcCmdKeyValues(reader)
80 case 33:
81 messageData = messages.ParseSvcPaintmapData(reader)
82 default:
83 return nil
84 }
85 fmt.Printf("\t\t(%d) %s:\n\t\t\t%+v\n", messageType, reflect.ValueOf(messageData).Type(), messageData)
86 return messageData
87}
diff --git a/packets/messages/types/NetDisconnect.go b/pkg/messages/types/netDisconnect.go
index 8b65568..69d4a67 100644
--- a/packets/messages/types/NetDisconnect.go
+++ b/pkg/messages/types/netDisconnect.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
@@ -7,5 +7,7 @@ type NetDisconnect struct {
7} 7}
8 8
9func ParseNetDisconnect(reader *bitreader.ReaderType) NetDisconnect { 9func ParseNetDisconnect(reader *bitreader.ReaderType) NetDisconnect {
10 return NetDisconnect{Text: reader.TryReadString()} 10 return NetDisconnect{
11 Text: reader.TryReadString(),
12 }
11} 13}
diff --git a/packets/messages/types/NetFile.go b/pkg/messages/types/netFile.go
index c65873d..a41a0cf 100644
--- a/packets/messages/types/NetFile.go
+++ b/pkg/messages/types/netFile.go
@@ -1,16 +1,16 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
5type NetFile struct { 5type NetFile struct {
6 TransferId uint32 6 TransferId int32
7 FileName string 7 FileName string
8 FileRequested bool 8 FileRequested bool
9} 9}
10 10
11func ParseNetFile(reader *bitreader.ReaderType) NetFile { 11func ParseNetFile(reader *bitreader.ReaderType) NetFile {
12 return NetFile{ 12 return NetFile{
13 TransferId: reader.TryReadInt32(), 13 TransferId: int32(reader.TryReadBits(32)),
14 FileName: reader.TryReadString(), 14 FileName: reader.TryReadString(),
15 FileRequested: reader.TryReadBool(), 15 FileRequested: reader.TryReadBool(),
16 } 16 }
diff --git a/pkg/messages/types/netNop.go b/pkg/messages/types/netNop.go
new file mode 100644
index 0000000..33f8e25
--- /dev/null
+++ b/pkg/messages/types/netNop.go
@@ -0,0 +1,9 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type NetNop struct{}
6
7func ParseNetNop(reader *bitreader.ReaderType) NetNop {
8 return NetNop{}
9}
diff --git a/packets/messages/types/NetSetConVar.go b/pkg/messages/types/netSetConVar.go
index eca05e0..08042ae 100644
--- a/packets/messages/types/NetSetConVar.go
+++ b/pkg/messages/types/netSetConVar.go
@@ -1,26 +1,29 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
5type NetSetConVar struct { 5type NetSetConVar struct {
6 ConVars []ConVar 6 Length int8
7 ConVars []conVar
7} 8}
8 9
9type ConVar struct { 10type conVar struct {
10 Name string 11 Name string
11 Value string 12 Value string
12} 13}
13 14
14func ParseNetSetConVar(reader *bitreader.ReaderType) NetSetConVar { 15func ParseNetSetConVar(reader *bitreader.ReaderType) NetSetConVar {
15 length := reader.TryReadInt8() 16 length := reader.TryReadBits(8)
16 convars := make([]ConVar, length) 17 convars := []conVar{}
17 for i := 0; i < int(length); i++ { 18 for count := 0; count < int(length); count++ {
18 convars[i] = ConVar{ 19 convar := conVar{
19 Name: reader.TryReadString(), 20 Name: reader.TryReadString(),
20 Value: reader.TryReadString(), 21 Value: reader.TryReadString(),
21 } 22 }
23 convars = append(convars, convar)
22 } 24 }
23 return NetSetConVar{ 25 return NetSetConVar{
26 Length: int8(length),
24 ConVars: convars, 27 ConVars: convars,
25 } 28 }
26} 29}
diff --git a/pkg/messages/types/netSignOnState.go b/pkg/messages/types/netSignOnState.go
new file mode 100644
index 0000000..4609ff2
--- /dev/null
+++ b/pkg/messages/types/netSignOnState.go
@@ -0,0 +1,26 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type NetSignOnState struct {
6 SignOnState int8
7 SpawnCount int32
8 NumServerPlayers int32
9 IdsLength int32
10 PlayersNetworksIds []byte
11 MapNameLength int32
12 MapName string
13}
14
15func ParseNetSignOnState(reader *bitreader.ReaderType) NetSignOnState {
16 netSignOnState := NetSignOnState{
17 SignOnState: int8(reader.TryReadBits(8)),
18 SpawnCount: int32(reader.TryReadBits(32)),
19 NumServerPlayers: int32(reader.TryReadBits(32)),
20 IdsLength: int32(reader.TryReadBits(32)),
21 }
22 netSignOnState.PlayersNetworksIds = reader.TryReadBytesToSlice(int(netSignOnState.IdsLength))
23 netSignOnState.MapNameLength = int32(reader.TryReadBits(32))
24 netSignOnState.MapName = reader.TryReadStringLen(int(netSignOnState.MapNameLength))
25 return netSignOnState
26}
diff --git a/packets/messages/types/NetSplitScreenUser.go b/pkg/messages/types/netSplitScreenUser.go
index d4d04b5..65e85f3 100644
--- a/packets/messages/types/NetSplitScreenUser.go
+++ b/pkg/messages/types/netSplitScreenUser.go
@@ -1,13 +1,13 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
5type NetSplitScreenUser struct { 5type NetSplitScreenUser struct {
6 PlayerSlot bool 6 Unknown bool
7} 7}
8 8
9func ParseNetSplitScreenUser(reader *bitreader.ReaderType) NetSplitScreenUser { 9func ParseNetSplitScreenUser(reader *bitreader.ReaderType) NetSplitScreenUser {
10 return NetSplitScreenUser{ 10 return NetSplitScreenUser{
11 PlayerSlot: reader.TryReadBool(), 11 Unknown: reader.TryReadBool(),
12 } 12 }
13} 13}
diff --git a/packets/messages/types/NetStringCmd.go b/pkg/messages/types/netStringCmd.go
index 1ee9f67..158658e 100644
--- a/packets/messages/types/NetStringCmd.go
+++ b/pkg/messages/types/netStringCmd.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
diff --git a/pkg/messages/types/netTick.go b/pkg/messages/types/netTick.go
new file mode 100644
index 0000000..e14f259
--- /dev/null
+++ b/pkg/messages/types/netTick.go
@@ -0,0 +1,17 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type NetTick struct {
6 Tick int32
7 HostFrameTime int16
8 HostFrameTimeStdDeviation int16
9}
10
11func ParseNetTick(reader *bitreader.ReaderType) NetTick {
12 return NetTick{
13 Tick: int32(reader.TryReadBits(32)),
14 HostFrameTime: int16(reader.TryReadBits(16) / 10e5),
15 HostFrameTimeStdDeviation: int16(reader.TryReadBits(16) / 10e5),
16 }
17}
diff --git a/pkg/messages/types/svcBspDecal.go b/pkg/messages/types/svcBspDecal.go
new file mode 100644
index 0000000..484497f
--- /dev/null
+++ b/pkg/messages/types/svcBspDecal.go
@@ -0,0 +1,61 @@
1package messages
2
3import (
4 "github.com/pektezol/bitreader"
5)
6
7type SvcBspDecal struct {
8 Pos []vectorCoord
9 DecalTextureIndex int16
10 EntityIndex int16
11 ModelIndex int16
12 LowPriority int8
13}
14
15type vectorCoord struct {
16 Value float32
17 Valid bool
18}
19
20func ParseSvcBspDecal(reader *bitreader.ReaderType) SvcBspDecal {
21 svcBspDecal := SvcBspDecal{
22 Pos: readVectorCoords(reader),
23 DecalTextureIndex: int16(reader.TryReadBits(9)),
24 }
25 if reader.TryReadBool() {
26 svcBspDecal.EntityIndex = int16(reader.TryReadBits(11))
27 svcBspDecal.ModelIndex = int16(reader.TryReadBits(11))
28 }
29 svcBspDecal.LowPriority = int8(reader.TryReadBits(1))
30 return svcBspDecal
31}
32
33func readVectorCoords(reader *bitreader.ReaderType) []vectorCoord {
34 const COORD_INTEGER_BITS uint8 = 14
35 const COORD_FRACTIONAL_BITS uint8 = 5
36 const COORD_DENOMINATOR uint8 = 1 << COORD_FRACTIONAL_BITS
37 const COORD_RESOLUTION float32 = 1.0 / float32(COORD_DENOMINATOR)
38 readVectorCoord := func() float32 {
39 value := float32(0)
40 integer := reader.TryReadBits(1)
41 fraction := reader.TryReadBits(1)
42 if integer != 0 || fraction != 0 {
43 sign := reader.TryReadBits(1)
44 if integer != 0 {
45 integer = reader.TryReadBits(int(COORD_INTEGER_BITS)) + 1
46 }
47 if fraction != 0 {
48 fraction = reader.TryReadBits(int(COORD_FRACTIONAL_BITS))
49 }
50 value = float32(integer) + float32(fraction)*COORD_RESOLUTION
51 if sign != 0 {
52 value = -value
53 }
54 }
55 return value
56 }
57 x := reader.TryReadBits(1)
58 y := reader.TryReadBits(1)
59 z := reader.TryReadBits(1)
60 return []vectorCoord{{Value: readVectorCoord(), Valid: x != 0}, {Value: readVectorCoord(), Valid: y != 0}, {Value: readVectorCoord(), Valid: z != 0}}
61}
diff --git a/pkg/messages/types/svcClassInfo.go b/pkg/messages/types/svcClassInfo.go
new file mode 100644
index 0000000..9f367d3
--- /dev/null
+++ b/pkg/messages/types/svcClassInfo.go
@@ -0,0 +1,40 @@
1package messages
2
3import (
4 "fmt"
5 "math"
6
7 "github.com/pektezol/bitreader"
8)
9
10type SvcClassInfo struct {
11 Length int16
12 CreateOnClient bool
13 ServerClasses []serverClass
14}
15
16type serverClass struct {
17 ClassId int16
18 ClassName string
19 DataTableName string
20}
21
22func ParseSvcClassInfo(reader *bitreader.ReaderType) SvcClassInfo {
23 svcClassInfo := SvcClassInfo{
24 Length: int16(reader.TryReadBits(16)),
25 CreateOnClient: reader.TryReadBool(),
26 }
27 classes := []serverClass{}
28 if !svcClassInfo.CreateOnClient {
29 for count := 0; count < int(svcClassInfo.Length); count++ {
30 fmt.Println(classes)
31 classes = append(classes, serverClass{
32 ClassId: int16(reader.TryReadBits(int(math.Log2(float64(svcClassInfo.Length)) + 1))),
33 ClassName: reader.TryReadString(),
34 DataTableName: reader.TryReadString(),
35 })
36 }
37 }
38 svcClassInfo.ServerClasses = classes
39 return svcClassInfo
40}
diff --git a/pkg/messages/types/svcCmdKeyValues.go b/pkg/messages/types/svcCmdKeyValues.go
new file mode 100644
index 0000000..1c4d819
--- /dev/null
+++ b/pkg/messages/types/svcCmdKeyValues.go
@@ -0,0 +1,16 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcCmdKeyValues struct {
6 Length int32
7 Data []byte
8}
9
10func ParseSvcCmdKeyValues(reader *bitreader.ReaderType) SvcCmdKeyValues {
11 svcCmdKeyValues := SvcCmdKeyValues{
12 Length: int32(reader.TryReadBits(32)),
13 }
14 svcCmdKeyValues.Data = reader.TryReadBytesToSlice(int(svcCmdKeyValues.Length))
15 return svcCmdKeyValues
16}
diff --git a/pkg/messages/types/svcCreateStringTable.go b/pkg/messages/types/svcCreateStringTable.go
new file mode 100644
index 0000000..ed9e477
--- /dev/null
+++ b/pkg/messages/types/svcCreateStringTable.go
@@ -0,0 +1,36 @@
1package messages
2
3import (
4 "math"
5
6 "github.com/pektezol/bitreader"
7)
8
9type SvcCreateStringTable struct {
10 Name string
11 MaxEntries int16
12 NumEntries int8
13 Length int32
14 UserDataFixedSize bool
15 UserDataSize int16
16 UserDataSizeBits int8
17 Flags int8
18 StringData int
19}
20
21func ParseSvcCreateStringTable(reader *bitreader.ReaderType) SvcCreateStringTable {
22 svcCreateStringTable := SvcCreateStringTable{
23 Name: reader.TryReadString(),
24 MaxEntries: int16(reader.TryReadBits(16)),
25 }
26 svcCreateStringTable.NumEntries = int8(reader.TryReadBits(int(math.Log2(float64(svcCreateStringTable.MaxEntries))) + 1))
27 svcCreateStringTable.Length = int32(reader.TryReadBits(20))
28 svcCreateStringTable.UserDataFixedSize = reader.TryReadBool()
29 if svcCreateStringTable.UserDataFixedSize {
30 svcCreateStringTable.UserDataSize = int16(reader.TryReadBits(12))
31 svcCreateStringTable.UserDataSizeBits = int8(reader.TryReadBits(4))
32 }
33 svcCreateStringTable.Flags = int8(reader.TryReadBits(2))
34 reader.SkipBits(int(svcCreateStringTable.Length)) // TODO: StringTable parsing
35 return svcCreateStringTable
36}
diff --git a/packets/messages/types/SvcCrosshairAngle.go b/pkg/messages/types/svcCrosshairAngle.go
index 6584426..cf18212 100644
--- a/packets/messages/types/SvcCrosshairAngle.go
+++ b/pkg/messages/types/svcCrosshairAngle.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
@@ -8,10 +8,6 @@ type SvcCrosshairAngle struct {
8 8
9func ParseSvcCrosshairAngle(reader *bitreader.ReaderType) SvcCrosshairAngle { 9func ParseSvcCrosshairAngle(reader *bitreader.ReaderType) SvcCrosshairAngle {
10 return SvcCrosshairAngle{ 10 return SvcCrosshairAngle{
11 Angle: []int16{ 11 Angle: []int16{int16(reader.TryReadBits(16)), int16(reader.TryReadBits(16)), int16(reader.TryReadBits(16))},
12 int16(reader.TryReadInt16()),
13 int16(reader.TryReadInt16()),
14 int16(reader.TryReadInt16()),
15 },
16 } 12 }
17} 13}
diff --git a/pkg/messages/types/svcEntityMessage.go b/pkg/messages/types/svcEntityMessage.go
new file mode 100644
index 0000000..9726ced
--- /dev/null
+++ b/pkg/messages/types/svcEntityMessage.go
@@ -0,0 +1,20 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcEntityMessage struct {
6 EntityIndex int16
7 ClassId int16
8 Length int16
9 Data []byte
10}
11
12func ParseSvcEntityMessage(reader *bitreader.ReaderType) SvcEntityMessage {
13 svcEntityMessage := SvcEntityMessage{
14 EntityIndex: int16(reader.TryReadBits(11)),
15 ClassId: int16(reader.TryReadBits(9)),
16 Length: int16(reader.TryReadBits(11)),
17 }
18 svcEntityMessage.Data = reader.TryReadBitsToSlice(int(svcEntityMessage.Length))
19 return svcEntityMessage
20}
diff --git a/pkg/messages/types/svcFixAngle.go b/pkg/messages/types/svcFixAngle.go
new file mode 100644
index 0000000..56acf04
--- /dev/null
+++ b/pkg/messages/types/svcFixAngle.go
@@ -0,0 +1,15 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcFixAngle struct {
6 Relative bool
7 Angle []int16
8}
9
10func ParseSvcFixAngle(reader *bitreader.ReaderType) SvcFixAngle {
11 return SvcFixAngle{
12 Relative: reader.TryReadBool(),
13 Angle: []int16{int16(reader.TryReadBits(16)), int16(reader.TryReadBits(16)), int16(reader.TryReadBits(16))},
14 }
15}
diff --git a/pkg/messages/types/svcGameEvent.go b/pkg/messages/types/svcGameEvent.go
new file mode 100644
index 0000000..6ee4d01
--- /dev/null
+++ b/pkg/messages/types/svcGameEvent.go
@@ -0,0 +1,16 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcGameEvent struct {
6 Length int16
7 Data []byte // TODO: GameEvent[]
8}
9
10func ParseSvcGameEvent(reader *bitreader.ReaderType) SvcGameEvent {
11 svcGameEvent := SvcGameEvent{
12 Length: int16(reader.TryReadBits(11)),
13 }
14 svcGameEvent.Data = reader.TryReadBitsToSlice(int(svcGameEvent.Length))
15 return svcGameEvent
16}
diff --git a/pkg/messages/types/svcGameEventList.go b/pkg/messages/types/svcGameEventList.go
new file mode 100644
index 0000000..b99ce28
--- /dev/null
+++ b/pkg/messages/types/svcGameEventList.go
@@ -0,0 +1,21 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcGameEventList struct {
6 Events int16
7 Length int32
8 GameEventDescriptor []gameEventDescriptor
9}
10
11type gameEventDescriptor struct {
12}
13
14func ParseSvcGameEventList(reader *bitreader.ReaderType) SvcGameEventList {
15 svcGameEventList := SvcGameEventList{
16 Events: int16(reader.TryReadBits(9)),
17 Length: int32(reader.TryReadBits(20)),
18 }
19 reader.TryReadBitsToSlice(int(svcGameEventList.Length))
20 return svcGameEventList
21}
diff --git a/packets/messages/types/SvcGetCvarValue.go b/pkg/messages/types/svcGetCvarValue.go
index 2925da5..aef5c8e 100644
--- a/packets/messages/types/SvcGetCvarValue.go
+++ b/pkg/messages/types/svcGetCvarValue.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
@@ -8,8 +8,9 @@ type SvcGetCvarValue struct {
8} 8}
9 9
10func ParseSvcGetCvarValue(reader *bitreader.ReaderType) SvcGetCvarValue { 10func ParseSvcGetCvarValue(reader *bitreader.ReaderType) SvcGetCvarValue {
11 return SvcGetCvarValue{ 11 svcGetCvarValue := SvcGetCvarValue{
12 Cookie: reader.TryReadStringLen(32), 12 Cookie: reader.TryReadStringLen(4),
13 CvarName: reader.TryReadString(), 13 CvarName: reader.TryReadString(),
14 } 14 }
15 return svcGetCvarValue
15} 16}
diff --git a/pkg/messages/types/svcMenu.go b/pkg/messages/types/svcMenu.go
new file mode 100644
index 0000000..d89f52c
--- /dev/null
+++ b/pkg/messages/types/svcMenu.go
@@ -0,0 +1,18 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcMenu struct {
6 MenuType int16
7 Length int32
8 Data []byte
9}
10
11func ParseSvcMenu(reader *bitreader.ReaderType) SvcMenu {
12 svcMenu := SvcMenu{
13 MenuType: int16(reader.TryReadBits(16)),
14 Length: int32(reader.TryReadBits(32)),
15 }
16 svcMenu.Data = reader.TryReadBitsToSlice(int(svcMenu.Length))
17 return svcMenu
18}
diff --git a/pkg/messages/types/svcPacketEntities.go b/pkg/messages/types/svcPacketEntities.go
new file mode 100644
index 0000000..b1c23e5
--- /dev/null
+++ b/pkg/messages/types/svcPacketEntities.go
@@ -0,0 +1,30 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcPacketEntities struct {
6 MaxEntries int16
7 IsDelta bool
8 DeltaFrom int32
9 BaseLine bool
10 UpdatedEntries int16
11 Length int32
12 UpdatedBaseline bool
13 Data []byte
14}
15
16func ParseSvcPacketEntities(reader *bitreader.ReaderType) SvcPacketEntities {
17 svcPacketEntities := SvcPacketEntities{
18 MaxEntries: int16(reader.TryReadBits(11)),
19 IsDelta: reader.TryReadBool(),
20 }
21 if svcPacketEntities.IsDelta {
22 svcPacketEntities.DeltaFrom = int32(reader.TryReadBits(32))
23 }
24 svcPacketEntities.BaseLine = reader.TryReadBool()
25 svcPacketEntities.UpdatedEntries = int16(reader.TryReadBits(11))
26 svcPacketEntities.Length = int32(reader.TryReadBits(20))
27 svcPacketEntities.UpdatedBaseline = reader.TryReadBool()
28 svcPacketEntities.Data = reader.TryReadBitsToSlice(int(svcPacketEntities.Length))
29 return svcPacketEntities
30}
diff --git a/pkg/messages/types/svcPaintmapData.go b/pkg/messages/types/svcPaintmapData.go
new file mode 100644
index 0000000..6b041da
--- /dev/null
+++ b/pkg/messages/types/svcPaintmapData.go
@@ -0,0 +1,16 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcPaintmapData struct {
6 Length int32
7 Data []byte
8}
9
10func ParseSvcPaintmapData(reader *bitreader.ReaderType) SvcPaintmapData {
11 svcPaintmapData := SvcPaintmapData{
12 Length: int32(reader.TryReadBits(32)),
13 }
14 svcPaintmapData.Data = reader.TryReadBitsToSlice(int(svcPaintmapData.Length))
15 return svcPaintmapData
16}
diff --git a/packets/messages/types/SvcPrefetch.go b/pkg/messages/types/svcPrefetch.go
index b277252..549f926 100644
--- a/packets/messages/types/SvcPrefetch.go
+++ b/pkg/messages/types/svcPrefetch.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
diff --git a/packets/messages/types/SvcPrint.go b/pkg/messages/types/svcPrint.go
index c6d91ac..8aff927 100644
--- a/packets/messages/types/SvcPrint.go
+++ b/pkg/messages/types/svcPrint.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
diff --git a/pkg/messages/types/svcSendTable.go b/pkg/messages/types/svcSendTable.go
new file mode 100644
index 0000000..ae8960b
--- /dev/null
+++ b/pkg/messages/types/svcSendTable.go
@@ -0,0 +1,17 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcSendTable struct {
6 NeedsDecoder int8
7 Length int8
8 Props int32
9}
10
11func ParseSvcSendTable(reader *bitreader.ReaderType) SvcSendTable {
12 return SvcSendTable{
13 NeedsDecoder: int8(reader.TryReadBits(8)),
14 Length: int8(reader.TryReadBits(8)),
15 Props: int32(reader.TryReadBits(32)),
16 }
17}
diff --git a/pkg/messages/types/svcServerInfo.go b/pkg/messages/types/svcServerInfo.go
new file mode 100644
index 0000000..b8bb308
--- /dev/null
+++ b/pkg/messages/types/svcServerInfo.go
@@ -0,0 +1,43 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcServerInfo struct {
6 Protocol int16
7 ServerCount int32
8 IsHltv bool
9 IsDedicated bool
10 ClientCrc int32
11 MaxClasses int16
12 MapCrc int32
13 PlayerSlot int8
14 MaxClients int8
15 Unk int32
16 TickInterval int32
17 COs int8
18 GameDir string
19 MapName string
20 SkyName string
21 HostName string
22}
23
24func ParseSvcServerInfo(reader *bitreader.ReaderType) SvcServerInfo {
25 return SvcServerInfo{
26 Protocol: int16(reader.TryReadBits(16)),
27 ServerCount: int32(reader.TryReadBits(32)),
28 IsHltv: reader.TryReadBool(),
29 IsDedicated: reader.TryReadBool(),
30 ClientCrc: int32(reader.TryReadBits(32)),
31 MaxClasses: int16(reader.TryReadBits(16)),
32 MapCrc: int32(reader.TryReadBits(32)),
33 PlayerSlot: int8(reader.TryReadBits(8)),
34 MaxClients: int8(reader.TryReadBits(8)),
35 Unk: int32(reader.TryReadBits(32)),
36 TickInterval: int32(reader.TryReadBits(32)),
37 COs: int8(reader.TryReadBits(8)),
38 GameDir: reader.TryReadString(),
39 MapName: reader.TryReadString(),
40 SkyName: reader.TryReadString(),
41 HostName: reader.TryReadString(),
42 }
43}
diff --git a/packets/messages/types/SvcSetPause.go b/pkg/messages/types/svcSetPause.go
index c71485c..94303b7 100644
--- a/packets/messages/types/SvcSetPause.go
+++ b/pkg/messages/types/svcSetPause.go
@@ -1,13 +1,13 @@
1package types 1package messages
2 2
3import ( 3import "github.com/pektezol/bitreader"
4 "github.com/pektezol/bitreader"
5)
6 4
7type SvcSetPause struct { 5type SvcSetPause struct {
8 Paused bool 6 Paused bool
9} 7}
10 8
11func ParseSvcSetPause(reader *bitreader.ReaderType) SvcSetPause { 9func ParseSvcSetPause(reader *bitreader.ReaderType) SvcSetPause {
12 return SvcSetPause{Paused: reader.TryReadBool()} 10 return SvcSetPause{
11 Paused: reader.TryReadBool(),
12 }
13} 13}
diff --git a/packets/messages/types/SvcSetView.go b/pkg/messages/types/svcSetView.go
index 5507eae..70d1e2b 100644
--- a/packets/messages/types/SvcSetView.go
+++ b/pkg/messages/types/svcSetView.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
diff --git a/pkg/messages/types/svcSounds.go b/pkg/messages/types/svcSounds.go
new file mode 100644
index 0000000..e87d584
--- /dev/null
+++ b/pkg/messages/types/svcSounds.go
@@ -0,0 +1,25 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcSounds struct {
6 ReliableSound bool
7 Size int8
8 Length int16
9 Data []byte
10}
11
12func ParseSvcSounds(reader *bitreader.ReaderType) SvcSounds {
13 svcSounds := SvcSounds{
14 ReliableSound: reader.TryReadBool(),
15 }
16 if svcSounds.ReliableSound {
17 svcSounds.Size = 1
18 svcSounds.Length = int16(reader.TryReadBits(8))
19 } else {
20 svcSounds.Size = int8(reader.TryReadBits(8))
21 svcSounds.Length = int16(reader.TryReadBits(16))
22 }
23 svcSounds.Data = reader.TryReadBitsToSlice(int(svcSounds.Length))
24 return svcSounds
25}
diff --git a/pkg/messages/types/svcSplitScreen.go b/pkg/messages/types/svcSplitScreen.go
new file mode 100644
index 0000000..9c808bc
--- /dev/null
+++ b/pkg/messages/types/svcSplitScreen.go
@@ -0,0 +1,18 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcSplitScreen struct {
6 Unk bool
7 Length int16
8 Data []byte
9}
10
11func ParseSvcSplitScreen(reader *bitreader.ReaderType) SvcSplitScreen {
12 svcSplitScreen := SvcSplitScreen{
13 Unk: reader.TryReadBool(),
14 Length: int16(reader.TryReadBits(11)),
15 }
16 svcSplitScreen.Data = reader.TryReadBitsToSlice(int(svcSplitScreen.Length))
17 return svcSplitScreen
18}
diff --git a/pkg/messages/types/svcTempEntities.go b/pkg/messages/types/svcTempEntities.go
new file mode 100644
index 0000000..d22423d
--- /dev/null
+++ b/pkg/messages/types/svcTempEntities.go
@@ -0,0 +1,18 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcTempEntities struct {
6 NumEntries int8
7 Length int32
8 Data []byte
9}
10
11func ParseSvcTempEntities(reader *bitreader.ReaderType) SvcTempEntities {
12 svcTempEntities := SvcTempEntities{
13 NumEntries: int8(reader.TryReadBits(8)),
14 Length: int32(reader.TryReadBits(17)),
15 }
16 svcTempEntities.Data = reader.TryReadBitsToSlice(int(svcTempEntities.Length))
17 return svcTempEntities
18}
diff --git a/pkg/messages/types/svcUpdateStringTable.go b/pkg/messages/types/svcUpdateStringTable.go
new file mode 100644
index 0000000..2840482
--- /dev/null
+++ b/pkg/messages/types/svcUpdateStringTable.go
@@ -0,0 +1,22 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcUpdateStringTable struct {
6 TableId int8
7 NumChangedEntries int16
8 Length int32
9 Data []byte
10}
11
12func ParseSvcUpdateStringTable(reader *bitreader.ReaderType) SvcUpdateStringTable {
13 svcUpdateStringTable := SvcUpdateStringTable{
14 TableId: int8(reader.TryReadBits(5)),
15 }
16 if reader.TryReadBool() {
17 svcUpdateStringTable.NumChangedEntries = int16(reader.TryReadBits(16))
18 }
19 svcUpdateStringTable.Length = int32(reader.TryReadBits(20))
20 svcUpdateStringTable.Data = reader.TryReadBitsToSlice(int(svcUpdateStringTable.Length))
21 return svcUpdateStringTable
22}
diff --git a/pkg/messages/types/svcUserMessage.go b/pkg/messages/types/svcUserMessage.go
new file mode 100644
index 0000000..b53c7c0
--- /dev/null
+++ b/pkg/messages/types/svcUserMessage.go
@@ -0,0 +1,18 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcUserMessage struct {
6 MsgType int8
7 Length int16
8 Data []byte
9}
10
11func ParseSvcUserMessage(reader *bitreader.ReaderType) SvcUserMessage {
12 svcUserMessage := SvcUserMessage{
13 MsgType: int8(reader.TryReadBits(8)),
14 Length: int16(reader.TryReadBits(12)),
15 }
16 svcUserMessage.Data = reader.TryReadBitsToSlice(int(svcUserMessage.Length))
17 return svcUserMessage
18}
diff --git a/pkg/messages/types/svcVoiceData.go b/pkg/messages/types/svcVoiceData.go
new file mode 100644
index 0000000..b6c81d4
--- /dev/null
+++ b/pkg/messages/types/svcVoiceData.go
@@ -0,0 +1,20 @@
1package messages
2
3import "github.com/pektezol/bitreader"
4
5type SvcVoiceData struct {
6 Client int8
7 Proximity int8
8 Length int16
9 Data []byte
10}
11
12func ParseSvcVoiceData(reader *bitreader.ReaderType) SvcVoiceData {
13 svcVoiceData := SvcVoiceData{
14 Client: int8(reader.TryReadBits(8)),
15 Proximity: int8(reader.TryReadBits(8)),
16 Length: int16(reader.TryReadBits(16)),
17 }
18 svcVoiceData.Data = reader.TryReadBitsToSlice(int(svcVoiceData.Length))
19 return svcVoiceData
20}
diff --git a/packets/messages/types/SvcVoiceInit.go b/pkg/messages/types/svcVoiceInit.go
index 3e18a7b..4c95aab 100644
--- a/packets/messages/types/SvcVoiceInit.go
+++ b/pkg/messages/types/svcVoiceInit.go
@@ -1,4 +1,4 @@
1package types 1package messages
2 2
3import "github.com/pektezol/bitreader" 3import "github.com/pektezol/bitreader"
4 4
@@ -9,12 +9,12 @@ type SvcVoiceInit struct {
9} 9}
10 10
11func ParseSvcVoiceInit(reader *bitreader.ReaderType) SvcVoiceInit { 11func ParseSvcVoiceInit(reader *bitreader.ReaderType) SvcVoiceInit {
12 svcvoiceinit := SvcVoiceInit{ 12 svcVoiceInit := SvcVoiceInit{
13 Codec: reader.TryReadString(), 13 Codec: reader.TryReadString(),
14 Quality: reader.TryReadInt8(), 14 Quality: uint8(reader.TryReadBits(8)),
15 } 15 }
16 if svcvoiceinit.Quality == 255 { 16 if svcVoiceInit.Quality == 0b11111111 {
17 svcvoiceinit.Unk = reader.TryReadFloat32() 17 svcVoiceInit.Unk = reader.TryReadFloat32()
18 } 18 }
19 return svcvoiceinit 19 return svcVoiceInit
20} 20}
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/packets/types.go b/pkg/packets/types.go
index 41d633a..6297b01 100644
--- a/packets/types.go
+++ b/pkg/packets/types.go
@@ -1,51 +1,40 @@
1package packets 1package packets
2 2
3import ( 3import "github.com/pektezol/demoparser/pkg/classes"
4 "github.com/pektezol/demoparser/packets/classes"
5 "github.com/pektezol/demoparser/packets/messages"
6)
7
8type Header struct {
9 DemoFileStamp string
10 DemoProtocol uint32
11 NetworkProtocol uint32
12 ServerName string
13 ClientName string
14 MapName string
15 GameDirectory string
16 PlaybackTime float32
17 PlaybackTicks int32
18 PlaybackFrames int32
19 SignOnLength uint32
20}
21 4
22type SignOn struct { 5type SignOn struct {
23 PacketInfo []classes.CmdInfo 6 PacketInfo []classes.CmdInfo
24 InSequence int32 7 InSequence int32
25 OutSequence int32 8 OutSequence int32
26 Data []messages.Message 9 Size int32
10 Data []any
27} 11}
28 12
29type Packet struct { 13type Packet struct {
30 PacketInfo []classes.CmdInfo 14 PacketInfo []classes.CmdInfo
31 InSequence int32 15 InSequence int32
32 OutSequence int32 16 OutSequence int32
33 Data []messages.Message 17 Size int32
18 Data []any
34} 19}
35 20
36type SyncTick struct{} 21type SyncTick struct{}
37 22
38type ConsoleCmd struct { 23type ConsoleCmd struct {
24 Size int32
39 Data string 25 Data string
40} 26}
41 27
42type UserCmd struct { 28type UserCmd struct {
43 Cmd int32 29 Cmd int32
30 Size int32
44 Data classes.UserCmdInfo 31 Data classes.UserCmdInfo
45} 32}
46 33
47type DataTables struct { 34type DataTables struct {
48 Data classes.DataTable 35 Size int32
36 SendTable []classes.SendTable
37 ServerClassInfo []classes.ServerClassInfo
49} 38}
50 39
51type Stop struct { 40type Stop struct {
@@ -54,9 +43,11 @@ type Stop struct {
54 43
55type CustomData struct { 44type CustomData struct {
56 Unknown int32 45 Unknown int32
57 Data []byte 46 Size int32
47 Data string
58} 48}
59 49
60type StringTables struct { 50type StringTables struct {
51 Size int32
61 Data []classes.StringTable 52 Data []classes.StringTable
62} 53}