Skip to content

Instantly share code, notes, and snippets.

@nilsabdi
Created May 23, 2024 09:51
Show Gist options
  • Select an option

  • Save nilsabdi/08983383ea5e9757e56543c9e7d6d062 to your computer and use it in GitHub Desktop.

Select an option

Save nilsabdi/08983383ea5e9757e56543c9e7d6d062 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"log"
"os"
"github.com/dotabuff/manta"
"github.com/dotabuff/manta/dota"
)
type Entry struct {
Time int `json:"time,omitempty"`
Type string `json:"type,omitempty"`
Team int `json:"team,omitempty"`
Unit string `json:"unit,omitempty"`
Key string `json:"key,omitempty"`
Value int `json:"value,omitempty"`
Slot int `json:"slot,omitempty"`
PlayerSlot int `json:"player_slot,omitempty"`
Player1 int `json:"player1,omitempty"`
Player2 int `json:"player2,omitempty"`
AttackerName uint32 `json:"attackername,omitempty"`
TargetName uint32 `json:"targetname,omitempty"`
SourceName uint32 `json:"sourcename,omitempty"`
TargetSourceName uint32 `json:"targetsourcename,omitempty"`
AttackerHero bool `json:"attackerhero,omitempty"`
TargetHero bool `json:"targethero,omitempty"`
AttackerIllusion bool `json:"attackerillusion,omitempty"`
TargetIllusion bool `json:"targetillusion,omitempty"`
AbilityLevel int `json:"abilitylevel,omitempty"`
Inflictor uint32 `json:"inflictor,omitempty"`
GoldReason int `json:"gold_reason,omitempty"`
XpReason int `json:"xp_reason,omitempty"`
ValueName string `json:"valuename,omitempty"`
StunDuration float32 `json:"stun_duration,omitempty"`
SlowDuration float32 `json:"slow_duration,omitempty"`
Gold int `json:"gold,omitempty"`
Lh int `json:"lh,omitempty"`
Xp int `json:"xp,omitempty"`
X float32 `json:"x,omitempty"`
Y float32 `json:"y,omitempty"`
Z float32 `json:"z,omitempty"`
Stuns float32 `json:"stuns,omitempty"`
HeroID int `json:"hero_id,omitempty"`
HeroInventory []Item `json:"hero_inventory,omitempty"`
ItemSlot int `json:"itemslot,omitempty"`
Charges int `json:"charges,omitempty"`
SecondaryCharges int `json:"secondary_charges,omitempty"`
LifeState int `json:"life_state,omitempty"`
Level int `json:"level,omitempty"`
Kills int `json:"kills,omitempty"`
Deaths int `json:"deaths,omitempty"`
Assists int `json:"assists,omitempty"`
Denies int `json:"denies,omitempty"`
EntityLeft bool `json:"entityleft,omitempty"`
EHandle int `json:"ehandle,omitempty"`
ObsPlaced int `json:"obs_placed,omitempty"`
SenPlaced int `json:"sen_placed,omitempty"`
CreepsStacked int `json:"creeps_stacked,omitempty"`
CampsStacked int `json:"camps_stacked,omitempty"`
RunePickups int `json:"rune_pickups,omitempty"`
Repicked bool `json:"repicked,omitempty"`
Randomed bool `json:"randomed,omitempty"`
PredictedVictory bool `json:"pred_vict,omitempty"`
TrackedDeath bool `json:"tracked_death,omitempty"`
GreevilsGreedStack int `json:"greevils_greed_stack,omitempty"`
TrackedSourceName string `json:"tracked_sourcename,omitempty"`
FirstBloodClaimed int `json:"firstblood_claimed,omitempty"`
TeamfightParticipation float32 `json:"teamfight_participation,omitempty"`
TowersKilled int `json:"towers_killed,omitempty"`
RoshansKilled int `json:"roshans_killed,omitempty"`
ObserversPlaced int `json:"observers_placed,omitempty"`
DraftOrder int `json:"draft_order,omitempty"`
Pick bool `json:"pick,omitempty"`
DraftActiveTeam int `json:"draft_active_team,omitempty"`
DraftExtime0 int `json:"draft_extime0,omitempty"`
DraftExtime1 int `json:"draft_extime1,omitempty"`
Networth int `json:"networth,omitempty"`
Stage int `json:"stage,omitempty"`
}
type Item struct {
ID string `json:"id"`
Slot int `json:"slot"`
NumCharges int `json:"num_charges"`
NumSecondaryCharges int `json:"num_secondary_charges"`
}
func main() {
// Create a new parser instance from a file.
f, err := os.Open("7378630668_738958849.dem")
if err != nil {
log.Fatalf("unable to open file: %s", err)
}
defer f.Close()
outputFile, err := os.Create("output.json")
if err != nil {
log.Fatalf("unable to create output file: %s", err)
}
defer outputFile.Close()
var entries []Entry
p, err := manta.NewStreamParser(f)
if err != nil {
log.Fatalf("unable to create parser: %s", err)
}
// Combat log entry callback
p.Callbacks.OnCMsgDOTACombatLogEntry(func(m *dota.CMsgDOTACombatLogEntry) error {
entry := Entry{
Time: int(m.GetTimestamp()),
Type: m.GetType().String(),
AttackerName: m.GetAttackerName(),
TargetName: m.GetTargetName(),
SourceName: m.GetDamageSourceName(),
TargetSourceName: m.GetTargetSourceName(),
Inflictor: m.GetInflictorName(),
AttackerHero: m.GetIsAttackerHero(),
TargetHero: m.GetIsTargetHero(),
AttackerIllusion: m.GetIsAttackerIllusion(),
TargetIllusion: m.GetIsTargetIllusion(),
Value: int(m.GetValue()),
StunDuration: m.GetStunDuration(),
SlowDuration: m.GetSlowDuration(),
}
entries = append(entries, entry)
return nil
})
// Start parsing the replay!
p.Start()
encoder := json.NewEncoder(outputFile)
encoder.SetIndent("", " ")
if err := encoder.Encode(entries); err != nil {
log.Fatalf("Error encoding entries to JSON: %s", err)
}
log.Printf("Parse Complete!\n")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment