aboutsummaryrefslogtreecommitdiff
path: root/pkg/packets/packets.go
blob: a84da21ec320a5c7a94c1c7172920799b2f0d094 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package packets

import (
	"bytes"

	"github.com/pektezol/bitreader"
	"github.com/pektezol/demoparser/pkg/classes"
	"github.com/pektezol/demoparser/pkg/messages"
)

type PacketMessageInfo struct {
	PacketType int8
	TickNumber int32
	SlotNumber int8
	Data       any
}

const MSSC = 2

func ParsePackets(reader *bitreader.ReaderType) PacketMessageInfo {
	packetType := reader.TryReadBits(8)
	tickNumber := reader.TryReadBits(32)
	slotNumber := reader.TryReadBits(8)
	var packetData any
	switch packetType {
	case 1: // SignOn
		signOn := SignOn{}
		for count := 0; count < MSSC; count++ {
			signOn.PacketInfo = append(signOn.PacketInfo, classes.ParseCmdInfo(reader))
		}
		signOn.InSequence = int32(reader.TryReadBits(32))
		signOn.OutSequence = int32(reader.TryReadBits(32))
		signOn.Size = int32(reader.TryReadInt32())
		data := reader.TryReadBytesToSlice(int(signOn.Size))
		packetReader := bitreader.Reader(bytes.NewReader(data), true)
		for {
			messageType, err := packetReader.ReadBits(6)
			if err != nil {
				break
			}
			signOn.Data = append(signOn.Data, messages.ParseMessages(int(messageType), packetReader))
		}
		packetData = signOn
	case 2: // Packet
		packet := Packet{}
		for count := 0; count < MSSC; count++ {
			packet.PacketInfo = append(packet.PacketInfo, classes.ParseCmdInfo(reader))
		}
		packet.InSequence = int32(reader.TryReadBits(32))
		packet.OutSequence = int32(reader.TryReadBits(32))
		packet.Size = int32(reader.TryReadInt32())
		data := reader.TryReadBytesToSlice(int(packet.Size))
		packetReader := bitreader.Reader(bytes.NewReader(data), true)
		for {
			messageType, err := packetReader.ReadBits(6)
			if err != nil {
				break
			}
			packet.Data = append(packet.Data, messages.ParseMessages(int(messageType), packetReader))
		}
		packetData = packet
	case 3: // SyncTick
		syncTick := SyncTick{}
		packetData = syncTick
	case 4: // ConsoleCmd
		size := reader.TryReadInt32()
		consoleCmd := ConsoleCmd{
			Size: int32(size),
			Data: reader.TryReadStringLen(int(size)),
		}
		packetData = consoleCmd
	case 5: // UserCmd
		userCmd := UserCmd{}
		userCmd.Cmd = int32(reader.TryReadInt32())
		userCmd.Size = int32(reader.TryReadInt32())
		data := reader.TryReadBytesToSlice(int(userCmd.Size))
		userCmd.Data = classes.ParseUserCmdInfo(data)
		packetData = userCmd
	case 6: // DataTables
		dataTables := DataTables{}
		dataTables.Size = int32(reader.TryReadInt32())
		data := reader.TryReadBytesToSlice(int(dataTables.Size))
		dataTableReader := bitreader.Reader(bytes.NewReader(data), true)
		count := 0
		for dataTableReader.TryReadBool() {
			count++
			dataTables.SendTable = append(dataTables.SendTable, classes.ParseSendTable(dataTableReader))
		}
		numOfClasses := dataTableReader.TryReadBits(16)
		for count = 0; count < int(numOfClasses); count++ {
			dataTables.ServerClassInfo = append(dataTables.ServerClassInfo, classes.ParseServerClassInfo(dataTableReader, count, int(numOfClasses)))
		}
		packetData = dataTables
	case 7: // Stop
		stop := Stop{}
		if reader.TryReadBool() {
			// read remaining data
			stop.RemainingData = []byte{}
		}
		packetData = stop
	case 8: // CustomData
		customData := CustomData{
			Unknown: int32(reader.TryReadBits(32)),
			Size:    int32(reader.TryReadBits(32)),
		}
		customData.Data = string(reader.TryReadBytesToSlice(int(customData.Size)))
		packetData = customData
	case 9: // StringTables
		stringTables := StringTables{
			Size: int32(reader.TryReadInt32()),
		}
		data := reader.TryReadBytesToSlice(int(stringTables.Size))
		stringTableReader := bitreader.Reader(bytes.NewReader(data), true)
		stringTables.Data = classes.ParseStringTables(stringTableReader)
		packetData = stringTables
	default: // invalid
		panic("invalid packet type")
	}
	return PacketMessageInfo{
		PacketType: int8(packetType),
		TickNumber: int32(tickNumber),
		SlotNumber: int8(slotNumber),
		Data:       packetData,
	}
}