From 82871ba1bac1d62f69e1933b66659e62d2e5e063 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Tue, 12 Sep 2023 20:53:09 +0300 Subject: another rewrite, v1.0.0 --- pkg/packets/headers.go | 48 +++++++++++++++++++ pkg/packets/packets.go | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ pkg/packets/types.go | 53 +++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 pkg/packets/headers.go create mode 100644 pkg/packets/packets.go create mode 100644 pkg/packets/types.go (limited to 'pkg/packets') 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 @@ +package packets + +import ( + "fmt" + + "github.com/pektezol/bitreader" +) + +type Headers struct { + DemoFileStamp string + DemoProtocol int32 + NetworkProtocol int32 + ServerName string + ClientName string + MapName string + GameDirectory string + PlaybackTime float32 + PlaybackTicks int32 + PlaybackFrames int32 + SignOnLength int32 +} + +func ParseHeaders(reader *bitreader.ReaderType) Headers { + headers := Headers{ + DemoFileStamp: reader.TryReadString(), + DemoProtocol: int32(reader.TryReadInt32()), + NetworkProtocol: int32(reader.TryReadInt32()), + ServerName: reader.TryReadStringLen(260), + ClientName: reader.TryReadStringLen(260), + MapName: reader.TryReadStringLen(260), + GameDirectory: reader.TryReadStringLen(260), + PlaybackTime: reader.TryReadFloat32(), + PlaybackTicks: int32(reader.TryReadInt32()), + PlaybackFrames: int32(reader.TryReadInt32()), + SignOnLength: int32(reader.TryReadInt32()), + } + if headers.DemoFileStamp != "HL2DEMO" { + panic("invalid demo file stamp") + } + if headers.DemoProtocol != 4 { + panic("this parser only supports demos from new engine") + } + if headers.NetworkProtocol != 2001 { + panic("this parser only supports demos from portal 2") + } + fmt.Printf("Headers: %+v\n", headers) + return headers +} 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 @@ +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, + } +} 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 @@ +package packets + +import "github.com/pektezol/demoparser/pkg/classes" + +type SignOn struct { + PacketInfo []classes.CmdInfo + InSequence int32 + OutSequence int32 + Size int32 + Data []any +} + +type Packet struct { + PacketInfo []classes.CmdInfo + InSequence int32 + OutSequence int32 + Size int32 + Data []any +} + +type SyncTick struct{} + +type ConsoleCmd struct { + Size int32 + Data string +} + +type UserCmd struct { + Cmd int32 + Size int32 + Data classes.UserCmdInfo +} + +type DataTables struct { + Size int32 + SendTable []classes.SendTable + ServerClassInfo []classes.ServerClassInfo +} + +type Stop struct { + RemainingData []byte +} + +type CustomData struct { + Unknown int32 + Size int32 + Data string +} + +type StringTables struct { + Size int32 + Data []classes.StringTable +} -- cgit v1.2.3