func info(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("info", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> info [options] <demofile.dem> \n", os.Args[0]) fs.PrintDefaults() } fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a demo name.") } demo := fs.Arg(0) df, err := p.Get(demo) if err != nil { log.Fatalf("Getting %q: %v", demo, err) } d := dem.Open(df) timeUpdates := 0 messages := 0 blockCount := 0 for { block, err := d.ReadBlock() if err == io.EOF { break } if err != nil { log.Fatalf("Demo error: %v", err) } blockCount++ msgs, err := block.Messages() if err != nil { log.Fatalf("Getting messages: %v", err) } timeUpdatesInBlock := 0 for _, msg := range msgs { messages++ if _, ok := msg.(*dem.MsgTime); ok { timeUpdates++ timeUpdatesInBlock++ } } if timeUpdatesInBlock > 1 { fmt.Printf("Block %d had %d time updates\n", blockCount, timeUpdatesInBlock) } } fmt.Printf("Blocks: %d\n", blockCount) fmt.Printf("Messages: %d\n", messages) fmt.Printf("Time updates: %d\n", timeUpdates) }
func convert(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("convert", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> convert [options] <demofile.dem> \n", os.Args[0]) fs.PrintDefaults() } radiosity := fs.Bool("radiosity", false, "Use radiosity lighting.") fps := fs.Float64("fps", 30.0, "Frames per second.") outDir := fs.String("out", "render", "Output directory.") cameraLight := fs.Bool("camera_light", false, "Add camera light.") threesixty := fs.Bool("threesixty", false, "360 degree view mode.") fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a demo name.") } demo := fs.Arg(0) df, err := p.Get(demo) if err != nil { log.Fatalf("Getting %q: %v", demo, err) } d := dem.Open(df) var oldState *dem.State newState := dem.NewState() frameNum := 0 for { block, err := d.ReadBlock() if err == io.EOF { break } if err != nil { log.Fatalf("Demo error: %v", err) } if !newState.CameraSetViewAngle { newState.ViewAngle = block.Header.ViewAngle } seenTime := false msgs, err := block.Messages() if err != nil { log.Fatalf("Getting messages: %v", err) } for _, msg := range msgs { msg.Apply(newState) if _, ok := msg.(*dem.MsgTime); ok { seenTime = true } else if m, ok := msg.(*dem.MsgCameraPos); ok { if *verbose { fmt.Printf("Camera set to %d\n", m.Entity) } } else if m, ok := msg.(*dem.MsgIntermission); ok { if *verbose { fmt.Printf("Intermission: %q\n", m.Text) } } else if m, ok := msg.(*dem.MsgFinale); ok { if *verbose { fmt.Printf("Finale: %q\n", m.Text) } } else if m, ok := msg.(*dem.MsgCameraOrientation); ok { if *verbose { fmt.Printf("Camera angle set to <%g,%g,%g>\n", m.X, m.Y, m.Z) } } else if m, ok := msg.(*dem.MsgSpawnBaseline); ok { if false { fmt.Printf("Spawning %d: %+v\n", m.Entity, newState.ServerInfo.Models[m.Model]) } } else if m, ok := msg.(*dem.MsgUpdate); ok { if false { debugEnt := uint16(1) if m.Entity == debugEnt { fmt.Printf("MOVE Frame %d Ent %d moved from %v %v to %v %v\n", frameNum, m.Entity, oldState.Entities[m.Entity].Pos, oldState.Entities[m.Entity].Angle, newState.Entities[m.Entity].Pos, newState.Entities[m.Entity].Angle, ) } } } } if seenTime { anyFrame := false for n := range newState.Entities { newState.Entities[n].Visible = newState.SeenEntity[uint16(n)] } newState.Entities[0].Visible = true // World. if oldState != nil { if *verbose { fmt.Printf("Saw time, outputting frames between %g and %g\n", oldState.Time, newState.Time, ) } for _, t := range genTimeFrames(float64(oldState.Time), float64(newState.Time), *fps) { // TODO: Only generate frames if client state is 2. if *verbose { log.Printf("Generating frame %d", frameNum) } generateFrame(p, *outDir, oldState, newState, frameNum, t, *cameraLight, *radiosity, *threesixty) anyFrame = true frameNum++ } } // Only wipe old state if we generate any frame at all. if oldState == nil || anyFrame { oldState = newState.Copy() newState.SeenEntity = make(map[uint16]bool) } } } }