diff --git a/rep/replay.go b/rep/replay.go index 5a3b3b3..1117d06 100644 --- a/rep/replay.go +++ b/rep/replay.go @@ -29,6 +29,9 @@ type Replay struct { // Computed contains data that is computed / derived from other parts of the // replay. Computed *Computed + + // ShieldBattery holds info if game was played on ShieldBattery + ShieldBattery *ShieldBattery `json:",omitempty"` } // Compute creates and computes the Computed field. diff --git a/rep/shieldbattery.go b/rep/shieldbattery.go new file mode 100644 index 0000000..8bb9487 --- /dev/null +++ b/rep/shieldbattery.go @@ -0,0 +1,10 @@ +// This file contains the types describing info parsed from the ShieldBattery custom section. + +package rep + +// ShieldBattery models the data parsed from the ShieldBattery custom section. +type ShieldBattery struct { + StarCraftExeBuild uint32 + ShieldBatteryVersion string + GameID string +} diff --git a/repparser/repparser.go b/repparser/repparser.go index a9b93cb..e4810fb 100644 --- a/repparser/repparser.go +++ b/repparser/repparser.go @@ -222,7 +222,6 @@ func parse(dec repdecoder.Decoder, cfg Config) (*rep.Replay, error) { return nil, fmt.Errorf("Decoder.NewSection() error: %w", err) } - fmt.Println("icza ", sectionCounter) var s *Section var size int32 if sectionCounter < len(Sections) { @@ -252,7 +251,6 @@ func parse(dec repdecoder.Decoder, cfg Config) (*rep.Replay, error) { } if s == nil { - fmt.Println("icza sectionID ", sectionID) s = ModernSections[sectionID] if s == nil { // Unknown section, just skip it: @@ -1038,7 +1036,34 @@ func parsePlayerColors(data []byte, r *rep.Replay, cfg Config) error { // parseShieldBatterySection processes the ShieldBattery data. func parseShieldBatterySection(data []byte, r *rep.Replay, cfg Config) error { - // TODO + // info source: + // https://github.com/ShieldBattery/ShieldBattery/blob/master/game/src/replay.rs#L62-L80 + // https://github.com/ShieldBattery/ShieldBattery/blob/master/app/replays/parse-shieldbattery-replay.ts + + if len(data) < 0x56 { + // 0x56 bytes is the size of SB's first version of the section. + return nil // Unknown format + } + + bo := binary.LittleEndian // ByteOrder reader: little-endian + + sb := new(rep.ShieldBattery) + r.ShieldBattery = sb + + formatVersion := bo.Uint16(data) + + sb.StarCraftExeBuild = bo.Uint32(data[0x01:]) + sb.ShieldBatteryVersion, _ = cString(data[0x06:0x16]) + + // 0x16 - 0x1a: team_game_main_players + // 0x1a - 0x26: starting_races + + gameID := data[0x26:0x36] + sb.GameID = fmt.Sprintf("%x-%x-%x-%x-%x", gameID[:4], gameID[4:6], gameID[6:8], gameID[8:10], gameID[10:]) + + if formatVersion >= 0x01 { + // 0x56 - 0x58: game_logic_version + } return nil }