/// <summary> /// Parses a demo file from any engine /// </summary> /// <param name="filename">Path to the file</param> /// <returns></returns> public static CrossParseResult Parse(string filename) { var cpr = new CrossParseResult(); switch (CheckDemoType(filename)) { case Parseresult.GoldSource: cpr.Type = Parseresult.GoldSource; cpr.GsDemoInfo = GoldSourceParser.ReadGoldSourceDemo(filename); break; case Parseresult.UnsupportedFile: cpr.Type = Parseresult.UnsupportedFile; Main.Log("Demotype check resulted in an unsupported file."); break; case Parseresult.Source: cpr.Type = Parseresult.Source; var a = new SourceParser(new MemoryStream(File.ReadAllBytes(filename))); cpr.Sdi = a.Info; if (cpr.Sdi.GameDirectory == "portal") { cpr.Type = Parseresult.Portal; var lp = new L4D2BranchParser(); cpr.L4D2BranchInfo = lp.Parse(filename); } break; case Parseresult.Hlsooe: cpr.Type = Parseresult.Hlsooe; cpr.HlsooeDemoInfo = GoldSourceParser.ParseDemoHlsooe(filename); break; case Parseresult.L4D2Branch: cpr.Type = Parseresult.L4D2Branch; var l = new L4D2BranchParser(); cpr.L4D2BranchInfo = l.Parse(filename); break; default: cpr.Type = Parseresult.UnsupportedFile; Main.Log( "No idea how the f**k did this happen but default happened at switch(CheckDemoType(filename))"); break; } if (cpr.Type == Parseresult.GoldSource) { if (cpr.GsDemoInfo.ParsingErrors.Count > 0) { if (MessageBox.Show(@"Would you like to open the demo doctor?", @"Demo errors detected!", MessageBoxButtons.YesNo) == DialogResult.Yes) { using (var dd = new DemoDoctor(filename)) dd.ShowDialog(); } } } cpr.DisplayData = GetDemoDataTuples(cpr); return(cpr); }
/// <summary> /// This returns a nice string which can be assigned to the richtexbox only call it if you /// are extremely sure the demo is not corrupt. /// </summary> /// <param name="demo"></param> /// <returns></returns> public static List <Tuple <string, string> > GetDemoDataTuples(CrossParseResult demo) { //Maybe enum as 3rd tuple item? var result = new List <Tuple <string, string> >(); #region Print switch (demo.Type) { case Parseresult.UnsupportedFile: result.Add(new Tuple <string, string>("Unsupported file!", "")); break; case Parseresult.GoldSource: result = new List <Tuple <string, string> >() { new Tuple <string, string>($"Analyzed GoldSource engine demo file ({demo.GsDemoInfo.Header.GameDir}):", ""), new Tuple <string, string>($"Demo protocol", $"{demo.GsDemoInfo.Header.DemoProtocol}"), new Tuple <string, string>($"Net protocol", $"{demo.GsDemoInfo.Header.DemoProtocol}"), new Tuple <string, string>($"Directory Offset", $"{demo.GsDemoInfo.Header.DirectoryOffset}"), new Tuple <string, string>($"MapCRC", $"{demo.GsDemoInfo.Header.MapCrc}"), new Tuple <string, string>($"Map name", $"{demo.GsDemoInfo.Header.MapName}"), new Tuple <string, string>($"Game directory", $"{demo.GsDemoInfo.Header.GameDir}"), new Tuple <string, string>($"Length in seconds", $"{demo.GsDemoInfo.DirectoryEntries.Sum(x => x.TrackTime).ToString("n3")}s"), new Tuple <string, string>($"Directory Offset", $"{demo.GsDemoInfo.Header.DirectoryOffset}"), new Tuple <string, string>($"Frame count", $"{demo.GsDemoInfo.DirectoryEntries.Sum(x => x.FrameCount)}"), new Tuple <string, string>($"Highest FPS", $"{(1 / demo.GsDemoInfo.AditionalStats.FrametimeMin).ToString("N2")}"), new Tuple <string, string>($"Lowest FPS", $"{(1 / demo.GsDemoInfo.AditionalStats.FrametimeMax).ToString("N2")}"), new Tuple <string, string>($"Average FPS", $"{(demo.GsDemoInfo.AditionalStats.Count / demo.GsDemoInfo.AditionalStats.FrametimeSum).ToString("N2")}"), new Tuple <string, string>($"Lowest msec", $"{(1000.0 / demo.GsDemoInfo.AditionalStats.MsecMin).ToString("N2")} FPS"), new Tuple <string, string>($"Highest msec", $"{(1000.0 / demo.GsDemoInfo.AditionalStats.MsecMax).ToString("N2")} FPS"), new Tuple <string, string>($"Frame count", $"{demo.GsDemoInfo.DirectoryEntries.Sum(x => x.FrameCount)}"), new Tuple <string, string>($"Average msec", $"{(1000.0 / (demo.GsDemoInfo.AditionalStats.MsecSum / (double)demo.GsDemoInfo.AditionalStats.Count)).ToString("N2")} FPS") }; break; case Parseresult.Hlsooe: result = new List <Tuple <string, string> >() { new Tuple <string, string>($"Demo protocol", $"{demo.HlsooeDemoInfo.Header.DemoProtocol}"), new Tuple <string, string>($"Net protocol", $"{demo.HlsooeDemoInfo.Header.NetProtocol}"), new Tuple <string, string>($"Directory offset", $"{demo.HlsooeDemoInfo.Header.DirectoryOffset}"), new Tuple <string, string>($"Map name", $"{demo.HlsooeDemoInfo.Header.MapName}"), new Tuple <string, string>($"Game directory", $"{demo.HlsooeDemoInfo.Header.GameDir}"), new Tuple <string, string>($"Length in seconds", $"{demo.HlsooeDemoInfo.DirectoryEntries.SkipWhile(x => x.FrameCount < 1).Max(x => x.Frames.Max(y => y.Key.Index))*0.015}s [{demo.HlsooeDemoInfo.DirectoryEntries.SkipWhile(x => x.FrameCount < 1).Max(x => x.Frames.Max(y => y.Key.Index))}ticks]"), new Tuple <string, string>($"Save flag:", $"{demo.HlsooeDemoInfo.DirectoryEntries.SkipWhile(x => x.FrameCount < 1).Max(x => x.Frames.Where((y => y.Key.Type == Hlsooe.DemoFrameType.ConsoleCommand)).FirstOrDefault(z => ((Hlsooe.ConsoleCommandFrame)(z.Value)).Command.Contains("#SAVE#")).Key.Index)*0.015} [{demo.HlsooeDemoInfo.DirectoryEntries.SkipWhile(x => x.FrameCount < 1).Max(x => x.Frames.Where((y => y.Key.Type == Hlsooe.DemoFrameType.ConsoleCommand)).FirstOrDefault(z => ((Hlsooe.ConsoleCommandFrame)(z.Value)).Command.Contains("#SAVE#")).Key.Index)}ticks]") }; break; case Parseresult.Source: result = new List <Tuple <string, string> >() { new Tuple <string, string>($"Demo protocol", $"{demo.Sdi.DemoProtocol}"), new Tuple <string, string>($"Net protocol", $"{demo.Sdi.NetProtocol}"), new Tuple <string, string>($"Server name", $"{demo.Sdi.ServerName}"), new Tuple <string, string>($"Client name", $"{demo.Sdi.ClientName}"), new Tuple <string, string>($"Map name", $"{demo.Sdi.MapName}"), new Tuple <string, string>($"Playback seconds", $"{demo.Sdi.Seconds.ToString("n3")}s"), new Tuple <string, string>($"Playback tick count", $"{demo.Sdi.TickCount}"), new Tuple <string, string>($"Event count", $"{demo.Sdi.EventCount}"), new Tuple <string, string>($"Length", $"{(demo.Sdi.Messages.SkipWhile(x => x.Type != SourceParser.MessageType.SyncTick).Max(x => x.Tick) * 0.015).ToString("n3")}s"), new Tuple <string, string>($"Ticks", $"{demo.Sdi.Messages.SkipWhile(x => x.Type != SourceParser.MessageType.SyncTick).Max(x => x.Tick)}"), }; break; case Parseresult.Portal: case Parseresult.L4D2Branch: result = new List <Tuple <string, string> >() { new Tuple <string, string>($"Demo protocol", $"{demo.L4D2BranchInfo.Header.Protocol}"), new Tuple <string, string>($"Net protocol", $"{demo.L4D2BranchInfo.Header.NetworkProtocol}"), new Tuple <string, string>($"Server name", $"{demo.L4D2BranchInfo.Header.ServerName}"), new Tuple <string, string>($"Client name", $"{demo.L4D2BranchInfo.Header.ClientName}"), new Tuple <string, string>($"Mapname", $"{demo.L4D2BranchInfo.Header.MapName}"), new Tuple <string, string>($"GameDir", $"{demo.L4D2BranchInfo.Header.GameDirectory}"), new Tuple <string, string>($"Playback seconds", $"{(demo.L4D2BranchInfo.Header.PlaybackTime).ToString("n3")}s"), new Tuple <string, string>($"Playback tick count", $"{demo.L4D2BranchInfo.Header.PlaybackTicks}"), new Tuple <string, string>($"Event count", $"{demo.L4D2BranchInfo.Header.EventCount}"), new Tuple <string, string>($"Signon Length", $"{demo.L4D2BranchInfo.Header.SignonLength}"), new Tuple <string, string>($"Tickrate", $"{demo.L4D2BranchInfo.Header.Tickrate}"), new Tuple <string, string>($"Start tick", $"{demo.L4D2BranchInfo.PortalDemoInfo?.StartAdjustmentTick}"), new Tuple <string, string>($"Type", $"{demo.L4D2BranchInfo.PortalDemoInfo?.StartAdjustmentType}"), new Tuple <string, string>($"End tick", $"{demo.L4D2BranchInfo.PortalDemoInfo?.EndAdjustmentTick}"), new Tuple <string, string>($"Type", $"{demo.L4D2BranchInfo.PortalDemoInfo?.EndAdjustmentType}"), new Tuple <string, string>($"Adjusted time", $"{demo.L4D2BranchInfo.PortalDemoInfo?.AdjustTime(demo.L4D2BranchInfo.Header.TicksPerSecond).ToString("n3")}s"), new Tuple <string, string>($"Adjusted ticks", $"{demo.L4D2BranchInfo.PortalDemoInfo?.AdjustedTicks}"), }; break; } #endregion return(FormatTuples(result)); }