first commit
This commit is contained in:
3
parse/const.go
Normal file
3
parse/const.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package parse
|
||||
|
||||
const SIGNATURE = "PBDEMS2\x00"
|
||||
98
parse/parse.go
Normal file
98
parse/parse.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/olemorud/replay-parser/demo"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
Kind uint64 `json:"kind"` // see demo.proto
|
||||
Tick uint64 `json:"tick"` // time elapsed in replay time
|
||||
Size uint64 `json:"size"` // size of message in bytes
|
||||
Message *demo.CDemoFileInfo `json:"message"` // protobuf encoded message (may be compressed with snappy)
|
||||
}
|
||||
|
||||
// If kind has a certain bit set, the frame message is compressed
|
||||
// returns true if frame is compressed
|
||||
func isCompressed(frame *Frame) bool {
|
||||
return (frame.Kind&uint64(demo.EDemoCommands_DEM_IsCompressed) != 0)
|
||||
}
|
||||
|
||||
// Checks if file header is correct and returns number the address of the last frame
|
||||
func First(r *bufio.Reader) (uint64, error) {
|
||||
// Check if first 8 bytes of file matches the source 2 replay file header
|
||||
header := make([]byte, 8)
|
||||
if _, err := io.ReadFull(r, header); err != nil {
|
||||
return 0, fmt.Errorf("error when reading file: %v", err)
|
||||
}
|
||||
if string(header) != SIGNATURE {
|
||||
return 0, fmt.Errorf("wrong file signature: %v, should be ", SIGNATURE)
|
||||
}
|
||||
|
||||
// Read last frame
|
||||
var offset uint32
|
||||
err := binary.Read(r, binary.LittleEndian, &offset)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error reading number of frames in replay: %v", err)
|
||||
}
|
||||
|
||||
/// remove later
|
||||
println("size of demo is", offset, "frames")
|
||||
|
||||
return uint64(offset), nil
|
||||
}
|
||||
|
||||
// Parses the next frame on the reader
|
||||
func DecodeNextFrame(r *bufio.Reader) (*Frame, error) {
|
||||
// Read kind, tick, size and message
|
||||
frame := new(Frame)
|
||||
var err error
|
||||
|
||||
if frame.Kind, err = binary.ReadUvarint(r); err != nil {
|
||||
return nil, fmt.Errorf("error reading frame kind for frame: %v", err)
|
||||
}
|
||||
|
||||
if frame.Tick, err = binary.ReadUvarint(r); err != nil {
|
||||
return nil, fmt.Errorf("error reading frame tick for frame: %v", err)
|
||||
}
|
||||
|
||||
if frame.Size, err = binary.ReadUvarint(r); err != nil {
|
||||
return nil, fmt.Errorf("error reading frame size for frame: %v", err)
|
||||
}
|
||||
|
||||
message := make([]byte, frame.Size)
|
||||
io.ReadFull(r, message)
|
||||
|
||||
frame.Message = new(demo.CDemoFileInfo)
|
||||
|
||||
if isCompressed(frame) {
|
||||
decoded, err := snappy.Decode(nil, message)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding message: %v", err)
|
||||
}
|
||||
fmt.Println("I got decompressed :O")
|
||||
proto.Unmarshal(decoded, frame.Message)
|
||||
} else {
|
||||
proto.Unmarshal(message, frame.Message)
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Reads every single frame (probably not very efficient)
|
||||
func DecodeAllFrames(r *bufio.Reader, frameCount uint64) ([]*Frame, error) {
|
||||
replay := make([]*Frame, frameCount)
|
||||
|
||||
// Decode all frames and add them to *Frame slice
|
||||
for i := 0; i < int(frameCount); i++ {
|
||||
replay[i], _ = DecodeNextFrame(r)
|
||||
}
|
||||
|
||||
return replay, nil
|
||||
}
|
||||
Reference in New Issue
Block a user