diff --git a/UncraftedDemoParser/demos/ademo.dem b/UncraftedDemoParser/demos/ademo.dem deleted file mode 100644 index 2cb27e9..0000000 Binary files a/UncraftedDemoParser/demos/ademo.dem and /dev/null differ diff --git a/UncraftedDemoParser/demos/problem demos/ademo.dem b/UncraftedDemoParser/demos/problem demos/ademo.dem deleted file mode 100644 index 2cb27e9..0000000 Binary files a/UncraftedDemoParser/demos/problem demos/ademo.dem and /dev/null differ diff --git a/UncraftedDemoParser/demos/problem demos/other issues.txt b/UncraftedDemoParser/demos/problem demos/other issues.txt deleted file mode 100644 index 871f48d..0000000 --- a/UncraftedDemoParser/demos/problem demos/other issues.txt +++ /dev/null @@ -1,8 +0,0 @@ -if parsing dir, last demo will go out of bounds: -UncraftedDemoParser.exe "B:\Games\Portal Source\portal" -c -f -System.ArgumentOutOfRangeException: Index and lenfth must refer to a location with the string. -Parameter name: length: - at System.String.Substring(Int32 startIndex, int32 length) - at UncraftedDemoParser.ConsoleParsing.ConsoleOptions.MainLoop() - at UncraftedDemoParser.ConsoleParsing.ConsoleOptions.ParseOptions(String[] args) - at UncraftedDemoParser.Program.Main(String[] args) \ No newline at end of file diff --git a/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingMain.cs b/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingMain.cs index 7819f04..dc04d82 100644 --- a/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingMain.cs +++ b/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingMain.cs @@ -54,7 +54,7 @@ private static void MainLoop() { foreach (string demoPath in _demoPaths) { _currentDemo = new SourceDemo(demoPath, parse: false); string relativeDir = demoPath.GetPathRelativeTo(Application.ExecutablePath); - if (relativeDir.Substring(0, 9) == "../../../") + if (relativeDir.Length >= 9 && relativeDir.Substring(0, 9) == "../../../") relativeDir = demoPath; Console.WriteLine($"Parsing {relativeDir}..."); Debug.WriteLine($"Parsing {Path.GetFullPath(demoPath)}..."); diff --git a/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingSetup.cs b/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingSetup.cs index 95dae8a..58f271e 100644 --- a/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingSetup.cs +++ b/UncraftedDemoParser/src/ConsoleParsing/ConsoleParsingSetup.cs @@ -11,7 +11,7 @@ namespace UncraftedDemoParser.ConsoleParsing { // I tried to make this better than it was. I'm not sure if I did, but at least I made some tasty spaghetti. internal static partial class ConsoleOptions { - private const string Version = "0.1"; + private const string Version = "0.2"; // A list of all the options; each option has the following properties: // the character to set the option, the priority of that option: @@ -29,6 +29,7 @@ internal static partial class ConsoleOptions { {'p', Tuple.Create(5, false, DumpPositions, "positions", new[] {typeof(Packet)})}, {'r', Tuple.Create(5, true, DumpRegexMatches, "regex matches", new[] {typeof(ConsoleCmd)})}, {'R', Tuple.Create(8, false, SearchRecursively, null, new Type[0])}, + {'j', Tuple.Create(5, false, DumpJumps, "jump list", new[] {typeof(ConsoleCmd)})} }; // this is a separate thing cuz the above list is already supa fat @@ -41,7 +42,8 @@ internal static partial class ConsoleOptions { {"-r", $" (def.=\"{DefaultRegex}\") Dumps all console commands where the regex matches"}, {"-p", $" Dump every |tick|~|x,y,z|pitch,yaw,roll|~{{player2}}~... for all players"}, {"-c", $" Dump all suspicious commands and cheats"}, - {"-R", $" Search folders recursively"} + {"-R", $" Search folders recursively"}, + {"-h", $" Dump all jumps found in the demo"} }; // pre-parsing/const stuff @@ -56,11 +58,14 @@ internal static partial class ConsoleOptions { public static void ParseOptions(string[] args) { if (args.Length == 1) { - if (args[0] == "-h" || args[0] == "--help" || args[0] == "/?") + if (args[0] == "-h" || args[0] == "--help" || args[0] == "/?") { PrintFullHelp(); - if (args[0] == "--version") + Environment.Exit(0); + } + if (args[0] == "--version") { Console.WriteLine($"v{Version}"); - Environment.Exit(0); + Environment.Exit(0); + } } bool helpOptionSet = false; // handled separately @@ -199,8 +204,9 @@ private static void PrintFullHelp() { private static void PrintOptionHelp() { foreach (string option in UserOptions.Select(option => option.Substring(0, 2))) { - if (HelpMessages.ContainsKey(option)) - Console.WriteLine($"{option}{HelpMessages[option]}"); + Console.WriteLine(HelpMessages.ContainsKey(option) + ? $"{option}{HelpMessages[option]}" + : "No help description written"); } } diff --git a/UncraftedDemoParser/src/Parser/Components/PacketFrame.cs b/UncraftedDemoParser/src/Parser/Components/PacketFrame.cs index a29f50a..0f7ad7b 100644 --- a/UncraftedDemoParser/src/Parser/Components/PacketFrame.cs +++ b/UncraftedDemoParser/src/Parser/Components/PacketFrame.cs @@ -49,7 +49,6 @@ public PacketFrame(byte[] data, ref int pointer, SourceDemo demoRef) : base(data } int packetLength; - switch (Type) { case PacketType.SignOn: packetLength = demoRef.DemoSettings.Header.SignOnLength; @@ -78,6 +77,7 @@ public PacketFrame(byte[] data, ref int pointer, SourceDemo demoRef) : base(data packetLength = 0; break; default: + Console.WriteLine($"unexpected packet number: {Type}"); throw new ArgumentOutOfRangeException(); } diff --git a/UncraftedDemoParser/src/Program.cs b/UncraftedDemoParser/src/Program.cs index 5ddc7f2..b54661f 100644 --- a/UncraftedDemoParser/src/Program.cs +++ b/UncraftedDemoParser/src/Program.cs @@ -20,17 +20,15 @@ public static void Main(string[] args) { ConsoleOptions.ParseOptions(args); Environment.Exit(0); } else { - /*ConsoleOptions.ParseOptions(new[] - {@"../../demos/cm-08-inbounds-1182.dem", "-r", "-v", "-l", "-m", "-c", "-p", "-R", "-f", "ya boi", "-s"});*/ + ConsoleOptions.ParseOptions(new[] + {@"escape_02_1.dem"}); const string demoName = "problem demos\\chapter7"; SourceDemo sd = new SourceDemo(new DirectoryInfo($@"..\..\demos\{demoName}.dem"), false); //sd.QuickParse(); sd.ParseBytes(); - - Console.WriteLine(sd.FilteredForPacketType().Where(packet => packet.MessageType == SvcMessageType.NetTick) - .Select(packet => packet.SvcNetMessage).Cast().Select(netTick => netTick.EngineTick - netTick.Tick).Distinct().QuickToString()); - + + //File.WriteAllText(@"B:\Projects\Rider\UncraftedDemoParser\UncraftedDemoParser\bin\Debug\output.txt", sd.AsVerboseString()); //sd.UpdateBytes(); //File.WriteAllBytes(@"B:\Projects\Rider\UncraftedDemoParser\UncraftedDemoParser\bin\Debug\ademo.dem", sd.Bytes); diff --git a/UncraftedDemoParser/src/Utils/Extensions.cs b/UncraftedDemoParser/src/Utils/Extensions.cs index d429f84..97dd344 100644 --- a/UncraftedDemoParser/src/Utils/Extensions.cs +++ b/UncraftedDemoParser/src/Utils/Extensions.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using static UncraftedDemoParser.Parser.Components.Packets.Packet; @@ -9,9 +11,16 @@ namespace UncraftedDemoParser.Utils { public static class Extensions { - public static T[] SubArray(this T[] data, int index, int length) { + public static T[] SubArray(this T[] data, int index, int length, [CallerMemberName] string caller = "") { T[] result = new T[length]; - Array.Copy(data, index, result, 0, length); + if (index + length > data.Length) { + Array.Copy(data, index, result, 0, data.Length - index); + Debug.WriteLine( + $"SubArray() trying to go out of bounds, writing {(data.Length - index)} bytes instead of {length}; caller: {caller}"); + } else { + Array.Copy(data, index, result, 0, length); + } + return result; } @@ -97,6 +106,7 @@ public static string QuickToString(this IEnumerable enumerable, string sep public static string GetPathRelativeTo(this string relativeTo, string path) { + //Console.WriteLine(); return Uri.UnescapeDataString(new Uri(Path.GetFullPath(path)).MakeRelativeUri(new Uri(Path.GetFullPath(relativeTo))).ToString()); } } diff --git a/UncraftedDemoParser/src/Utils/ParserTextUtils.cs b/UncraftedDemoParser/src/Utils/ParserTextUtils.cs index 8952098..0902ade 100644 --- a/UncraftedDemoParser/src/Utils/ParserTextUtils.cs +++ b/UncraftedDemoParser/src/Utils/ParserTextUtils.cs @@ -61,7 +61,7 @@ public static string AsVerboseString(this SourceDemo sd) { } - // prints basically what listdemo prints, optionally prints the "correct" timing for length + // prints the same "wrong" tick count as listdemo+ for consistency, not including the 0th tick public static void PrintListdemoOutput(this SourceDemo sd, bool printHeader, bool printName, TextWriter writer = null) { if (!sd.FilteredForPacketType().Any()) throw new FailedToParseException("this demo is missing regular packets"); @@ -85,19 +85,30 @@ public static void PrintListdemoOutput(this SourceDemo sd, bool printHeader, boo $"\n{"Frames", -25}: {h.FrameCount}" + $"\n{"SignOn Length", -25}: {h.SignOnLength}\n\n"); } - - StringBuilder builder = new StringBuilder("\n"); - foreach (ConsoleCmd i in sd.PacketsWhereRegexMatches(new Regex("autosave"))) - builder.AppendLine($"Autosave command detected on tick {i.Tick}, time {i.Tick / sd.DemoSettings.TicksPerSeoncd:F3}"); - foreach (ConsoleCmd i in sd.PacketsWhereRegexMatches(new Regex("#save#", RegexOptions.IgnoreCase))) - builder.AppendLine($"Save flag detected on tick {i.Tick}, time {i.Tick / sd.DemoSettings.TicksPerSeoncd:F3}"); - foreach (ConsoleCmd i in sd.PacketsWhereRegexMatches(new Regex("startneurotoxins 99999"))) - builder.AppendLine( - $"End of normal game detected on tick {i.Tick}, time {i.Tick / sd.DemoSettings.TicksPerSeoncd:F3}"); - if (builder.Length > 1) { - Console.ForegroundColor = ConsoleColor.Yellow; - writer.Write(builder.ToString()); + Regex[] regexes = { + new Regex("autosave"), + new Regex("#checkpoint#", RegexOptions.IgnoreCase), + new Regex("#save#", RegexOptions.IgnoreCase), + new Regex("startneurotoxins 99999") + }; + string[] names = { // all appended by "detected on tick..." + "Autosave command", + "Checkpoint flag", + "Save flag", + "End of game" + }; + ConsoleColor[] colors = { + ConsoleColor.DarkYellow, + ConsoleColor.Magenta, + ConsoleColor.Yellow, + ConsoleColor.Green + }; + for (int i = 0; i < regexes.Length; i++) { + foreach (ConsoleCmd cmd in sd.PacketsWhereRegexMatches(regexes[i])) { + Console.ForegroundColor = colors[i]; + writer.WriteLine($"{names[i]} detected on tick {cmd.Tick}, time {cmd.Tick / sd.DemoSettings.TicksPerSeoncd:F3}"); + } } Console.ForegroundColor = ConsoleColor.Cyan; diff --git a/github-resources/example_usage.gif b/github-resources/example_usage.gif new file mode 100644 index 0000000..486550c Binary files /dev/null and b/github-resources/example_usage.gif differ