From f108a577658c9aab8496da4ebd0fb4f0216093e8 Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Sat, 27 Aug 2022 13:02:35 +0300 Subject: init --- .gitignore | 2 ++ classes/cmdInfo.go | 25 ++++++++++++++ classes/stringTable.go | 27 +++++++++++++++ classes/userCmdInfo.go | 57 ++++++++++++++++++++++++++++++++ go.mod | 5 +++ go.sum | 2 ++ main.go | 26 +++++++++++++++ messages/messages.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ messages/types.go | 36 ++++++++++++++++++++ utils/header.go | 43 ++++++++++++++++++++++++ utils/utils.go | 57 ++++++++++++++++++++++++++++++++ 11 files changed, 369 insertions(+) create mode 100644 .gitignore create mode 100644 classes/cmdInfo.go create mode 100644 classes/stringTable.go create mode 100644 classes/userCmdInfo.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 messages/messages.go create mode 100644 messages/types.go create mode 100644 utils/header.go create mode 100644 utils/utils.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..55fc782 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +*.dem \ No newline at end of file diff --git a/classes/cmdInfo.go b/classes/cmdInfo.go new file mode 100644 index 0000000..c1faadd --- /dev/null +++ b/classes/cmdInfo.go @@ -0,0 +1,25 @@ +package classes + +import "parser/utils" + +type CmdInfo struct { + Flags int32 + ViewOrigin []float32 + ViewAngles []float32 + LocalViewAngles []float32 + ViewOrigin2 []float32 + ViewAngles2 []float32 + LocalViewAngles2 []float32 +} + +func CmdInfoInit(bytes []byte) (output CmdInfo) { + var class CmdInfo + class.Flags = int32(utils.IntFromBytes(bytes[:4])) + class.ViewOrigin = utils.FloatArrFromBytes(bytes[4:16]) + class.ViewAngles = utils.FloatArrFromBytes(bytes[16:28]) + class.LocalViewAngles = utils.FloatArrFromBytes(bytes[28:40]) + class.ViewOrigin2 = utils.FloatArrFromBytes(bytes[40:52]) + class.ViewAngles2 = utils.FloatArrFromBytes(bytes[52:64]) + class.LocalViewAngles2 = utils.FloatArrFromBytes(bytes[64:76]) + return class +} diff --git a/classes/stringTable.go b/classes/stringTable.go new file mode 100644 index 0000000..0833612 --- /dev/null +++ b/classes/stringTable.go @@ -0,0 +1,27 @@ +package classes + +type StringTable struct { + NumOfTables int32 + TableName string + NumOfEntries int16 + EntryName string + EntrySize int16 + EntryData []byte + NumOfClientEntries int16 + ClientEntryName string + ClientEntrySize int16 + ClientEntryData []byte +} + +/* +func StringTableInit(bytes []byte) (output StringTable) { + var class StringTable + class.NumOfTables = int(utils.IntFromBytes(bytes[:1])) + class.TableName = string(bytes[1:16]) + class.ViewAngles = utils.FloatArrFromBytes(bytes[16:28]) + class.LocalViewAngles = utils.FloatArrFromBytes(bytes[28:40]) + class.ViewOrigin2 = utils.FloatArrFromBytes(bytes[40:52]) + class.ViewAngles2 = utils.FloatArrFromBytes(bytes[52:64]) + class.LocalViewAngles2 = utils.FloatArrFromBytes(bytes[64:76]) + return class +}*/ diff --git a/classes/userCmdInfo.go b/classes/userCmdInfo.go new file mode 100644 index 0000000..ae27e9a --- /dev/null +++ b/classes/userCmdInfo.go @@ -0,0 +1,57 @@ +package classes + +import ( + "parser/utils" +) + +type UserCmdInfo struct { + CommandNumber int32 + TickCount int32 + ViewAnglesX float32 + ViewAnglesY float32 + ViewAnglesZ float32 + ForwardMove float32 + SideMove float32 + UpMove float32 + Buttons int32 + Impulse byte + /*WeaponSelect int + WeaponSubtype int + MouseDx int16 + MouseDy int16*/ +} + +func UserCmdInfoInit(byteArr []byte, size int) (output UserCmdInfo) { + var class UserCmdInfo + if size-1 >= 4 { + class.CommandNumber = int32(utils.IntFromBytes(byteArr[:4])) + } + if size-1 >= 8 { + class.TickCount = int32(utils.IntFromBytes(byteArr[4:8])) + } + if size-1 >= 12 { + class.ViewAnglesX = utils.FloatFromBytes(byteArr[8:12]) + } + if size-1 >= 16 { + class.ViewAnglesY = utils.FloatFromBytes(byteArr[12:16]) + } + if size-1 >= 20 { + class.ViewAnglesZ = utils.FloatFromBytes(byteArr[16:20]) + } + if size-1 >= 24 { + class.ForwardMove = utils.FloatFromBytes(byteArr[20:24]) + } + if size-1 >= 28 { + class.SideMove = utils.FloatFromBytes(byteArr[24:28]) + } + if size-1 >= 32 { + class.UpMove = utils.FloatFromBytes(byteArr[28:32]) + } + if size-1 >= 36 { + class.Buttons = int32(utils.IntFromBytes(byteArr[32:36])) + } + if size-1 >= 40 { + class.Impulse = byteArr[36] + } + return class +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e58d4e9 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module parser + +go 1.19 + +require github.com/potterxu/bitreader v0.0.2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7476ab8 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/potterxu/bitreader v0.0.2 h1:oFOXpMwuatGrIY6pmBAQRpwt1lRWfINOtU+XT03/eTc= +github.com/potterxu/bitreader v0.0.2/go.mod h1:zvQewWmu5YxT6gjvCjlpziVv3S/CTHMeRqo+pcgROmo= diff --git a/main.go b/main.go new file mode 100644 index 0000000..6f9acb4 --- /dev/null +++ b/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "log" + "os" + "parser/messages" + "parser/utils" +) + +func main() { + if len(os.Args) != 2 { + log.Fatal("Specifiy file in command line arguments.") + } + file, err := os.Open(os.Args[1]) + utils.CheckError(err) + utils.HeaderOut(file) + for { + code := messages.MessageTypeCheck(file) + if code == 7 { + messages.MessageTypeCheck(file) + break // TODO: Check last CustomData + } + } + + //defer file.Close() +} diff --git a/messages/messages.go b/messages/messages.go new file mode 100644 index 0000000..db9d027 --- /dev/null +++ b/messages/messages.go @@ -0,0 +1,89 @@ +package messages + +import ( + "fmt" + "os" + "parser/classes" + "parser/utils" +) + +func MessageTypeCheck(file *os.File) (statusCode int) { + var MSSC int32 = 2 + Type := make([]byte, 1) + Tick := make([]byte, 4) + Slot := make([]byte, 1) + file.Read(Type) + file.Read(Tick) + file.Read(Slot) + switch Type[0] { + case 0x01: // SignOn + var packet Packet + var cmdinfo classes.CmdInfo + packet.PacketInfo = utils.ReadByteFromFile(file, 76*MSSC) + packet.InSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + packet.OutSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + packet.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + packet.Data = utils.ReadByteFromFile(file, packet.Size) + cmdinfo = classes.CmdInfoInit(packet.PacketInfo) + fmt.Println(cmdinfo) + return 1 + case 0x02: // Packet + var packet Packet + var cmdinfo classes.CmdInfo + packet.PacketInfo = utils.ReadByteFromFile(file, 76*MSSC) + packet.InSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + packet.OutSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + packet.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + packet.Data = utils.ReadByteFromFile(file, packet.Size) + cmdinfo = classes.CmdInfoInit(packet.PacketInfo) + fmt.Printf("[%d] %v\n", utils.IntFromBytes(Tick), cmdinfo) + return 2 + case 0x03: // SyncTick + return 3 + case 0x04: // Consolecmd + var consolecmd ConsoleCmd + consolecmd.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + consolecmd.Data = string(utils.ReadByteFromFile(file, consolecmd.Size)) + fmt.Printf("[%d] %s\n", utils.IntFromBytes(Tick), consolecmd.Data) + return 4 + case 0x05: // Usercmd FIXME: Correct bit-packing inside classes + var usercmd UserCmd + //var usercmdinfo classes.UserCmdInfo + usercmd.Cmd = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + usercmd.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + usercmd.Data = utils.ReadByteFromFile(file, usercmd.Size) + //usercmdinfo = classes.UserCmdInfoInit(usercmd.Data, int(usercmd.Size)) + //fmt.Printf("[%d] UserCmd: %v\n", utils.IntFromBytes(Tick), usercmdinfo) + return 5 + case 0x06: // DataTables + var datatables DataTables + //var stringtable classes.StringTable + datatables.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) + datatables.Data = utils.ReadByteFromFile(file, datatables.Size) + // stringtable = classes.StringTableInit(Data) + // fmt.Printf("[%d] DataTables: %v\n", utils.IntFromBytes(Size), stringtable) + return 6 + case 0x07: // Stop + fmt.Println("Stop") + return 7 + case 0x08: // CustomData + Unknown := make([]byte, 4) + file.Read(Unknown) + Size := make([]byte, 4) + file.Read(Size) + Data := make([]byte, utils.IntFromBytes(Size)) + file.Read(Data) + return 8 + case 0x09: // StringTables + Size := make([]byte, 4) + file.Read(Size) + Data := make([]byte, utils.IntFromBytes(Size)) + file.Read(Data) + return 9 + default: + return 0 + } + //fmt.Println(Type[0]) + //fmt.Println(utils.IntFromBytes(Tick)) + //fmt.Println(Slot[0]) +} diff --git a/messages/types.go b/messages/types.go new file mode 100644 index 0000000..ee42a96 --- /dev/null +++ b/messages/types.go @@ -0,0 +1,36 @@ +package messages + +type Packet struct { + PacketInfo []byte + InSequence int32 + OutSequence int32 + Size int32 + Data []byte +} + +type ConsoleCmd struct { + Size int32 + Data string +} + +type UserCmd struct { + Cmd int32 + Size int32 + Data []byte +} + +type DataTables struct { + Size int32 + Data []byte +} + +type CustomData struct { + Unknown int32 + Size int32 + Data []byte +} + +type StringTables struct { + Size int32 + Data []byte +} diff --git a/utils/header.go b/utils/header.go new file mode 100644 index 0000000..68def9e --- /dev/null +++ b/utils/header.go @@ -0,0 +1,43 @@ +package utils + +import ( + "fmt" + "os" +) + +func HeaderOut(file *os.File) { + DemoFileStamp := make([]byte, 8) + DemoProtocol := make([]byte, 4) + NetworkProtocol := make([]byte, 4) + ServerName := make([]byte, 260) + ClientName := make([]byte, 260) + MapName := make([]byte, 260) + GameDirectory := make([]byte, 260) + PlaybackTime := make([]byte, 4) + PlaybackTicks := make([]byte, 4) + PlaybackFrames := make([]byte, 4) + SignOnLength := make([]byte, 4) + file.Read(DemoFileStamp) + file.Read(DemoProtocol) + file.Read(NetworkProtocol) + file.Read(ServerName) + file.Read(ClientName) + file.Read(MapName) + file.Read(GameDirectory) + file.Read(PlaybackTime) + file.Read(PlaybackTicks) + file.Read(PlaybackFrames) + file.Read(SignOnLength) + + fmt.Println(string(DemoFileStamp)) + fmt.Println(IntFromBytes(DemoProtocol)) + fmt.Println(IntFromBytes(NetworkProtocol)) + fmt.Println(string(ServerName)) + fmt.Println(string(ClientName)) + fmt.Println(string(MapName)) + fmt.Println(string(GameDirectory)) + fmt.Println(FloatFromBytes(PlaybackTime)) + fmt.Println(IntFromBytes(PlaybackTicks)) + fmt.Println(IntFromBytes(PlaybackFrames)) + fmt.Println(IntFromBytes(SignOnLength)) +} diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..62924c2 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,57 @@ +package utils + +import ( + "encoding/binary" + "log" + "math" + "os" + "unsafe" + + "github.com/potterxu/bitreader" +) + +func ReadByteFromFile(file *os.File, size int32) []byte { + tmp := make([]byte, size) + file.Read(tmp) + return tmp +} + +func CheckError(e error) { + if e != nil { + log.Panic(e) + } +} + +func CheckFirstBit(byteArr []byte) bool { + reader := bitreader.BitReader(byteArr) + state, err := reader.ReadBit() + if err != nil { + state = false + } + return state +} + +func IntFromBytes(byteArr []byte) uint32 { + int := binary.LittleEndian.Uint32(byteArr) + return int +} + +func FloatFromBytes(byteArr []byte) float32 { + bits := binary.LittleEndian.Uint32(byteArr) + float := math.Float32frombits(bits) + return float +} + +func FloatArrFromBytes(byteArr []byte) []float32 { + if len(byteArr) == 0 { + return nil + } + + l := len(byteArr) / 4 + ptr := unsafe.Pointer(&byteArr[0]) + // It is important to keep in mind that the Go garbage collector + // will not interact with this data, and that if src if freed, + // the behavior of any Go code using the slice is nondeterministic. + // Reference: https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices + return (*[1 << 26]float32)((*[1 << 26]float32)(ptr))[:l:l] +} -- cgit v1.2.3