diff options
| author | BiSaXa <1669855+BiSaXa@users.noreply.github.com> | 2022-08-27 13:02:35 +0300 |
|---|---|---|
| committer | BiSaXa <1669855+BiSaXa@users.noreply.github.com> | 2022-08-27 13:02:35 +0300 |
| commit | f108a577658c9aab8496da4ebd0fb4f0216093e8 (patch) | |
| tree | e484a8a8b54c92ca4a393f267ebc755ec6434c8d | |
| download | sdp.go-f108a577658c9aab8496da4ebd0fb4f0216093e8.tar.gz sdp.go-f108a577658c9aab8496da4ebd0fb4f0216093e8.tar.bz2 sdp.go-f108a577658c9aab8496da4ebd0fb4f0216093e8.zip | |
init
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | classes/cmdInfo.go | 25 | ||||
| -rw-r--r-- | classes/stringTable.go | 27 | ||||
| -rw-r--r-- | classes/userCmdInfo.go | 57 | ||||
| -rw-r--r-- | go.mod | 5 | ||||
| -rw-r--r-- | go.sum | 2 | ||||
| -rw-r--r-- | main.go | 26 | ||||
| -rw-r--r-- | messages/messages.go | 89 | ||||
| -rw-r--r-- | messages/types.go | 36 | ||||
| -rw-r--r-- | utils/header.go | 43 | ||||
| -rw-r--r-- | utils/utils.go | 57 |
11 files changed, 369 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..55fc782 --- /dev/null +++ b/.gitignore | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | .vscode | ||
| 2 | *.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 @@ | |||
| 1 | package classes | ||
| 2 | |||
| 3 | import "parser/utils" | ||
| 4 | |||
| 5 | type 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 | |||
| 15 | func CmdInfoInit(bytes []byte) (output CmdInfo) { | ||
| 16 | var class CmdInfo | ||
| 17 | class.Flags = int32(utils.IntFromBytes(bytes[:4])) | ||
| 18 | class.ViewOrigin = utils.FloatArrFromBytes(bytes[4:16]) | ||
| 19 | class.ViewAngles = utils.FloatArrFromBytes(bytes[16:28]) | ||
| 20 | class.LocalViewAngles = utils.FloatArrFromBytes(bytes[28:40]) | ||
| 21 | class.ViewOrigin2 = utils.FloatArrFromBytes(bytes[40:52]) | ||
| 22 | class.ViewAngles2 = utils.FloatArrFromBytes(bytes[52:64]) | ||
| 23 | class.LocalViewAngles2 = utils.FloatArrFromBytes(bytes[64:76]) | ||
| 24 | return class | ||
| 25 | } | ||
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 @@ | |||
| 1 | package classes | ||
| 2 | |||
| 3 | type StringTable struct { | ||
| 4 | NumOfTables int32 | ||
| 5 | TableName string | ||
| 6 | NumOfEntries int16 | ||
| 7 | EntryName string | ||
| 8 | EntrySize int16 | ||
| 9 | EntryData []byte | ||
| 10 | NumOfClientEntries int16 | ||
| 11 | ClientEntryName string | ||
| 12 | ClientEntrySize int16 | ||
| 13 | ClientEntryData []byte | ||
| 14 | } | ||
| 15 | |||
| 16 | /* | ||
| 17 | func StringTableInit(bytes []byte) (output StringTable) { | ||
| 18 | var class StringTable | ||
| 19 | class.NumOfTables = int(utils.IntFromBytes(bytes[:1])) | ||
| 20 | class.TableName = string(bytes[1:16]) | ||
| 21 | class.ViewAngles = utils.FloatArrFromBytes(bytes[16:28]) | ||
| 22 | class.LocalViewAngles = utils.FloatArrFromBytes(bytes[28:40]) | ||
| 23 | class.ViewOrigin2 = utils.FloatArrFromBytes(bytes[40:52]) | ||
| 24 | class.ViewAngles2 = utils.FloatArrFromBytes(bytes[52:64]) | ||
| 25 | class.LocalViewAngles2 = utils.FloatArrFromBytes(bytes[64:76]) | ||
| 26 | return class | ||
| 27 | }*/ | ||
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 @@ | |||
| 1 | package classes | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "parser/utils" | ||
| 5 | ) | ||
| 6 | |||
| 7 | type UserCmdInfo struct { | ||
| 8 | CommandNumber int32 | ||
| 9 | TickCount int32 | ||
| 10 | ViewAnglesX float32 | ||
| 11 | ViewAnglesY float32 | ||
| 12 | ViewAnglesZ float32 | ||
| 13 | ForwardMove float32 | ||
| 14 | SideMove float32 | ||
| 15 | UpMove float32 | ||
| 16 | Buttons int32 | ||
| 17 | Impulse byte | ||
| 18 | /*WeaponSelect int | ||
| 19 | WeaponSubtype int | ||
| 20 | MouseDx int16 | ||
| 21 | MouseDy int16*/ | ||
| 22 | } | ||
| 23 | |||
| 24 | func UserCmdInfoInit(byteArr []byte, size int) (output UserCmdInfo) { | ||
| 25 | var class UserCmdInfo | ||
| 26 | if size-1 >= 4 { | ||
| 27 | class.CommandNumber = int32(utils.IntFromBytes(byteArr[:4])) | ||
| 28 | } | ||
| 29 | if size-1 >= 8 { | ||
| 30 | class.TickCount = int32(utils.IntFromBytes(byteArr[4:8])) | ||
| 31 | } | ||
| 32 | if size-1 >= 12 { | ||
| 33 | class.ViewAnglesX = utils.FloatFromBytes(byteArr[8:12]) | ||
| 34 | } | ||
| 35 | if size-1 >= 16 { | ||
| 36 | class.ViewAnglesY = utils.FloatFromBytes(byteArr[12:16]) | ||
| 37 | } | ||
| 38 | if size-1 >= 20 { | ||
| 39 | class.ViewAnglesZ = utils.FloatFromBytes(byteArr[16:20]) | ||
| 40 | } | ||
| 41 | if size-1 >= 24 { | ||
| 42 | class.ForwardMove = utils.FloatFromBytes(byteArr[20:24]) | ||
| 43 | } | ||
| 44 | if size-1 >= 28 { | ||
| 45 | class.SideMove = utils.FloatFromBytes(byteArr[24:28]) | ||
| 46 | } | ||
| 47 | if size-1 >= 32 { | ||
| 48 | class.UpMove = utils.FloatFromBytes(byteArr[28:32]) | ||
| 49 | } | ||
| 50 | if size-1 >= 36 { | ||
| 51 | class.Buttons = int32(utils.IntFromBytes(byteArr[32:36])) | ||
| 52 | } | ||
| 53 | if size-1 >= 40 { | ||
| 54 | class.Impulse = byteArr[36] | ||
| 55 | } | ||
| 56 | return class | ||
| 57 | } | ||
| @@ -0,0 +1,5 @@ | |||
| 1 | module parser | ||
| 2 | |||
| 3 | go 1.19 | ||
| 4 | |||
| 5 | require github.com/potterxu/bitreader v0.0.2 | ||
| @@ -0,0 +1,2 @@ | |||
| 1 | github.com/potterxu/bitreader v0.0.2 h1:oFOXpMwuatGrIY6pmBAQRpwt1lRWfINOtU+XT03/eTc= | ||
| 2 | github.com/potterxu/bitreader v0.0.2/go.mod h1:zvQewWmu5YxT6gjvCjlpziVv3S/CTHMeRqo+pcgROmo= | ||
| @@ -0,0 +1,26 @@ | |||
| 1 | package main | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "log" | ||
| 5 | "os" | ||
| 6 | "parser/messages" | ||
| 7 | "parser/utils" | ||
| 8 | ) | ||
| 9 | |||
| 10 | func main() { | ||
| 11 | if len(os.Args) != 2 { | ||
| 12 | log.Fatal("Specifiy file in command line arguments.") | ||
| 13 | } | ||
| 14 | file, err := os.Open(os.Args[1]) | ||
| 15 | utils.CheckError(err) | ||
| 16 | utils.HeaderOut(file) | ||
| 17 | for { | ||
| 18 | code := messages.MessageTypeCheck(file) | ||
| 19 | if code == 7 { | ||
| 20 | messages.MessageTypeCheck(file) | ||
| 21 | break // TODO: Check last CustomData | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | //defer file.Close() | ||
| 26 | } | ||
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 @@ | |||
| 1 | package messages | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "os" | ||
| 6 | "parser/classes" | ||
| 7 | "parser/utils" | ||
| 8 | ) | ||
| 9 | |||
| 10 | func MessageTypeCheck(file *os.File) (statusCode int) { | ||
| 11 | var MSSC int32 = 2 | ||
| 12 | Type := make([]byte, 1) | ||
| 13 | Tick := make([]byte, 4) | ||
| 14 | Slot := make([]byte, 1) | ||
| 15 | file.Read(Type) | ||
| 16 | file.Read(Tick) | ||
| 17 | file.Read(Slot) | ||
| 18 | switch Type[0] { | ||
| 19 | case 0x01: // SignOn | ||
| 20 | var packet Packet | ||
| 21 | var cmdinfo classes.CmdInfo | ||
| 22 | packet.PacketInfo = utils.ReadByteFromFile(file, 76*MSSC) | ||
| 23 | packet.InSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 24 | packet.OutSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 25 | packet.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 26 | packet.Data = utils.ReadByteFromFile(file, packet.Size) | ||
| 27 | cmdinfo = classes.CmdInfoInit(packet.PacketInfo) | ||
| 28 | fmt.Println(cmdinfo) | ||
| 29 | return 1 | ||
| 30 | case 0x02: // Packet | ||
| 31 | var packet Packet | ||
| 32 | var cmdinfo classes.CmdInfo | ||
| 33 | packet.PacketInfo = utils.ReadByteFromFile(file, 76*MSSC) | ||
| 34 | packet.InSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 35 | packet.OutSequence = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 36 | packet.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 37 | packet.Data = utils.ReadByteFromFile(file, packet.Size) | ||
| 38 | cmdinfo = classes.CmdInfoInit(packet.PacketInfo) | ||
| 39 | fmt.Printf("[%d] %v\n", utils.IntFromBytes(Tick), cmdinfo) | ||
| 40 | return 2 | ||
| 41 | case 0x03: // SyncTick | ||
| 42 | return 3 | ||
| 43 | case 0x04: // Consolecmd | ||
| 44 | var consolecmd ConsoleCmd | ||
| 45 | consolecmd.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 46 | consolecmd.Data = string(utils.ReadByteFromFile(file, consolecmd.Size)) | ||
| 47 | fmt.Printf("[%d] %s\n", utils.IntFromBytes(Tick), consolecmd.Data) | ||
| 48 | return 4 | ||
| 49 | case 0x05: // Usercmd FIXME: Correct bit-packing inside classes | ||
| 50 | var usercmd UserCmd | ||
| 51 | //var usercmdinfo classes.UserCmdInfo | ||
| 52 | usercmd.Cmd = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 53 | usercmd.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 54 | usercmd.Data = utils.ReadByteFromFile(file, usercmd.Size) | ||
| 55 | //usercmdinfo = classes.UserCmdInfoInit(usercmd.Data, int(usercmd.Size)) | ||
| 56 | //fmt.Printf("[%d] UserCmd: %v\n", utils.IntFromBytes(Tick), usercmdinfo) | ||
| 57 | return 5 | ||
| 58 | case 0x06: // DataTables | ||
| 59 | var datatables DataTables | ||
| 60 | //var stringtable classes.StringTable | ||
| 61 | datatables.Size = int32(utils.IntFromBytes(utils.ReadByteFromFile(file, 4))) | ||
| 62 | datatables.Data = utils.ReadByteFromFile(file, datatables.Size) | ||
| 63 | // stringtable = classes.StringTableInit(Data) | ||
| 64 | // fmt.Printf("[%d] DataTables: %v\n", utils.IntFromBytes(Size), stringtable) | ||
| 65 | return 6 | ||
| 66 | case 0x07: // Stop | ||
| 67 | fmt.Println("Stop") | ||
| 68 | return 7 | ||
| 69 | case 0x08: // CustomData | ||
| 70 | Unknown := make([]byte, 4) | ||
| 71 | file.Read(Unknown) | ||
| 72 | Size := make([]byte, 4) | ||
| 73 | file.Read(Size) | ||
| 74 | Data := make([]byte, utils.IntFromBytes(Size)) | ||
| 75 | file.Read(Data) | ||
| 76 | return 8 | ||
| 77 | case 0x09: // StringTables | ||
| 78 | Size := make([]byte, 4) | ||
| 79 | file.Read(Size) | ||
| 80 | Data := make([]byte, utils.IntFromBytes(Size)) | ||
| 81 | file.Read(Data) | ||
| 82 | return 9 | ||
| 83 | default: | ||
| 84 | return 0 | ||
| 85 | } | ||
| 86 | //fmt.Println(Type[0]) | ||
| 87 | //fmt.Println(utils.IntFromBytes(Tick)) | ||
| 88 | //fmt.Println(Slot[0]) | ||
| 89 | } | ||
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 @@ | |||
| 1 | package messages | ||
| 2 | |||
| 3 | type Packet struct { | ||
| 4 | PacketInfo []byte | ||
| 5 | InSequence int32 | ||
| 6 | OutSequence int32 | ||
| 7 | Size int32 | ||
| 8 | Data []byte | ||
| 9 | } | ||
| 10 | |||
| 11 | type ConsoleCmd struct { | ||
| 12 | Size int32 | ||
| 13 | Data string | ||
| 14 | } | ||
| 15 | |||
| 16 | type UserCmd struct { | ||
| 17 | Cmd int32 | ||
| 18 | Size int32 | ||
| 19 | Data []byte | ||
| 20 | } | ||
| 21 | |||
| 22 | type DataTables struct { | ||
| 23 | Size int32 | ||
| 24 | Data []byte | ||
| 25 | } | ||
| 26 | |||
| 27 | type CustomData struct { | ||
| 28 | Unknown int32 | ||
| 29 | Size int32 | ||
| 30 | Data []byte | ||
| 31 | } | ||
| 32 | |||
| 33 | type StringTables struct { | ||
| 34 | Size int32 | ||
| 35 | Data []byte | ||
| 36 | } | ||
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 @@ | |||
| 1 | package utils | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "os" | ||
| 6 | ) | ||
| 7 | |||
| 8 | func HeaderOut(file *os.File) { | ||
| 9 | DemoFileStamp := make([]byte, 8) | ||
| 10 | DemoProtocol := make([]byte, 4) | ||
| 11 | NetworkProtocol := make([]byte, 4) | ||
| 12 | ServerName := make([]byte, 260) | ||
| 13 | ClientName := make([]byte, 260) | ||
| 14 | MapName := make([]byte, 260) | ||
| 15 | GameDirectory := make([]byte, 260) | ||
| 16 | PlaybackTime := make([]byte, 4) | ||
| 17 | PlaybackTicks := make([]byte, 4) | ||
| 18 | PlaybackFrames := make([]byte, 4) | ||
| 19 | SignOnLength := make([]byte, 4) | ||
| 20 | file.Read(DemoFileStamp) | ||
| 21 | file.Read(DemoProtocol) | ||
| 22 | file.Read(NetworkProtocol) | ||
| 23 | file.Read(ServerName) | ||
| 24 | file.Read(ClientName) | ||
| 25 | file.Read(MapName) | ||
| 26 | file.Read(GameDirectory) | ||
| 27 | file.Read(PlaybackTime) | ||
| 28 | file.Read(PlaybackTicks) | ||
| 29 | file.Read(PlaybackFrames) | ||
| 30 | file.Read(SignOnLength) | ||
| 31 | |||
| 32 | fmt.Println(string(DemoFileStamp)) | ||
| 33 | fmt.Println(IntFromBytes(DemoProtocol)) | ||
| 34 | fmt.Println(IntFromBytes(NetworkProtocol)) | ||
| 35 | fmt.Println(string(ServerName)) | ||
| 36 | fmt.Println(string(ClientName)) | ||
| 37 | fmt.Println(string(MapName)) | ||
| 38 | fmt.Println(string(GameDirectory)) | ||
| 39 | fmt.Println(FloatFromBytes(PlaybackTime)) | ||
| 40 | fmt.Println(IntFromBytes(PlaybackTicks)) | ||
| 41 | fmt.Println(IntFromBytes(PlaybackFrames)) | ||
| 42 | fmt.Println(IntFromBytes(SignOnLength)) | ||
| 43 | } | ||
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 @@ | |||
| 1 | package utils | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "encoding/binary" | ||
| 5 | "log" | ||
| 6 | "math" | ||
| 7 | "os" | ||
| 8 | "unsafe" | ||
| 9 | |||
| 10 | "github.com/potterxu/bitreader" | ||
| 11 | ) | ||
| 12 | |||
| 13 | func ReadByteFromFile(file *os.File, size int32) []byte { | ||
| 14 | tmp := make([]byte, size) | ||
| 15 | file.Read(tmp) | ||
| 16 | return tmp | ||
| 17 | } | ||
| 18 | |||
| 19 | func CheckError(e error) { | ||
| 20 | if e != nil { | ||
| 21 | log.Panic(e) | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | func CheckFirstBit(byteArr []byte) bool { | ||
| 26 | reader := bitreader.BitReader(byteArr) | ||
| 27 | state, err := reader.ReadBit() | ||
| 28 | if err != nil { | ||
| 29 | state = false | ||
| 30 | } | ||
| 31 | return state | ||
| 32 | } | ||
| 33 | |||
| 34 | func IntFromBytes(byteArr []byte) uint32 { | ||
| 35 | int := binary.LittleEndian.Uint32(byteArr) | ||
| 36 | return int | ||
| 37 | } | ||
| 38 | |||
| 39 | func FloatFromBytes(byteArr []byte) float32 { | ||
| 40 | bits := binary.LittleEndian.Uint32(byteArr) | ||
| 41 | float := math.Float32frombits(bits) | ||
| 42 | return float | ||
| 43 | } | ||
| 44 | |||
| 45 | func FloatArrFromBytes(byteArr []byte) []float32 { | ||
| 46 | if len(byteArr) == 0 { | ||
| 47 | return nil | ||
| 48 | } | ||
| 49 | |||
| 50 | l := len(byteArr) / 4 | ||
| 51 | ptr := unsafe.Pointer(&byteArr[0]) | ||
| 52 | // It is important to keep in mind that the Go garbage collector | ||
| 53 | // will not interact with this data, and that if src if freed, | ||
| 54 | // the behavior of any Go code using the slice is nondeterministic. | ||
| 55 | // Reference: https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices | ||
| 56 | return (*[1 << 26]float32)((*[1 << 26]float32)(ptr))[:l:l] | ||
| 57 | } | ||