You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
3.8 KiB
Go

8 years ago
package main
8 years ago
// go:generate ./mkprotos
//go:generate go run ./gen/main.go ./dota
8 years ago
import (
8 years ago
"compress/bzip2"
8 years ago
"flag"
8 years ago
"fmt"
8 years ago
"io"
"log"
8 years ago
"os"
8 years ago
"reflect"
"runtime/pprof"
8 years ago
"strings"
8 years ago
"github.com/golang/protobuf/proto"
"github.com/jordanorelli/hyperstone/ent"
"github.com/jordanorelli/hyperstone/stbl"
8 years ago
)
const (
replayHeader = "PBDEMS2\000"
)
8 years ago
func ensureNewline(t string) string {
if strings.HasSuffix(t, "\n") {
return t
}
return t + "\n"
}
func bail(status int, t string, args ...interface{}) {
var out io.Writer
if status == 0 {
out = os.Stdout
} else {
out = os.Stderr
}
fmt.Fprintf(out, ensureNewline(t), args...)
os.Exit(status)
}
8 years ago
func wrap(err error, t string, args ...interface{}) error {
if err == io.EOF {
return io.EOF
}
return fmt.Errorf(t+": %v", append(args, err)...)
}
8 years ago
type options struct {
b bool // bzip compression flag
v bool // verbose flag
f string // input file
memprofile string
cpuprofile string
8 years ago
}
func (o options) input() (io.Reader, error) {
var r io.Reader
if o.f == "--" {
r = os.Stdin
} else {
fi, err := os.Open(o.f)
if err != nil {
8 years ago
return nil, wrap(err, "unable to open file %s", o.f)
8 years ago
}
r = fi
8 years ago
}
8 years ago
if o.b {
r = bzip2.NewReader(r)
8 years ago
}
8 years ago
return r, nil
8 years ago
}
func memprofile(dest string) {
fmt.Println("writing mem profile to", dest)
w, err := os.Create(dest)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to open memprofile output %s: %v\n", dest, err)
} else {
defer w.Close()
err := pprof.WriteHeapProfile(w)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to write heap profile: %v\n", err)
}
}
}
func cpuprofile(dest string) func() {
fmt.Println("writing cpu profile to", dest)
w, err := os.Create(dest)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to open cpuprofile output %s: %v\n", dest, err)
return func() {}
} else {
pprof.StartCPUProfile(w)
return func() {
pprof.StopCPUProfile()
w.Close()
}
}
}
8 years ago
func check(msg proto.Message) {}
func printTypes(m proto.Message) {
fmt.Println(reflect.TypeOf(m))
}
8 years ago
func main() {
8 years ago
var opts options
flag.BoolVar(&opts.b, "b", false, "input is expected to be bzip-compressed")
flag.BoolVar(&opts.v, "v", false, "verbose mode")
flag.StringVar(&opts.f, "f", "--", "input file to be used. -- means stdin")
flag.StringVar(&opts.memprofile, "memprofile", "", "memory profile destination")
flag.StringVar(&opts.cpuprofile, "cpuprofile", "", "cpu profile destination")
8 years ago
flag.Parse()
8 years ago
if opts.v {
Debug.SetOutput(os.Stdout)
ent.Debug.SetOutput(os.Stdout)
stbl.Debug.SetOutput(os.Stdout)
}
8 years ago
var handle func(proto.Message)
switch flag.Arg(0) {
case "":
handle = check
case "types":
handle = printTypes
case "pretty":
handle = prettyPrint
case "string-tables":
stbl.Debug = log.New(os.Stdout, "", 0)
d := stbl.NewDict()
handle = d.Handle
8 years ago
case "class-info":
handle = dumpClasses
case "entities":
ent.Debug = log.New(os.Stdout, "", 0)
sd := stbl.NewDict()
env := new(ent.Env)
handle = func(m proto.Message) {
sd.Handle(m)
env.Handle(m)
}
8 years ago
default:
bail(1, "no such action: %s", flag.Arg(0))
}
if opts.memprofile != "" {
defer memprofile(opts.memprofile)
}
if opts.cpuprofile != "" {
defer cpuprofile(opts.cpuprofile)()
}
r, err := opts.input()
8 years ago
if err != nil {
8 years ago
bail(1, "input error: %v", err)
8 years ago
}
8 years ago
c := make(chan maybe, 32)
p := newParser(r)
delete(p.ewl, EBaseGameEvents_GE_SosStartSoundEvent)
delete(p.ewl, EDotaUserMessages_DOTA_UM_SpectatorPlayerUnitOrders)
delete(p.ewl, EDotaUserMessages_DOTA_UM_SpectatorPlayerClick)
8 years ago
delete(p.ewl, EDotaUserMessages_DOTA_UM_TE_UnitAnimation)
delete(p.ewl, EDotaUserMessages_DOTA_UM_TE_UnitAnimationEnd)
8 years ago
go p.run(c)
8 years ago
for m := range c {
if m.error != nil {
fmt.Fprintln(os.Stderr, m.error)
8 years ago
} else {
8 years ago
handle(m.Message)
8 years ago
messages.Return(m.Message)
8 years ago
}
}
8 years ago
if p.err != nil {
fmt.Printf("parser error: %v\n", p.err)
8 years ago
}
8 years ago
}