From 1c1e6680c4d782327cbbb2af15ff08c0734e2d7c Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Fri, 17 Mar 2023 09:36:18 -0400 Subject: [PATCH 01/89] Fixed some history issues in the new commands. --- SrcMod/Shell/Modules/BaseModule.cs | 50 ++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 51a191c..58b6b38 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -174,17 +174,23 @@ public static class BaseModule { action = delegate { - if (!File.Exists(absDest)) + if (File.Exists(absDest)) { - Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); - return; + FileInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The copied file has been modified and probably shouldn't be undone."); + + File.Delete(absDest); } + else if (Directory.Exists(absDest)) + { + DirectoryInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The copied directory has been modified and probably shouldn't be undone."); - FileInfo info = new(absDest); - if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) - throw new("The copied file or folder has been modified and probably shouldn't be undone."); - - File.Delete(absDest); + Directory.Delete(absDest, true); + } + else Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); }, name = $"Copied a file or folder from \"{absSource}\" to \"{absDest}\"" }); @@ -340,17 +346,29 @@ public static class BaseModule { action = delegate { - if (!File.Exists(absDest)) + if (File.Exists(absDest)) { - Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); - return; + FileInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The copied file has been modified and probably shouldn't be undone."); + + if (File.Exists(absSource)) throw new($"A file already exists at {absSource} and can't " + + "be overriden."); + + File.Move(absDest, absSource); } + else if (Directory.Exists(absDest)) + { + DirectoryInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The copied directory has been modified and probably shouldn't be undone."); - FileInfo info = new(absDest); - if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) - throw new("The moved file or folder has been modified and probably shouldn't be undone."); + if (Directory.Exists(absSource)) throw new($"A directory already exists at {absSource} and " + + "can't be overriden."); - File.Delete(absDest); + Directory.Move(absDest, absSource); + } + else Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); }, name = $"Moved a file or folder from \"{absSource}\" to \"{absDest}\"" }); @@ -360,7 +378,7 @@ public static class BaseModule public static void ReallyDelete(string path) { if (File.Exists(path)) File.Delete(path); - else if (Directory.Exists(path)) Directory.Delete(path); + else if (Directory.Exists(path)) Directory.Delete(path, true); else throw new($"No file or directory exists at \"{path}\""); } -- 2.49.0.windows.1 From 8d74174eb03087ebec877822dbb28beb757e56e5 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Fri, 17 Mar 2023 09:58:59 -0400 Subject: [PATCH 02/89] Moved the command to its own seperate module. --- SrcMod/Shell/Modules/BaseModule.cs | 96 ----------------------- SrcMod/Shell/Modules/CompressionModule.cs | 93 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 96 deletions(-) create mode 100644 SrcMod/Shell/Modules/CompressionModule.cs diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 58b6b38..41d45ec 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -19,102 +19,6 @@ public static class BaseModule Console.Write("\x1b[3J"); } - [Command("compress")] - public static void CompressFile(CompressedFileType type, string source, string? destination = null, - CompressionLevel level = CompressionLevel.Optimal) - { - destination ??= Path.Combine(Path.GetDirectoryName(source)!, - $"{Path.GetFileNameWithoutExtension(source)}.{type.ToString().ToLower()}"); - - string absSource = Path.GetFullPath(source), - absDest = Path.GetFullPath(destination); - - switch (type) - { - case CompressedFileType.Zip: - if (File.Exists(source)) - { - if (File.Exists(destination)) throw new($"File already exists at \"{destination}\""); - string message = $"Compressing file at \"{source}\" into \"{destination}\"..."; - Write(message); - - Stream writer = new FileStream(absDest, FileMode.CreateNew); - ZipArchive archive = new(writer, ZipArchiveMode.Create); - - archive.CreateEntryFromFile(absSource, Path.GetFileName(absSource), level); - - archive.Dispose(); - writer.Dispose(); - - Console.CursorLeft = 0; - Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; - Write(new string(' ', message.Length), newLine: false); - } - else if (Directory.Exists(source)) - { - if (File.Exists(destination)) throw new($"File already exists at \"{destination}\""); - - Write($"Compressing folder at \"{source}\" into \"{destination}\"..."); - - Stream writer = new FileStream(absDest, FileMode.CreateNew); - ZipArchive archive = new(writer, ZipArchiveMode.Create); - - List files = new(GetAllFiles(absSource)), - relative = new(); - foreach (string f in files) relative.Add(Path.GetRelativePath(absSource, f)); - - LoadingBarStart(); - for (int i = 0; i < files.Count; i++) - { - archive.CreateEntryFromFile(files[i], relative[i], level); - LoadingBarSet((i + 1) / (float)files.Count, ConsoleColor.DarkGreen); - Console.CursorLeft = 0; - string message = $"{relative[i]}"; - int remainder = Console.BufferWidth - message.Length; - if (remainder >= 0) message += new string(' ', remainder); - else message = $"...{message[(3 - remainder)..]}"; - - Write(message, newLine: false); - } - - archive.Dispose(); - writer.Dispose(); - - LoadingBarEnd(); - - Console.CursorLeft = 0; - Write(new string(' ', Console.BufferWidth), newLine: false); - Console.SetCursorPosition(0, Console.CursorTop - 2); - Write(new string(' ', Console.BufferWidth), newLine: false); - } - else throw new("No file or directory located at \"source\""); - break; - - default: throw new($"Unknown type: \"{type}\""); - } - - DateTime stamp = DateTime.Now; - - Program.Shell!.AddHistory(new() - { - action = delegate - { - if (!File.Exists(absDest)) - { - Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); - return; - } - - FileInfo info = new(absDest); - if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) - throw new("The archive has been modified and probably shouldn't be undone."); - - File.Delete(absDest); - }, - name = $"Compressed a file or folder into a {type} archive located at \"{destination}\"" - }); - } - [Command("copy")] public static void CopyFile(string source, string destination) { diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs new file mode 100644 index 0000000..ee03f0b --- /dev/null +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -0,0 +1,93 @@ +namespace SrcMod.Shell.Modules; + +[Module("compress")] +public static class CompressionModule +{ + public static void CompressZip(string source, string? destination = null, + CompressionLevel level = CompressionLevel.Optimal) + { + destination ??= Path.Combine(Path.GetDirectoryName(Path.GetFullPath(source))!, + $"{Path.GetFileNameWithoutExtension(source)}.zip"); + + string absSource = Path.GetFullPath(source), + localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination); + + if (File.Exists(source)) + { + if (File.Exists(destination)) throw new($"File already exists at \"{localDest}\""); + string message = $"Compressing file at \"{source}\" into \"{localDest}\"..."; + Write(message); + + Stream writer = new FileStream(destination, FileMode.CreateNew); + ZipArchive archive = new(writer, ZipArchiveMode.Create); + + archive.CreateEntryFromFile(absSource, Path.GetFileName(absSource), level); + + archive.Dispose(); + writer.Dispose(); + + Console.CursorLeft = 0; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; + Write(new string(' ', message.Length), newLine: false); + } + else if (Directory.Exists(source)) + { + if (File.Exists(destination)) throw new($"File already exists at \"{localDest}\""); + + Write($"Compressing folder at \"{source}\" into \"{localDest}\"..."); + + Stream writer = new FileStream(destination, FileMode.CreateNew); + ZipArchive archive = new(writer, ZipArchiveMode.Create); + + List files = new(GetAllFiles(absSource)), + relative = new(); + foreach (string f in files) relative.Add(Path.GetRelativePath(absSource, f)); + + LoadingBarStart(); + for (int i = 0; i < files.Count; i++) + { + archive.CreateEntryFromFile(files[i], relative[i], level); + LoadingBarSet((i + 1) / (float)files.Count, ConsoleColor.DarkGreen); + Console.CursorLeft = 0; + string message = $"{relative[i]}"; + int remainder = Console.BufferWidth - message.Length; + if (remainder >= 0) message += new string(' ', remainder); + else message = $"...{message[(3 - remainder)..]}"; + + Write(message, newLine: false); + } + + archive.Dispose(); + writer.Dispose(); + + LoadingBarEnd(); + + Console.CursorLeft = 0; + Write(new string(' ', Console.BufferWidth), newLine: false); + Console.SetCursorPosition(0, Console.CursorTop - 2); + Write(new string(' ', Console.BufferWidth), newLine: false); + } + else throw new("No file or directory located at \"source\""); + + DateTime stamp = DateTime.Now; + + Program.Shell!.AddHistory(new() + { + action = delegate + { + if (!File.Exists(absDest)) + { + Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); + return; + } + + FileInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The archive has been modified and probably shouldn't be undone."); + + File.Delete(absDest); + }, + name = $"Compressed a file or folder into a {type} archive located at \"{destination}\"" + }); + } +} -- 2.49.0.windows.1 From fab5f2c8164671aaaee37524acbb22e1a8b1a52a Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Fri, 17 Mar 2023 10:13:56 -0400 Subject: [PATCH 03/89] Crap. I forgot to test :( --- SrcMod/Shell/Modules/CompressionModule.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index ee03f0b..35742a9 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -3,6 +3,7 @@ [Module("compress")] public static class CompressionModule { + [Command("zip")] public static void CompressZip(string source, string? destination = null, CompressionLevel level = CompressionLevel.Optimal) { @@ -75,19 +76,19 @@ public static class CompressionModule { action = delegate { - if (!File.Exists(absDest)) + if (!File.Exists(destination)) { Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); return; } - FileInfo info = new(absDest); + FileInfo info = new(destination); if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) throw new("The archive has been modified and probably shouldn't be undone."); - File.Delete(absDest); + File.Delete(destination); }, - name = $"Compressed a file or folder into a {type} archive located at \"{destination}\"" + name = $"Compressed a file or folder into a zip archive located at \"{destination}\"" }); } } -- 2.49.0.windows.1 From ca71367f9ced5b95b6ef206d59323d60e398d7ba Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 28 Mar 2023 19:27:44 -0400 Subject: [PATCH 04/89] Added *some* clipboard commands. --- SrcMod/Shell/GlobalUsings.cs | 2 + SrcMod/Shell/Interop/Kernel32.cs | 11 +++ SrcMod/Shell/Interop/User32.cs | 29 ++++++ SrcMod/Shell/Modules/ClipboardModule.cs | 112 ++++++++++++++++++++++++ SrcMod/Shell/Shell.csproj | 1 + SrcMod/Shell/Tools.cs | 18 +++- 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 SrcMod/Shell/Interop/Kernel32.cs create mode 100644 SrcMod/Shell/Interop/User32.cs create mode 100644 SrcMod/Shell/Modules/ClipboardModule.cs diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index dc25d52..13ff962 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -8,5 +8,7 @@ global using System.IO; global using System.IO.Compression; global using System.Linq; global using System.Reflection; +global using System.Runtime.InteropServices; +global using System.Text; global using System.Threading; global using static SrcMod.Shell.Tools; diff --git a/SrcMod/Shell/Interop/Kernel32.cs b/SrcMod/Shell/Interop/Kernel32.cs new file mode 100644 index 0000000..751f71c --- /dev/null +++ b/SrcMod/Shell/Interop/Kernel32.cs @@ -0,0 +1,11 @@ +namespace SrcMod.Shell.Interop; + +internal static partial class Kernel32 +{ + [LibraryImport("kernel32.dll", SetLastError = true)] + public static partial uint GetFinalPathNameByHandleA(nint hFile, [MarshalAs(UnmanagedType.LPTStr)] string lpszFilePath, + uint cchFilePath, uint dwFlags); + + [LibraryImport("kernel32.dll")] + public static partial nuint GlobalSize(nint hPtr); +} diff --git a/SrcMod/Shell/Interop/User32.cs b/SrcMod/Shell/Interop/User32.cs new file mode 100644 index 0000000..b11f317 --- /dev/null +++ b/SrcMod/Shell/Interop/User32.cs @@ -0,0 +1,29 @@ +namespace SrcMod.Shell.Interop; + +internal static partial class User32 +{ + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool CloseClipboard(); + + [LibraryImport("user32.dll")] + public static partial uint EnumClipboardFormats(uint uFormat); + + [LibraryImport("user32.dll")] + public static partial nint GetClipboardData(uint uFormat); + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool IsClipboardFormatAvailable(uint uFormat); + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool OpenClipboard(nint hWndNewOwner); + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool EmptyClipboard(); + + [LibraryImport("user32.dll")] + public static partial nint SetClipboardData(uint uFormat, nint hMem); +} diff --git a/SrcMod/Shell/Modules/ClipboardModule.cs b/SrcMod/Shell/Modules/ClipboardModule.cs new file mode 100644 index 0000000..d69b42b --- /dev/null +++ b/SrcMod/Shell/Modules/ClipboardModule.cs @@ -0,0 +1,112 @@ +using SrcMod.Shell.Interop; + +namespace SrcMod.Shell.Modules; + +[Module("clipboard")] +public static class ClipboardModule +{ + [Command("clear")] + public static void ClearClipboard() + { + if (!ValidateUnsafe()) return; + + User32.OpenClipboard(0); + User32.EmptyClipboard(); + User32.CloseClipboard(); + } + + [Command("copy")] + public static void CopyClipboard(string text) + { + const uint format = 1; + + if (!ValidateUnsafe()) return; + + if (!text.EndsWith("\0")) text += "\0"; + byte[] data = Encoding.Default.GetBytes(text); + + nint hGlobal = Marshal.AllocHGlobal(data.Length + 1); + Marshal.Copy(data, 0, hGlobal, data.Length); + + User32.OpenClipboard(0); + User32.EmptyClipboard(); + + User32.SetClipboardData(format, hGlobal); + + User32.CloseClipboard(); + } + + [Command("view")] + public static void ViewClipboard() + { + // TODO (maybe): Make this support other formats? + // I spent way too long trying to make that a reality + // but the whole "clipboard format" thing is a nightmare. + + if (!ValidateUnsafe()) return; + + User32.OpenClipboard(0); + + nint hClipboard; + uint format; + if (User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.DspText) || + User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.OemText) || + User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.Text) || + User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.UnicodeText)) + hClipboard = User32.GetClipboardData(format); + else throw new("Clipboard doesn't contain text data."); + + nuint length = Kernel32.GlobalSize(hClipboard); + byte[] data = new byte[length]; + + Marshal.Copy(hClipboard, data, 0, (int)length); + + User32.CloseClipboard(); + + string msg = (ClipboardFormat)format switch + { + ClipboardFormat.DspText or ClipboardFormat.OemText or ClipboardFormat.Text => + Encoding.UTF8.GetString(data), + ClipboardFormat.UnicodeText => Encoding.Unicode.GetString(data), + _ => throw new("Unknown text format.") + }; + + Write(msg); + } + + public enum ClipboardFormat + { + Biff5 = 49988, + Biff8 = 49986, + Biff12 = 50009, + Bitmap = 2, + Csv = 49989, + DataObject = 49161, + Dib = 8, + Dif = 5, + DspText = 129, + EmbedSource = 49163, + EnhancedMetafile = 14, + HandleDrop = 15, + HtmlFormat = 49381, + Hyperlink = 50006, + Link = 49985, + LinkSource = 49165, + LinkSourceDescriptor = 49167, + Locale = 16, + Max = 17, + MetafilePicture = 3, + Native = 49156, + ObjectDescriptor = 49166, + ObjectLink = 49154, + OemText = 7, + OlePrivateData = 49171, + OwnerLink = 49155, + Palette = 9, + RichTextFormat = 49308, + SYLK = 4, + Text = 1, + UnicodeText = 13, + XmlSpreadSheet = 50007 + } +} diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index 0fdb552..511ed2f 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -12,6 +12,7 @@ That_One_Nerd false Logo.ico + true diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 8610be6..0bbeb15 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -1,4 +1,6 @@ -namespace SrcMod.Shell; +using System.Text; + +namespace SrcMod.Shell; public static class Tools { @@ -137,4 +139,18 @@ public static class Tools Console.ForegroundColor = prevCol; } + + public static bool ValidateUnsafe() + { + Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false); + + Console.ForegroundColor = ConsoleColor.Yellow; + Console.CursorVisible = true; + string result = Console.ReadLine()!.Trim().ToLower(); + Console.CursorVisible = false; + Console.ResetColor(); + + return result == "y" || result == "yes" || result == "t" || + result == "true" || result == "p" || result == "proceed"; + } } -- 2.49.0.windows.1 From a1d95170bd0107b8c91f20e0a64598c5ecfc915c Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 08:26:42 -0400 Subject: [PATCH 05/89] Added alias functionality to the shell. --- SrcMod/Shell/Modules/BaseModule.cs | 12 ++----- .../Modules/ObjectModels/CommandAttribute.cs | 2 +- .../Shell/Modules/ObjectModels/CommandInfo.cs | 35 ++++++++++++------- .../Shell/Modules/ObjectModels/ModuleInfo.cs | 8 ++--- SrcMod/Shell/Shell.cs | 4 +-- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 41d45ec..9e18192 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -100,9 +100,6 @@ public static class BaseModule }); } - [Command("cut")] - public static void CutFile(string source, string destination) => MoveFile(source, destination); - [Command("del")] public static void Delete(string path) { @@ -189,9 +186,6 @@ public static class BaseModule [Command("echo")] public static void Echo(string msg) => Write(msg); - [Command("exit")] - public static void ExitShell(int code = 0) => QuitShell(code); - [Command("explorer")] public static void OpenExplorer(string path = ".") => Process.Start("explorer.exe", Path.GetFullPath(path)); @@ -210,6 +204,7 @@ public static class BaseModule DisplayWithPages(lines); } + [Command("cut")] [Command("move")] public static void MoveFile(string source, string destination) { @@ -287,6 +282,7 @@ public static class BaseModule } [Command("print")] + [Command("type")] public static void Print(string file) { if (!File.Exists(file)) throw new($"No file exists at \"{file}\""); @@ -346,15 +342,13 @@ public static class BaseModule }); } + [Command("exit")] [Command("quit")] public static void QuitShell(int code = 0) { Environment.Exit(code); } - [Command("type")] - public static void Type(string file) => Print(file); - [Command("undo")] public static void UndoCommand(int amount = 1) { diff --git a/SrcMod/Shell/Modules/ObjectModels/CommandAttribute.cs b/SrcMod/Shell/Modules/ObjectModels/CommandAttribute.cs index 9d39d52..8ea8fff 100644 --- a/SrcMod/Shell/Modules/ObjectModels/CommandAttribute.cs +++ b/SrcMod/Shell/Modules/ObjectModels/CommandAttribute.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell.Modules.ObjectModels; -[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] public class CommandAttribute : Attribute { public readonly string NameId; diff --git a/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs b/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs index 7dee2d0..8505f35 100644 --- a/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs +++ b/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs @@ -17,26 +17,37 @@ public class CommandInfo RequiredParameters = 0; } - public static CommandInfo? FromMethod(ModuleInfo parentModule, MethodInfo info) + public static CommandInfo[] FromMethod(ModuleInfo parentModule, MethodInfo info) { - CommandAttribute? attribute = info.GetCustomAttribute(); - if (attribute is null) return null; + // This is a little redundant as we're duplicating a bunch of info, + // but honestly, it isn't too bad. Maybe there will be an improvement + // in the future, maybe not. But not for a while because this works. - if (info.ReturnType != typeof(void)) return null; + if (info.ReturnType != typeof(void)) return Array.Empty(); ParameterInfo[] param = info.GetParameters(); int required = 0; while (required < param.Length && !param[required].IsOptional) required++; - return new() + List commands = new(); + + CommandAttribute[] attributes = info.GetCustomAttributes().ToArray(); + if (attributes.Length <= 0) return Array.Empty(); + + foreach (CommandAttribute attribute in attributes) { - Method = info, - Module = parentModule, - Name = info.Name, - NameId = attribute.NameId, - Parameters = param, - RequiredParameters = required - }; + commands.Add(new() + { + Method = info, + Module = parentModule, + Name = info.Name, + NameId = attribute.NameId, + Parameters = param, + RequiredParameters = required + }); + } + + return commands.ToArray(); } public void Invoke(params string[] args) diff --git a/SrcMod/Shell/Modules/ObjectModels/ModuleInfo.cs b/SrcMod/Shell/Modules/ObjectModels/ModuleInfo.cs index 1200c83..ce9b58f 100644 --- a/SrcMod/Shell/Modules/ObjectModels/ModuleInfo.cs +++ b/SrcMod/Shell/Modules/ObjectModels/ModuleInfo.cs @@ -18,7 +18,7 @@ public class ModuleInfo NameIsPrefix = true; } - public static ModuleInfo? FromModule(Type info) + public static ModuleInfo? FromType(Type info) { ModuleAttribute? attribute = info.GetCustomAttribute(); if (attribute is null) return null; @@ -37,9 +37,9 @@ public class ModuleInfo List commands = new(); foreach (MethodInfo method in info.GetMethods()) { - CommandInfo? cmd = CommandInfo.FromMethod(module, method); - if (cmd is null) continue; - commands.Add(cmd); + CommandInfo[] cmds = CommandInfo.FromMethod(module, method); + if (cmds.Length <= 0) continue; + commands.AddRange(cmds); } module.Commands.AddRange(commands); diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 1d9464d..1a1479d 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.1.0"; + public const string Version = "Alpha 0.2.1"; public readonly string? ShellDirectory; @@ -62,7 +62,7 @@ public class Shell } foreach (Type t in possibleModules) { - ModuleInfo? module = ModuleInfo.FromModule(t); + ModuleInfo? module = ModuleInfo.FromType(t); if (module is not null) { LoadedModules.Add(module); -- 2.49.0.windows.1 From 8170a86247b72222003951175e06161dd74b9834 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 08:49:11 -0400 Subject: [PATCH 06/89] Fixed a loading bar issue (#19) --- SrcMod/Shell/Modules/BaseModule.cs | 15 +++++++++++++++ SrcMod/Shell/Shell.cs | 2 +- SrcMod/Shell/Tools.cs | 19 ++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 9e18192..2b6ad17 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -342,6 +342,21 @@ public static class BaseModule }); } + [Command("testing")] + public static void Testing() + { + LoadingBarStart(); + int count = 0; + for (float f = 0; f <= 1; f += 0.01f) + { + LoadingBarSet(f); + count++; + if (count % 10 == 0) Write("wowie!"); + Thread.Sleep(15); + } + LoadingBarEnd(); + } + [Command("exit")] [Command("quit")] public static void QuitShell(int code = 0) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 1a1479d..0ea44b3 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.2.1"; + public const string Version = "Alpha 0.2.2"; public readonly string? ShellDirectory; diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 0bbeb15..3fea015 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -7,6 +7,8 @@ public static class Tools private static int loadingPosition = -1; private static int lastLoadingBufferSize = 0; private static int lastLoadingValue = -1; + private static float loadingBarValue = 0; + private static ConsoleColor loadingBarColor = Console.ForegroundColor; public static bool LoadingBarEnabled { get; private set; } @@ -101,6 +103,9 @@ public static class Tools Int2 oldPos = (Console.CursorLeft, Console.CursorTop); + loadingBarValue = value; + loadingBarColor = color ?? Console.ForegroundColor; + // Erase last bar. Console.SetCursorPosition(0, loadingPosition); Console.Write(new string(' ', lastLoadingBufferSize)); @@ -119,14 +124,20 @@ public static class Tools Write(right, newLine: false); if (oldPos.y == Console.CursorTop) oldPos.y++; + while (oldPos.y >= Console.BufferHeight) + { + Console.WriteLine(); + oldPos.y--; + loadingPosition--; + } Console.SetCursorPosition(oldPos.x, oldPos.y); } public static void LoadingBarStart(float value = 0, int? position = null, ConsoleColor? color = null) { if (loadingPosition != -1) throw new("The loading bar has already been enabled."); loadingPosition = position ?? Console.CursorTop; - LoadingBarSet(value, color); LoadingBarEnabled = true; + LoadingBarSet(value, color); } public static void Write(object? message, ConsoleColor? col = null, bool newLine = true) @@ -138,6 +149,12 @@ public static class Tools else Console.Write(message); Console.ForegroundColor = prevCol; + + if (newLine && LoadingBarEnabled && Console.CursorTop >= Console.BufferHeight - 1) + { + loadingPosition--; + LoadingBarSet(loadingBarValue, loadingBarColor); + } } public static bool ValidateUnsafe() -- 2.49.0.windows.1 From 0ebecf42342074e6cecffe965c2de2e51b9411d4 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 09:08:32 -0400 Subject: [PATCH 07/89] Forgot to remove the testing command. --- SrcMod/Shell/Modules/BaseModule.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 2b6ad17..9e18192 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -342,21 +342,6 @@ public static class BaseModule }); } - [Command("testing")] - public static void Testing() - { - LoadingBarStart(); - int count = 0; - for (float f = 0; f <= 1; f += 0.01f) - { - LoadingBarSet(f); - count++; - if (count % 10 == 0) Write("wowie!"); - Thread.Sleep(15); - } - LoadingBarEnd(); - } - [Command("exit")] [Command("quit")] public static void QuitShell(int code = 0) -- 2.49.0.windows.1 From f95e3a89fff17cf506661b57af683ecd8a2e6ae2 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 10:19:34 -0400 Subject: [PATCH 08/89] Added a comment option for the command (#27) --- SrcMod/Shell/Modules/CompressionModule.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 35742a9..d009282 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -5,7 +5,7 @@ public static class CompressionModule { [Command("zip")] public static void CompressZip(string source, string? destination = null, - CompressionLevel level = CompressionLevel.Optimal) + CompressionLevel level = CompressionLevel.Optimal, string comment = "") { destination ??= Path.Combine(Path.GetDirectoryName(Path.GetFullPath(source))!, $"{Path.GetFileNameWithoutExtension(source)}.zip"); @@ -20,7 +20,10 @@ public static class CompressionModule Write(message); Stream writer = new FileStream(destination, FileMode.CreateNew); - ZipArchive archive = new(writer, ZipArchiveMode.Create); + ZipArchive archive = new(writer, ZipArchiveMode.Create) + { + Comment = comment + }; archive.CreateEntryFromFile(absSource, Path.GetFileName(absSource), level); -- 2.49.0.windows.1 From 506892b6e0e4248c7f3ec5aafdb5fa0b20997eb7 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 10:39:11 -0400 Subject: [PATCH 09/89] Added an extraction module, among one other thing. --- SrcMod/Shell/Modules/CompressionModule.cs | 7 +++--- SrcMod/Shell/Modules/ExtractionModule.cs | 26 +++++++++++++++++++++++ SrcMod/Shell/Shell.cs | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 SrcMod/Shell/Modules/ExtractionModule.cs diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index d009282..21aecfc 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -20,10 +20,8 @@ public static class CompressionModule Write(message); Stream writer = new FileStream(destination, FileMode.CreateNew); - ZipArchive archive = new(writer, ZipArchiveMode.Create) - { - Comment = comment - }; + ZipArchive archive = new(writer, ZipArchiveMode.Create); + if (!string.IsNullOrWhiteSpace(comment)) archive.Comment = comment; archive.CreateEntryFromFile(absSource, Path.GetFileName(absSource), level); @@ -42,6 +40,7 @@ public static class CompressionModule Stream writer = new FileStream(destination, FileMode.CreateNew); ZipArchive archive = new(writer, ZipArchiveMode.Create); + if (!string.IsNullOrWhiteSpace(comment)) archive.Comment = comment; List files = new(GetAllFiles(absSource)), relative = new(); diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs new file mode 100644 index 0000000..2eb82a2 --- /dev/null +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -0,0 +1,26 @@ +namespace SrcMod.Shell.Modules; + +[Module("extract")] +public static class ExtractionModule +{ + [Command("zip")] + public static void ExtractZip(string source, string? destination = null) + { + if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); + + destination ??= Path.GetDirectoryName(Path.GetFullPath(source)); + if (destination is null) throw new("Error detecting destination path."); + + if (!Directory.Exists(destination)) Directory.CreateDirectory(destination); + + FileStream reader = new(source, FileMode.Open); + ZipArchive zip = new(reader, ZipArchiveMode.Read); + + if (!string.IsNullOrWhiteSpace(zip.Comment)) Write(zip.Comment); + + zip.ExtractToDirectory(destination, true); + + zip.Dispose(); + reader.Dispose(); + } +} diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 0ea44b3..7275078 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.2.2"; + public const string Version = "Alpha 0.3.0"; public readonly string? ShellDirectory; -- 2.49.0.windows.1 From 9928f7d62f9ef7c2e04b8ee77e65cfd2be1baa3f Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 13:48:34 -0400 Subject: [PATCH 10/89] Fixed an issue with automatic destinations (#29) --- SrcMod/Shell/Modules/CompressionModule.cs | 44 ++++++++++++++++++++--- SrcMod/Shell/Modules/ExtractionModule.cs | 10 ++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 21aecfc..1fdf64f 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -7,8 +7,13 @@ public static class CompressionModule public static void CompressZip(string source, string? destination = null, CompressionLevel level = CompressionLevel.Optimal, string comment = "") { - destination ??= Path.Combine(Path.GetDirectoryName(Path.GetFullPath(source))!, - $"{Path.GetFileNameWithoutExtension(source)}.zip"); + if (destination is null) + { + string full = Path.GetFullPath(source); + string name = Path.GetFileNameWithoutExtension(full); + string folder = Program.Shell!.WorkingDirectory; + destination ??= $"{folder}\\{name}.zip"; + } string absSource = Path.GetFullPath(source), localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination); @@ -44,13 +49,34 @@ public static class CompressionModule List files = new(GetAllFiles(absSource)), relative = new(); - foreach (string f in files) relative.Add(Path.GetRelativePath(absSource, f)); + for (int i = 0; i < files.Count; i++) + { + string f = files[i]; + if (f.Trim().ToLower() == destination.Trim().ToLower()) + { + files.RemoveAt(i); + i--; + continue; + } + relative.Add(Path.GetRelativePath(absSource, f)); + } + + int failed = 0; LoadingBarStart(); for (int i = 0; i < files.Count; i++) { - archive.CreateEntryFromFile(files[i], relative[i], level); - LoadingBarSet((i + 1) / (float)files.Count, ConsoleColor.DarkGreen); + bool failedThisTime = false; + try + { + archive.CreateEntryFromFile(files[i], relative[i], level); + } + catch + { + failedThisTime = true; + failed++; + } + LoadingBarSet((i + 1) / (float)files.Count, failedThisTime ? ConsoleColor.Red : ConsoleColor.DarkGreen); ; Console.CursorLeft = 0; string message = $"{relative[i]}"; int remainder = Console.BufferWidth - message.Length; @@ -69,6 +95,14 @@ public static class CompressionModule Write(new string(' ', Console.BufferWidth), newLine: false); Console.SetCursorPosition(0, Console.CursorTop - 2); Write(new string(' ', Console.BufferWidth), newLine: false); + + if (failed > 0) + { + Console.CursorLeft = 0; + Console.CursorTop--; + Write($"{failed} file{(failed == 1 ? " has" : "s have")} been ignored due to an error.", + ConsoleColor.DarkYellow); + } } else throw new("No file or directory located at \"source\""); diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index 2eb82a2..d29774a 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -8,8 +8,14 @@ public static class ExtractionModule { if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); - destination ??= Path.GetDirectoryName(Path.GetFullPath(source)); - if (destination is null) throw new("Error detecting destination path."); + if (destination is null) + { + string full = Path.GetFullPath(source); + string folder = Program.Shell!.WorkingDirectory; + string name = Path.GetFileNameWithoutExtension(full); + + destination = $"{folder}\\{name}"; + } if (!Directory.Exists(destination)) Directory.CreateDirectory(destination); -- 2.49.0.windows.1 From 97385990882fbc64b0da6f9944eb63b0c427ce81 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 29 Mar 2023 17:40:26 -0400 Subject: [PATCH 11/89] Part of the GZip system. **INCOMPLETE** --- SrcMod/Shell/Modules/CompressionModule.cs | 57 ++++++++++++++++++++++- SrcMod/Shell/Shell.cs | 8 +++- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 1fdf64f..c2ceb71 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -3,6 +3,59 @@ [Module("compress")] public static class CompressionModule { + [Command("gz")] + [Command("gzip")] + public static void CompressGzip(string source, string? destination = null, + CompressionLevel level = CompressionLevel.Optimal) + { + if (destination is null) + { + string full = Path.GetFullPath(source); + string name = Path.GetFileNameWithoutExtension(full); + string folder = Program.Shell!.WorkingDirectory; + destination ??= $"{folder}\\{name}.gz"; + } + + string absSource = Path.GetFullPath(source), + localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination); + + if (File.Exists(source)) + { + if (File.Exists(destination)) throw new($"File already exists at \"{localDest}\""); + string message = $"Compressing file at \"{source}\" into \"{localDest}\"..."; + Write(message); + + FileStream writer = new(localDest, FileMode.CreateNew); + FileStream reader = new(absSource, FileMode.Open); + GZipStream gzip = new(writer, level); + + LoadingBarStart(); + + const int bufferSize = 1024; + byte[] buffer = new byte[bufferSize]; + for (int i = 0; i < reader.Length; i += bufferSize) + { + int size = reader.Read(buffer, 0, bufferSize); + gzip.Write(buffer, 0, size); + gzip.Flush(); + + LoadingBarSet((float)i / gzip.Length, ConsoleColor.Magenta); + } + + LoadingBarEnd(); + + gzip.Close(); + reader.Close(); + writer.Close(); + + Console.CursorLeft = 0; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; + Write(new string(' ', message.Length), newLine: false); + } + else if (Directory.Exists(source)) throw new("The GZip format can only compress 1 file."); + else throw new("No file located at \"source\""); + } + [Command("zip")] public static void CompressZip(string source, string? destination = null, CompressionLevel level = CompressionLevel.Optimal, string comment = "") @@ -24,7 +77,7 @@ public static class CompressionModule string message = $"Compressing file at \"{source}\" into \"{localDest}\"..."; Write(message); - Stream writer = new FileStream(destination, FileMode.CreateNew); + FileStream writer = new(destination, FileMode.CreateNew); ZipArchive archive = new(writer, ZipArchiveMode.Create); if (!string.IsNullOrWhiteSpace(comment)) archive.Comment = comment; @@ -43,7 +96,7 @@ public static class CompressionModule Write($"Compressing folder at \"{source}\" into \"{localDest}\"..."); - Stream writer = new FileStream(destination, FileMode.CreateNew); + FileStream writer = new(destination, FileMode.CreateNew); ZipArchive archive = new(writer, ZipArchiveMode.Create); if (!string.IsNullOrWhiteSpace(comment)) archive.Comment = comment; diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 7275078..3388eca 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.3.0"; + public const string Version = "Alpha 0.3"; public readonly string? ShellDirectory; @@ -170,10 +170,13 @@ public class Shell if (command.NameId.Trim().ToLower() != commandName) continue; int start = module.NameIsPrefix ? 2 : 1; string[] args = parts.GetRange(start, parts.Count - start).ToArray(); - + +#if RELEASE try { +#endif command.Invoke(args); +#if RELEASE } catch (TargetInvocationException ex) { @@ -185,6 +188,7 @@ public class Shell Write($"[ERROR] {ex.Message}", ConsoleColor.Red); if (LoadingBarEnabled) LoadingBarEnd(); } +#endif return; } } -- 2.49.0.windows.1 From 87166acda366348c5466843f3990cefcbb28ebeb Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Wed, 29 Mar 2023 19:02:55 -0400 Subject: [PATCH 12/89] Added GZip compatibility --- SrcMod/Shell/Modules/CompressionModule.cs | 27 ++++++------ SrcMod/Shell/Modules/ExtractionModule.cs | 51 +++++++++++++++++++++++ 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index c2ceb71..1b9581a 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -5,14 +5,14 @@ public static class CompressionModule { [Command("gz")] [Command("gzip")] - public static void CompressGzip(string source, string? destination = null, + public static void CompressGZip(string source, string? destination = null, CompressionLevel level = CompressionLevel.Optimal) { if (destination is null) { - string full = Path.GetFullPath(source); - string name = Path.GetFileNameWithoutExtension(full); - string folder = Program.Shell!.WorkingDirectory; + string full = Path.GetFullPath(source), + name = Path.GetFileName(full), + folder = Program.Shell!.WorkingDirectory; destination ??= $"{folder}\\{name}.gz"; } @@ -25,21 +25,21 @@ public static class CompressionModule string message = $"Compressing file at \"{source}\" into \"{localDest}\"..."; Write(message); - FileStream writer = new(localDest, FileMode.CreateNew); - FileStream reader = new(absSource, FileMode.Open); + FileStream writer = new(localDest, FileMode.CreateNew), + reader = new(absSource, FileMode.Open); GZipStream gzip = new(writer, level); LoadingBarStart(); - const int bufferSize = 1024; + int bufferSize = Mathf.Clamp((int)reader.Length / Console.BufferWidth, 1024 * 1024, 128 * 1024 * 1024); byte[] buffer = new byte[bufferSize]; - for (int i = 0; i < reader.Length; i += bufferSize) + for (long i = 0; i < reader.Length; i += bufferSize) { int size = reader.Read(buffer, 0, bufferSize); gzip.Write(buffer, 0, size); gzip.Flush(); - LoadingBarSet((float)i / gzip.Length, ConsoleColor.Magenta); + LoadingBarSet((float)i / reader.Length, ConsoleColor.DarkGreen); } LoadingBarEnd(); @@ -49,7 +49,7 @@ public static class CompressionModule writer.Close(); Console.CursorLeft = 0; - Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 2; Write(new string(' ', message.Length), newLine: false); } else if (Directory.Exists(source)) throw new("The GZip format can only compress 1 file."); @@ -62,9 +62,9 @@ public static class CompressionModule { if (destination is null) { - string full = Path.GetFullPath(source); - string name = Path.GetFileNameWithoutExtension(full); - string folder = Program.Shell!.WorkingDirectory; + string full = Path.GetFullPath(source), + name = Path.GetFileNameWithoutExtension(full), + folder = Program.Shell!.WorkingDirectory; destination ??= $"{folder}\\{name}.zip"; } @@ -152,7 +152,6 @@ public static class CompressionModule if (failed > 0) { Console.CursorLeft = 0; - Console.CursorTop--; Write($"{failed} file{(failed == 1 ? " has" : "s have")} been ignored due to an error.", ConsoleColor.DarkYellow); } diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index d29774a..ef342cc 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -3,6 +3,57 @@ [Module("extract")] public static class ExtractionModule { + [Command("gz")] + [Command("gzip")] + public static void ExtractGZip(string source, string? destination = null) + { + if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); + + if (destination is null) + { + string full = Path.GetFullPath(source); + string folder = Program.Shell!.WorkingDirectory; + string name = Path.GetFileNameWithoutExtension(full); + + destination = $"{folder}\\{name}"; + } + + string absSource = Path.GetFullPath(source), + localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination); + + if (File.Exists(destination)) throw new($"File already exists at \"{destination}\"."); + string message = $"Extracting file at \"{source}\" into \"{localDest}\"..."; + Write(message); + + FileStream writer = new(destination, FileMode.CreateNew), + reader = new(absSource, FileMode.Open); + GZipStream gzip = new(reader, CompressionMode.Decompress); + + LoadingBarStart(); + + int bufferSize = Mathf.Clamp((int)reader.Length / Console.BufferWidth, 1024 * 1024, 128 * 1024 * 1024); + byte[] buffer = new byte[bufferSize]; + int i = 0; + int size; + while ((size = gzip.Read(buffer, i, bufferSize)) > 0) + { + writer.Write(buffer, 0, size); + writer.Flush(); + + LoadingBarSet((float)i / reader.Length, ConsoleColor.DarkGreen); + } + + LoadingBarEnd(); + + gzip.Close(); + reader.Close(); + writer.Close(); + + Console.CursorLeft = 0; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 2; + Write(new string(' ', message.Length), newLine: false); + } + [Command("zip")] public static void ExtractZip(string source, string? destination = null) { -- 2.49.0.windows.1 From dda3ccad4d0a8f4bafc1dd5a67c06e3cd9690fa1 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Wed, 29 Mar 2023 20:27:10 -0400 Subject: [PATCH 13/89] Added tar functionality and only compression for tar-gz. Extraction coming soon. --- SrcMod/Shell/GlobalUsings.cs | 1 + SrcMod/Shell/Modules/CompressionModule.cs | 64 ++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index 13ff962..c3222e5 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -4,6 +4,7 @@ global using SrcMod.Shell.Modules.ObjectModels; global using System; global using System.Collections.Generic; global using System.Diagnostics; +global using System.Formats.Tar; global using System.IO; global using System.IO.Compression; global using System.Linq; diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 1b9581a..e1e87fa 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -1,4 +1,7 @@ -namespace SrcMod.Shell.Modules; +using System.Reflection.Emit; +using System.Xml.Linq; + +namespace SrcMod.Shell.Modules; [Module("compress")] public static class CompressionModule @@ -56,6 +59,65 @@ public static class CompressionModule else throw new("No file located at \"source\""); } + [Command("tar")] + [Command("tarball")] + public static void CompressTar(string source, string? destination = null) + { + if (destination is null) + { + string full = Path.GetFullPath(source), + name = Path.GetFileNameWithoutExtension(full), + folder = Program.Shell!.WorkingDirectory; + destination ??= $"{folder}\\{name}.tar"; + } + + string absSource = Path.GetFullPath(source), + localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination); + + if (File.Exists(source)) throw new("The Tar format cannot compress a single file."); + else if (Directory.Exists(source)) + { + if (File.Exists(destination)) throw new($"File already exists at \"{localDest}\""); + + Write($"Compressing folder at \"{source}\" into \"{localDest}\"..."); + + FileStream writer = new(destination, FileMode.CreateNew); + TarFile.CreateFromDirectory(absSource, writer, false); + + writer.Close(); + + Console.CursorLeft = 0; + Write(new string(' ', Console.BufferWidth), newLine: false); + Console.SetCursorPosition(0, Console.CursorTop - 1); + Write(new string(' ', Console.BufferWidth), newLine: false); + } + else throw new("No file or directory located at \"source\""); + } + + [Command("targz")] + [Command("tar.gz")] + [Command("tar-gz")] + public static void CompressTarGzip(string source, string? destination = null, + CompressionLevel level = CompressionLevel.Optimal) + { + if (destination is null) + { + string full = Path.GetFullPath(source), + name = Path.GetFileNameWithoutExtension(full), + folder = Program.Shell!.WorkingDirectory; + destination ??= $"{folder}\\{name}.tar.gz"; + } + + string firstDest = Path.GetFileNameWithoutExtension(destination); + + CompressTar(source, firstDest); + CompressGZip(firstDest, destination, level); + File.Delete(firstDest); + + Console.CursorLeft = 0; + Console.CursorTop--; + } + [Command("zip")] public static void CompressZip(string source, string? destination = null, CompressionLevel level = CompressionLevel.Optimal, string comment = "") -- 2.49.0.windows.1 From 8f7c2775d40338a200917def1dd5ae3834b35320 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 30 Mar 2023 09:06:09 -0400 Subject: [PATCH 14/89] Added support for extracting tar and tar.gz formats --- SrcMod/Shell/Modules/ExtractionModule.cs | 51 +++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index ef342cc..e06d826 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -50,10 +50,59 @@ public static class ExtractionModule writer.Close(); Console.CursorLeft = 0; - Console.CursorTop -= (message.Length / Console.BufferWidth) + 2; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; + if (Console.CursorTop >= Console.BufferHeight - 3) Console.CursorTop--; Write(new string(' ', message.Length), newLine: false); } + [Command("tar")] + [Command("tarball")] + public static void ExtractTar(string source, string? destination = null) + { + if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); + + if (destination is null) + { + string full = Path.GetFullPath(source); + string folder = Program.Shell!.WorkingDirectory; + string name = Path.GetFileNameWithoutExtension(full); + + destination = $"{folder}\\{name}"; + } + + if (!Directory.Exists(destination)) Directory.CreateDirectory(destination); + + FileStream reader = new(source, FileMode.Open); + TarFile.ExtractToDirectory(reader, Path.GetFileName(destination), true); + + reader.Dispose(); + } + + [Command("targz")] + [Command("tar.gz")] + [Command("tar-gz")] + public static void ExtractTarGz(string source, string? destination = null) + { + if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); + + if (destination is null) + { + string full = Path.GetFullPath(source); + string folder = Program.Shell!.WorkingDirectory; + string name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(full)); + + destination = $"{folder}\\{name}"; + } + + string absSource = Path.GetFullPath(source), + temp = Path.Combine(Path.GetDirectoryName(absSource)!, Path.GetFileNameWithoutExtension(absSource)); + + ExtractGZip(source, temp); + ExtractTar(temp, destination); + + File.Delete(temp); + } + [Command("zip")] public static void ExtractZip(string source, string? destination = null) { -- 2.49.0.windows.1 From 33130bc5f8710a9cb432722b95cbb676200cb8da Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 30 Mar 2023 10:28:56 -0400 Subject: [PATCH 15/89] Optimized some buffer copying in GZip stuff. --- SrcMod/Shell/Modules/CompressionModule.cs | 17 ++--------------- SrcMod/Shell/Modules/ExtractionModule.cs | 17 +---------------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index e1e87fa..043e653 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -32,27 +32,14 @@ public static class CompressionModule reader = new(absSource, FileMode.Open); GZipStream gzip = new(writer, level); - LoadingBarStart(); - - int bufferSize = Mathf.Clamp((int)reader.Length / Console.BufferWidth, 1024 * 1024, 128 * 1024 * 1024); - byte[] buffer = new byte[bufferSize]; - for (long i = 0; i < reader.Length; i += bufferSize) - { - int size = reader.Read(buffer, 0, bufferSize); - gzip.Write(buffer, 0, size); - gzip.Flush(); - - LoadingBarSet((float)i / reader.Length, ConsoleColor.DarkGreen); - } - - LoadingBarEnd(); + reader.CopyTo(gzip); gzip.Close(); reader.Close(); writer.Close(); Console.CursorLeft = 0; - Console.CursorTop -= (message.Length / Console.BufferWidth) + 2; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; Write(new string(' ', message.Length), newLine: false); } else if (Directory.Exists(source)) throw new("The GZip format can only compress 1 file."); diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index e06d826..a7d8bc7 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -29,21 +29,7 @@ public static class ExtractionModule reader = new(absSource, FileMode.Open); GZipStream gzip = new(reader, CompressionMode.Decompress); - LoadingBarStart(); - - int bufferSize = Mathf.Clamp((int)reader.Length / Console.BufferWidth, 1024 * 1024, 128 * 1024 * 1024); - byte[] buffer = new byte[bufferSize]; - int i = 0; - int size; - while ((size = gzip.Read(buffer, i, bufferSize)) > 0) - { - writer.Write(buffer, 0, size); - writer.Flush(); - - LoadingBarSet((float)i / reader.Length, ConsoleColor.DarkGreen); - } - - LoadingBarEnd(); + gzip.CopyTo(writer); gzip.Close(); reader.Close(); @@ -51,7 +37,6 @@ public static class ExtractionModule Console.CursorLeft = 0; Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; - if (Console.CursorTop >= Console.BufferHeight - 3) Console.CursorTop--; Write(new string(' ', message.Length), newLine: false); } -- 2.49.0.windows.1 From 471bb54fe0035dd948c9004f0c3cdd1e401a11ea Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 30 Mar 2023 14:09:25 -0400 Subject: [PATCH 16/89] Maybe 7Zip extraction? I haven't tested it. --- SrcMod/Shell/GlobalUsings.cs | 2 ++ SrcMod/Shell/Modules/CompressionModule.cs | 11 +++++---- SrcMod/Shell/Modules/ExtractionModule.cs | 28 +++++++++++++++++++++++ SrcMod/Shell/Shell.cs | 2 +- SrcMod/Shell/Shell.csproj | 1 + 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index c3222e5..56f20a3 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -1,4 +1,6 @@ global using Nerd_STF.Mathematics; +global using SharpCompress.Archives.SevenZip; +global using SharpCompress.Readers; global using SrcMod.Shell; global using SrcMod.Shell.Modules.ObjectModels; global using System; diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 043e653..7415870 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -1,8 +1,9 @@ -using System.Reflection.Emit; -using System.Xml.Linq; - -namespace SrcMod.Shell.Modules; +namespace SrcMod.Shell.Modules; +// Some things that can be extracted can't be compressed by SharpCompress. +// In the future I might replace it with my own, but that'll take a *really* +// long time and I'm already planning to do that for the valve compression formats, +// so I'll seethe for now. [Module("compress")] public static class CompressionModule { @@ -228,4 +229,6 @@ public static class CompressionModule name = $"Compressed a file or folder into a zip archive located at \"{destination}\"" }); } + + // 7z can't be compressed. } diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index a7d8bc7..1a6285b 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -114,4 +114,32 @@ public static class ExtractionModule zip.Dispose(); reader.Dispose(); } + + [Command("7z")] + [Command("7zip")] + [Command("sevenzip")] + public static void Extract7Zip(string source, string? destination = null) + { + if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); + + if (destination is null) + { + string full = Path.GetFullPath(source); + string folder = Program.Shell!.WorkingDirectory; + string name = Path.GetFileNameWithoutExtension(full); + + destination = $"{folder}\\{name}"; + } + + if (!Directory.Exists(destination)) Directory.CreateDirectory(destination); + + FileStream reader = new(source, FileMode.Open); + SevenZipArchive zip = SevenZipArchive.Open(source); + + IReader data = zip.ExtractAllEntries(); + data.WriteAllToDirectory(destination); + + zip.Dispose(); + reader.Dispose(); + } } diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 3388eca..e62b406 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.3"; + public const string Version = "Alpha 0.3.0"; public readonly string? ShellDirectory; diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index 511ed2f..d662f45 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -31,6 +31,7 @@ + -- 2.49.0.windows.1 From ce72491109d1867c1fdc28a888881c3f25ce07cf Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 30 Mar 2023 19:13:43 -0400 Subject: [PATCH 17/89] Added 7z extraction. I can't do compression ATM. --- SrcMod/Shell/Modules/ExtractionModule.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index 1a6285b..12e37f5 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -134,10 +134,16 @@ public static class ExtractionModule if (!Directory.Exists(destination)) Directory.CreateDirectory(destination); FileStream reader = new(source, FileMode.Open); - SevenZipArchive zip = SevenZipArchive.Open(source); + SevenZipArchive zip = SevenZipArchive.Open(reader); IReader data = zip.ExtractAllEntries(); - data.WriteAllToDirectory(destination); + data.WriteAllToDirectory(destination, new() + { + ExtractFullPath = true, + Overwrite = true, + PreserveAttributes = true, + PreserveFileTime = true + }); zip.Dispose(); reader.Dispose(); -- 2.49.0.windows.1 From 559190158a9e7ac37d102b81ab9947972149dd43 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 30 Mar 2023 19:31:14 -0400 Subject: [PATCH 18/89] Added rar extraction (can't do compression). --- SrcMod/Shell/GlobalUsings.cs | 1 + SrcMod/Shell/Modules/CompressionModule.cs | 2 ++ SrcMod/Shell/Modules/ExtractionModule.cs | 31 +++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index 56f20a3..1d90052 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -1,4 +1,5 @@ global using Nerd_STF.Mathematics; +global using SharpCompress.Archives.Rar; global using SharpCompress.Archives.SevenZip; global using SharpCompress.Readers; global using SrcMod.Shell; diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 7415870..43d5804 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -82,6 +82,8 @@ public static class CompressionModule else throw new("No file or directory located at \"source\""); } + // Rar can't be compressed. + [Command("targz")] [Command("tar.gz")] [Command("tar-gz")] diff --git a/SrcMod/Shell/Modules/ExtractionModule.cs b/SrcMod/Shell/Modules/ExtractionModule.cs index 12e37f5..75e0d6c 100644 --- a/SrcMod/Shell/Modules/ExtractionModule.cs +++ b/SrcMod/Shell/Modules/ExtractionModule.cs @@ -40,6 +40,37 @@ public static class ExtractionModule Write(new string(' ', message.Length), newLine: false); } + [Command("rar")] + public static void ExtractRar(string source, string? destination = null) + { + if (!File.Exists(source)) throw new($"No file exists at \"{source}\"."); + + if (destination is null) + { + string full = Path.GetFullPath(source); + string folder = Program.Shell!.WorkingDirectory; + string name = Path.GetFileNameWithoutExtension(full); + + destination = $"{folder}\\{name}"; + } + + if (!Directory.Exists(destination)) Directory.CreateDirectory(destination); + + FileStream reader = new(source, FileMode.Open); + RarArchive rar = RarArchive.Open(reader); + + IReader data = rar.ExtractAllEntries(); + data.WriteAllToDirectory(destination, new() + { + ExtractFullPath = true, + Overwrite = true, + PreserveFileTime = true + }); + + rar.Dispose(); + reader.Dispose(); + } + [Command("tar")] [Command("tarball")] public static void ExtractTar(string source, string? destination = null) -- 2.49.0.windows.1 From 5412b023a0374d58093a3b57b288c911a576e956 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Fri, 31 Mar 2023 18:12:20 -0400 Subject: [PATCH 19/89] Added some terminal interrupt systems. Later it will kill active commands. --- SrcMod/Shell/GlobalUsings.cs | 1 + SrcMod/Shell/Interop/Winmm.cs | 25 ++++++++++ SrcMod/Shell/Modules/ClipboardModule.cs | 4 +- SrcMod/Shell/Shell.cs | 66 +++++++++++++++++++++++-- 4 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 SrcMod/Shell/Interop/Winmm.cs diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index 1d90052..a26ef43 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -3,6 +3,7 @@ global using SharpCompress.Archives.Rar; global using SharpCompress.Archives.SevenZip; global using SharpCompress.Readers; global using SrcMod.Shell; +global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; global using System; global using System.Collections.Generic; diff --git a/SrcMod/Shell/Interop/Winmm.cs b/SrcMod/Shell/Interop/Winmm.cs new file mode 100644 index 0000000..58a6d67 --- /dev/null +++ b/SrcMod/Shell/Interop/Winmm.cs @@ -0,0 +1,25 @@ +namespace SrcMod.Shell.Interop; + +internal static partial class Winmm +{ + [LibraryImport("winmm.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool PlaySound([MarshalAs(UnmanagedType.LPStr)] string pszSound, nint hMod, uint fdwSound); + + public enum PlaySoundFlags : uint + { + SND_SYNC = 0x00000000, + SND_ASYNC = 0x00000001, + SND_NODEFAULT = 0x00000002, + SND_MEMORY = 0x00000004, + SND_LOOP = 0x00000008, + SND_NOSTOP = 0x00000010, + SND_PURGE = 0x00000040, + SND_APPLICATION = 0x00000080, + SND_NOWAIT = 0x00002000, + SND_ALIAS = 0x00010000, + SND_FILENAME = 0x00020000, + SND_RESOURCE = 0x00040000, + SND_ALIAS_ID = 0x00100000, + } +} diff --git a/SrcMod/Shell/Modules/ClipboardModule.cs b/SrcMod/Shell/Modules/ClipboardModule.cs index d69b42b..14a01c2 100644 --- a/SrcMod/Shell/Modules/ClipboardModule.cs +++ b/SrcMod/Shell/Modules/ClipboardModule.cs @@ -1,6 +1,4 @@ -using SrcMod.Shell.Interop; - -namespace SrcMod.Shell.Modules; +namespace SrcMod.Shell.Modules; [Module("clipboard")] public static class ClipboardModule diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index e62b406..02c25e1 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -16,6 +16,9 @@ public class Shell public List History; public string WorkingDirectory; + private bool lastCancel; + private bool printedCancel; + public Shell() { Console.CursorVisible = false; @@ -79,6 +82,9 @@ public class Shell Write(" by ", ConsoleColor.White, false); Write($"{Author}", ConsoleColor.DarkYellow); + lastCancel = false; + Console.CancelKeyPress += HandleCancel; + ActiveGame = null; ReloadDirectoryInfo(); @@ -106,8 +112,6 @@ public class Shell public string ReadLine() { - Console.CursorVisible = true; - Write($"\n{WorkingDirectory}", ConsoleColor.DarkGreen, false); if (ActiveGame is not null) Write($" {ActiveGame}", ConsoleColor.DarkYellow, false); if (ActiveMod is not null) Write($" {ActiveMod}", ConsoleColor.Magenta, false); @@ -116,17 +120,55 @@ public class Shell Write($" {Name}", ConsoleColor.DarkCyan, false); Write(" > ", ConsoleColor.White, false); + bool printed = false; + + if (lastCancel && !printedCancel) + { + // Print the warning. A little bit of mess because execution must + // continue without funny printing errors but it's alright I guess. + + int originalLeft = Console.CursorLeft; + + Console.CursorTop -= 3; + Write("Press ^C again to exit the shell.", ConsoleColor.Red); + // Send a warning sound. + + Winmm.PlaySound("SystemAsterisk", nint.Zero, + (uint)(Winmm.PlaySoundFlags.SND_ALIAS | Winmm.PlaySoundFlags.SND_ASYNC)); + + printedCancel = true; + Console.CursorTop += 2; + + Console.CursorLeft = originalLeft; + printed = true; + } + Console.ForegroundColor = ConsoleColor.White; + Console.CursorVisible = true; string message = Console.ReadLine()!; + Console.CursorVisible = false; Console.ResetColor(); - Console.CursorVisible = false; + if (!printed) + { + lastCancel = false; + printedCancel = false; + } return message; } public void InvokeCommand(string cmd) { + if (cmd is null) + { + // This usually won't happen, but might if for example + // the shell cancel interrupt is called. This probably + // happens for other shell interrupts are called. + Write(null); + return; + } + List parts = new(); string active = string.Empty; @@ -205,4 +247,22 @@ public class Shell if (ActiveMod is not null) title += $" - {ActiveMod.Name}"; Console.Title = title; } + + private void HandleCancel(object? sender, ConsoleCancelEventArgs args) + { + // Due to some funny multithreading issues, we want to make the warning label + // single-threaded on the shell. + if (!lastCancel) + { + // Enable the warning. The "ReadLine" method will do the rest. + lastCancel = true; + args.Cancel = true; // "Cancel" referring to the cancellation of the cancel operation. + return; + } + + // Actually kill the shell. We do still have to worry about some multithreaded + // nonsense, but a bearable amount of it. + Console.ResetColor(); + Environment.Exit(0); + } } -- 2.49.0.windows.1 From 1e5f0dba4ea3481cb4d146cec4530704aa2a9d75 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sat, 1 Apr 2023 08:27:30 -0400 Subject: [PATCH 20/89] Added method interrupt handling. --- SrcMod/Shell/Interop/Winmm.cs | 26 +++++----- SrcMod/Shell/Shell.cs | 92 +++++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 33 deletions(-) diff --git a/SrcMod/Shell/Interop/Winmm.cs b/SrcMod/Shell/Interop/Winmm.cs index 58a6d67..ac1e97a 100644 --- a/SrcMod/Shell/Interop/Winmm.cs +++ b/SrcMod/Shell/Interop/Winmm.cs @@ -8,18 +8,18 @@ internal static partial class Winmm public enum PlaySoundFlags : uint { - SND_SYNC = 0x00000000, - SND_ASYNC = 0x00000001, - SND_NODEFAULT = 0x00000002, - SND_MEMORY = 0x00000004, - SND_LOOP = 0x00000008, - SND_NOSTOP = 0x00000010, - SND_PURGE = 0x00000040, - SND_APPLICATION = 0x00000080, - SND_NOWAIT = 0x00002000, - SND_ALIAS = 0x00010000, - SND_FILENAME = 0x00020000, - SND_RESOURCE = 0x00040000, - SND_ALIAS_ID = 0x00100000, + Sync = 0x00000000, + Async = 0x00000001, + NoDefault = 0x00000002, + Memory = 0x00000004, + Loop = 0x00000008, + NoStop = 0x00000010, + Purge = 0x00000040, + Application = 0x00000080, + NoWait = 0x00002000, + Alias = 0x00010000, + FileName = 0x00020000, + Resource = 0x00040000, + AliasId = 0x00100000, } } diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 02c25e1..4cb5190 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -1,10 +1,12 @@ -namespace SrcMod.Shell; +using System.ComponentModel; + +namespace SrcMod.Shell; public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.3.0"; + public const string Version = "Alpha 0.3.1"; public readonly string? ShellDirectory; @@ -19,6 +21,8 @@ public class Shell private bool lastCancel; private bool printedCancel; + private BackgroundWorker? activeCommand; + public Shell() { Console.CursorVisible = false; @@ -83,6 +87,7 @@ public class Shell Write($"{Author}", ConsoleColor.DarkYellow); lastCancel = false; + activeCommand = null; Console.CancelKeyPress += HandleCancel; ActiveGame = null; @@ -131,10 +136,7 @@ public class Shell Console.CursorTop -= 3; Write("Press ^C again to exit the shell.", ConsoleColor.Red); - // Send a warning sound. - - Winmm.PlaySound("SystemAsterisk", nint.Zero, - (uint)(Winmm.PlaySoundFlags.SND_ALIAS | Winmm.PlaySoundFlags.SND_ASYNC)); + PlayWarningSound(); printedCancel = true; Console.CursorTop += 2; @@ -213,24 +215,41 @@ public class Shell int start = module.NameIsPrefix ? 2 : 1; string[] args = parts.GetRange(start, parts.Count - start).ToArray(); + void runCommand(object? sender, DoWorkEventArgs e) + { #if RELEASE - try - { + try + { #endif - command.Invoke(args); + command.Invoke(args); #if RELEASE - } - catch (TargetInvocationException ex) - { - Write($"[ERROR] {ex.InnerException!.Message}", ConsoleColor.Red); - if (LoadingBarEnabled) LoadingBarEnd(); - } - catch (Exception ex) - { - Write($"[ERROR] {ex.Message}", ConsoleColor.Red); - if (LoadingBarEnabled) LoadingBarEnd(); - } + } + catch (TargetInvocationException ex) + { + Write($"[ERROR] {ex.InnerException!.Message}", ConsoleColor.Red); + if (LoadingBarEnabled) LoadingBarEnd(); + } + catch (Exception ex) + { + Write($"[ERROR] {ex.Message}", ConsoleColor.Red); + if (LoadingBarEnabled) LoadingBarEnd(); + } #endif + } + + activeCommand = new(); + activeCommand.DoWork += runCommand; + activeCommand.RunWorkerAsync(); + + activeCommand.WorkerSupportsCancellation = true; + + while (activeCommand is not null && activeCommand.IsBusy) Thread.Yield(); + + if (activeCommand is not null) + { + activeCommand.Dispose(); + activeCommand = null; + } return; } } @@ -238,6 +257,17 @@ public class Shell Write($"[ERROR] Could not find command \"{cmd}\".", ConsoleColor.Red); } + private static void PlayErrorSound() + { + Winmm.PlaySound("SystemHand", nint.Zero, + (uint)(Winmm.PlaySoundFlags.Alias | Winmm.PlaySoundFlags.Async)); + } + private static void PlayWarningSound() + { + Winmm.PlaySound("SystemAsterisk", nint.Zero, + (uint)(Winmm.PlaySoundFlags.Alias | Winmm.PlaySoundFlags.Async)); + } + public void ReloadDirectoryInfo() { ActiveMod = Mod.ReadDirectory(WorkingDirectory); @@ -250,6 +280,28 @@ public class Shell private void HandleCancel(object? sender, ConsoleCancelEventArgs args) { + if (activeCommand is not null && activeCommand.IsBusy) + { + if (activeCommand.WorkerSupportsCancellation) + { + // Kill the active command. + activeCommand.CancelAsync(); + activeCommand.Dispose(); + activeCommand = null; + } + else + { + // Command doesn't support cancellation. + // Warn the user. + PlayErrorSound(); + } + + lastCancel = false; + printedCancel = false; + args.Cancel = true; + return; + } + // Due to some funny multithreading issues, we want to make the warning label // single-threaded on the shell. if (!lastCancel) -- 2.49.0.windows.1 From a7ff0a7ab40d94176447f50c2ef6c81e1377fe96 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sat, 1 Apr 2023 08:50:08 -0400 Subject: [PATCH 21/89] Added the ability to prevent cancellation. --- .../Shell/Modules/ObjectModels/CanCancelAttribute.cs | 12 ++++++++++++ SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs | 5 +++++ SrcMod/Shell/Shell.cs | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 SrcMod/Shell/Modules/ObjectModels/CanCancelAttribute.cs diff --git a/SrcMod/Shell/Modules/ObjectModels/CanCancelAttribute.cs b/SrcMod/Shell/Modules/ObjectModels/CanCancelAttribute.cs new file mode 100644 index 0000000..30f2451 --- /dev/null +++ b/SrcMod/Shell/Modules/ObjectModels/CanCancelAttribute.cs @@ -0,0 +1,12 @@ +namespace SrcMod.Shell.Modules.ObjectModels; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] +public class CanCancelAttribute : Attribute +{ + public readonly bool CanCancel; + + public CanCancelAttribute(bool canCancel) + { + CanCancel = canCancel; + } +} diff --git a/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs b/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs index 8505f35..0e71e6f 100644 --- a/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs +++ b/SrcMod/Shell/Modules/ObjectModels/CommandInfo.cs @@ -2,6 +2,7 @@ public class CommandInfo { + public bool CanBeCancelled { get; private set; } public required ModuleInfo Module { get; init; } public required MethodInfo Method { get; init; } public string Name { get; private set; } @@ -11,6 +12,7 @@ public class CommandInfo private CommandInfo() { + CanBeCancelled = false; Name = string.Empty; NameId = string.Empty; Parameters = Array.Empty(); @@ -34,10 +36,13 @@ public class CommandInfo CommandAttribute[] attributes = info.GetCustomAttributes().ToArray(); if (attributes.Length <= 0) return Array.Empty(); + CanCancelAttribute? cancel = info.GetCustomAttribute(); + foreach (CommandAttribute attribute in attributes) { commands.Add(new() { + CanBeCancelled = cancel is null || cancel.CanCancel, Method = info, Module = parentModule, Name = info.Name, diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 4cb5190..a2b7cda 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -241,7 +241,7 @@ public class Shell activeCommand.DoWork += runCommand; activeCommand.RunWorkerAsync(); - activeCommand.WorkerSupportsCancellation = true; + activeCommand.WorkerSupportsCancellation = command.CanBeCancelled; while (activeCommand is not null && activeCommand.IsBusy) Thread.Yield(); -- 2.49.0.windows.1 From 4c919a152c1b9af78ac0cd676f3f45b8e44ba607 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sat, 1 Apr 2023 15:05:58 -0400 Subject: [PATCH 22/89] Fixed issue #28. Literally a one-liner. --- SrcMod/Shell/Modules/BaseModule.cs | 2 +- SrcMod/Shell/Shell.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 9e18192..653dfbb 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -194,7 +194,7 @@ public static class BaseModule { List lines = new() { " Timestamp Description"}; int longestName = 0; - for (int i = lines.Count - 1; i >= 0; i--) + for (int i = Program.Shell!.History.Count - 1; i >= 0; i--) { HistoryItem hist = Program.Shell!.History[i]; if (hist.name.Length > longestName) longestName = hist.name.Length; diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index a2b7cda..3a90b88 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -6,7 +6,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.3.1"; + public const string Version = "Alpha 0.3.2"; public readonly string? ShellDirectory; -- 2.49.0.windows.1 From e8a5cbc846e6a04e43602913946074c174ba8a76 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sat, 1 Apr 2023 15:22:38 -0400 Subject: [PATCH 23/89] Oh look, another one liner. Fixed #34 --- SrcMod/Shell/Modules/BaseModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 653dfbb..374f672 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -159,7 +159,7 @@ public static class BaseModule FileInfo info = new(f); if (f.Length > longestName) longestName = f.Trim().Length; - int size = Mathf.Ceiling(MathF.Log10(info.Length)); + int size = Mathf.Ceiling(info.Length.ToString().Length); if (longestSize > size) longestSize = size; } -- 2.49.0.windows.1 From daae786beca340eb68ae10eb90dc0d5be22840f9 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sat, 1 Apr 2023 20:16:37 -0400 Subject: [PATCH 24/89] Added commands to make new directories and new files. --- SrcMod/Shell/Modules/BaseModule.cs | 154 +++++++++++++++++------------ 1 file changed, 91 insertions(+), 63 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 374f672..de258b6 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -100,6 +100,75 @@ public static class BaseModule }); } + [Command("cut")] + [Command("move")] + public static void MoveFile(string source, string destination) + { + string absSource = Path.GetFullPath(source), + absDest = Path.GetFullPath(destination); + + if (File.Exists(source)) + { + if (File.Exists(destination)) throw new($"File already exists at \"{destination}\""); + + string message = $"Moving file \"{source}\" to \"{destination}\"..."; + Write(message); + + File.Move(source, destination); + + Console.CursorLeft = 0; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; + Write(new string(' ', message.Length), newLine: false); + } + else if (Directory.Exists(source)) + { + if (Directory.Exists(destination)) throw new($"Directory already exists at \"{destination}\""); + + string message = $"Moving directory \"{source}\" to \"{destination}\"..."; + Write(message); + + Directory.Move(source, destination); + + Console.CursorLeft = 0; + Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; + Write(new string(' ', message.Length), newLine: false); + } + else throw new($"No file or directory found at \"{source}\""); + + DateTime stamp = DateTime.Now; + + Program.Shell!.AddHistory(new() + { + action = delegate + { + if (File.Exists(absDest)) + { + FileInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The copied file has been modified and probably shouldn't be undone."); + + if (File.Exists(absSource)) throw new($"A file already exists at {absSource} and can't " + + "be overriden."); + + File.Move(absDest, absSource); + } + else if (Directory.Exists(absDest)) + { + DirectoryInfo info = new(absDest); + if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) + throw new("The copied directory has been modified and probably shouldn't be undone."); + + if (Directory.Exists(absSource)) throw new($"A directory already exists at {absSource} and " + + "can't be overriden."); + + Directory.Move(absDest, absSource); + } + else Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); + }, + name = $"Moved a file or folder from \"{absSource}\" to \"{absDest}\"" + }); + } + [Command("del")] public static void Delete(string path) { @@ -204,73 +273,32 @@ public static class BaseModule DisplayWithPages(lines); } - [Command("cut")] - [Command("move")] - public static void MoveFile(string source, string destination) + [Command("makedir")] + [Command("mkdir")] + public static void CreateDirectory(string name) { - string absSource = Path.GetFullPath(source), - absDest = Path.GetFullPath(destination); + if (Directory.Exists(name)) throw new($"Directory already exists at \"{name}\""); + Directory.CreateDirectory(name); + } - if (File.Exists(source)) + [Command("makefile")] + [Command("mkfile")] + public static void CreateFile(string name, string? text = null) + { + string? dir = Path.GetDirectoryName(name); + if (dir is null) throw new($"Cannot parse file path \"{name}\""); + + if (File.Exists(name)) throw new($"File already exists at \"{name}\""); + if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); + + FileStream stream = File.Create(name); + if (text is not null) { - if (File.Exists(destination)) throw new($"File already exists at \"{destination}\""); - - string message = $"Moving file \"{source}\" to \"{destination}\"..."; - Write(message); - - File.Move(source, destination); - - Console.CursorLeft = 0; - Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; - Write(new string(' ', message.Length), newLine: false); + StreamWriter writer = new(stream); + writer.Write(text); + writer.Close(); } - else if (Directory.Exists(source)) - { - if (Directory.Exists(destination)) throw new($"Directory already exists at \"{destination}\""); - - string message = $"Moving directory \"{source}\" to \"{destination}\"..."; - Write(message); - - Directory.Move(source, destination); - - Console.CursorLeft = 0; - Console.CursorTop -= (message.Length / Console.BufferWidth) + 1; - Write(new string(' ', message.Length), newLine: false); - } - else throw new($"No file or directory found at \"{source}\""); - - DateTime stamp = DateTime.Now; - - Program.Shell!.AddHistory(new() - { - action = delegate - { - if (File.Exists(absDest)) - { - FileInfo info = new(absDest); - if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) - throw new("The copied file has been modified and probably shouldn't be undone."); - - if (File.Exists(absSource)) throw new($"A file already exists at {absSource} and can't " + - "be overriden."); - - File.Move(absDest, absSource); - } - else if (Directory.Exists(absDest)) - { - DirectoryInfo info = new(absDest); - if ((info.LastWriteTime - stamp).TotalMilliseconds >= 10) - throw new("The copied directory has been modified and probably shouldn't be undone."); - - if (Directory.Exists(absSource)) throw new($"A directory already exists at {absSource} and " + - "can't be overriden."); - - Directory.Move(absDest, absSource); - } - else Write("Looks like the job is already completed Boss.", ConsoleColor.DarkYellow); - }, - name = $"Moved a file or folder from \"{absSource}\" to \"{absDest}\"" - }); + stream.Close(); } [Command("permdel")] -- 2.49.0.windows.1 From a2b9daa10753666cbc3d7971bbb17b5c80c85e45 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sat, 1 Apr 2023 20:35:30 -0400 Subject: [PATCH 25/89] Made a command that can be used to run other processes. --- SrcMod/Shell/Modules/BaseModule.cs | 31 +++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index de258b6..0436cb5 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -255,6 +255,13 @@ public static class BaseModule [Command("echo")] public static void Echo(string msg) => Write(msg); + [Command("exit")] + [Command("quit")] + public static void QuitShell(int code = 0) + { + Environment.Exit(code); + } + [Command("explorer")] public static void OpenExplorer(string path = ".") => Process.Start("explorer.exe", Path.GetFullPath(path)); @@ -318,6 +325,23 @@ public static class BaseModule Write(reader.ReadToEnd()); } + [Command("run")] + [CanCancel(false)] + public static void RunProcess(string name, string args = "") + { + Process? run = Process.Start(new ProcessStartInfo() + { + Arguments = args, + CreateNoWindow = false, + ErrorDialog = true, + FileName = name + }); + + if (run is null) throw new($"Error starting the process \"{name}\""); + + run.WaitForExit(); + } + [Command("sleep")] public static void WaitTime(int timeMs) => Thread.Sleep(timeMs); @@ -370,13 +394,6 @@ public static class BaseModule }); } - [Command("exit")] - [Command("quit")] - public static void QuitShell(int code = 0) - { - Environment.Exit(code); - } - [Command("undo")] public static void UndoCommand(int amount = 1) { -- 2.49.0.windows.1 From 68336df8686a1061c98493709a9dff87f142f5a4 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 10 Apr 2023 13:27:55 -0400 Subject: [PATCH 26/89] Made some basic start to the config stuff. More will come later. --- SrcMod/Shell/GlobalUsings.cs | 4 ++- SrcMod/Shell/ObjectModels/ShellConfig.cs | 46 ++++++++++++++++++++++++ SrcMod/Shell/Shell.cs | 13 ++++--- SrcMod/Shell/Shell.csproj | 2 ++ SrcMod/Shell/Tools.cs | 14 ++++++-- 5 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 SrcMod/Shell/ObjectModels/ShellConfig.cs diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index a26ef43..8ae847e 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -1,12 +1,14 @@ global using Nerd_STF.Mathematics; +global using Newtonsoft.Json; global using SharpCompress.Archives.Rar; global using SharpCompress.Archives.SevenZip; global using SharpCompress.Readers; -global using SrcMod.Shell; global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; +global using SrcMod.Shell.ObjectModels; global using System; global using System.Collections.Generic; +global using System.ComponentModel; global using System.Diagnostics; global using System.Formats.Tar; global using System.IO; diff --git a/SrcMod/Shell/ObjectModels/ShellConfig.cs b/SrcMod/Shell/ObjectModels/ShellConfig.cs new file mode 100644 index 0000000..d347d11 --- /dev/null +++ b/SrcMod/Shell/ObjectModels/ShellConfig.cs @@ -0,0 +1,46 @@ +namespace SrcMod.Shell.ObjectModels; + +public class ShellConfig +{ + public const string FilePath = "config.json"; + + public static ShellConfig Defaults => new() + { + SteamDirectories = new[] + { + "Temp" + } + }; + public static ShellConfig LoadedConfig => p_data ?? Defaults; + + private static ShellConfig? p_data; + + public string[] SteamDirectories; + + public static void LoadConfig(string basePath) + { + string fullPath = Path.Combine(basePath, FilePath); + + if (!File.Exists(fullPath)) + { + p_data = null; + return; + } + StreamReader reader = new(fullPath); + JsonTextReader jsonReader = new(reader); + p_data = Serializer.Deserialize(jsonReader); + jsonReader.Close(); + reader.Close(); + } + + public static void SaveConfig(string basePath) + { + string fullPath = Path.Combine(basePath, FilePath); + + StreamWriter writer = new(fullPath); + JsonTextWriter jsonWriter = new(writer); + Serializer.Serialize(jsonWriter, p_data); + jsonWriter.Close(); + writer.Close(); + } +} diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 3a90b88..634ab0a 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -1,12 +1,10 @@ -using System.ComponentModel; - -namespace SrcMod.Shell; +namespace SrcMod.Shell; public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.3.2"; + public const string Version = "Alpha 0.3.3"; public readonly string? ShellDirectory; @@ -50,6 +48,10 @@ public class Shell WorkingDirectory = Directory.GetCurrentDirectory(); + // Load config. + if (ShellDirectory is null) Write("[WARNING] Could not load config from shell location. Defaults will be used."); + else ShellConfig.LoadConfig(ShellDirectory); + // Load modules and commands. List possibleAsms = new() { @@ -250,6 +252,9 @@ public class Shell activeCommand.Dispose(); activeCommand = null; } + + if (ShellDirectory is null) Write("[WARNING] Could not save config to shell location. Any changes will be ignored."); + else ShellConfig.SaveConfig(ShellDirectory); return; } } diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index d662f45..253835f 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -13,6 +13,7 @@ false Logo.ico true + true @@ -31,6 +32,7 @@ + diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 3fea015..9de1e0f 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -1,9 +1,9 @@ -using System.Text; - -namespace SrcMod.Shell; +namespace SrcMod.Shell; public static class Tools { + public static JsonSerializer Serializer { get; private set; } + private static int loadingPosition = -1; private static int lastLoadingBufferSize = 0; private static int lastLoadingValue = -1; @@ -12,6 +12,14 @@ public static class Tools public static bool LoadingBarEnabled { get; private set; } + static Tools() + { + Serializer = JsonSerializer.Create(new() + { + Formatting = Formatting.Indented + }); + } + public static void DisplayWithPages(IEnumerable lines, ConsoleColor? color = null) { int written = 0; -- 2.49.0.windows.1 From b2bc9fa7eee90d08ad5db5f1d4c3439a13ad01de Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 10 Apr 2023 18:46:40 -0400 Subject: [PATCH 27/89] New config system. Tracks changes instead of the whole thing. --- SrcMod/Shell/ObjectModels/Config.cs | 76 ++++++++++++++++++++++ SrcMod/Shell/ObjectModels/ConfigChanges.cs | 8 +++ SrcMod/Shell/ObjectModels/ShellConfig.cs | 46 ------------- SrcMod/Shell/Shell.cs | 4 +- 4 files changed, 86 insertions(+), 48 deletions(-) create mode 100644 SrcMod/Shell/ObjectModels/Config.cs create mode 100644 SrcMod/Shell/ObjectModels/ConfigChanges.cs delete mode 100644 SrcMod/Shell/ObjectModels/ShellConfig.cs diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs new file mode 100644 index 0000000..87b5ed8 --- /dev/null +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -0,0 +1,76 @@ +namespace SrcMod.Shell.ObjectModels; + +public struct Config +{ + public const string FilePath = "config.json"; + + public static readonly Config Defaults; + + public static Config LoadedConfig + { + get => p_applied; + set + { + p_applied = value; + p_changes = p_applied.GetChanges(Defaults); + } + } + + private static Config p_applied; + private static ConfigChanges? p_changes; + + static Config() + { + Defaults = new(); + } + + public string[] SteamDirectories; + + public Config ApplyChanges(ConfigChanges changes) => this with + { + SteamDirectories = changes.SteamDirectories ?? SteamDirectories + }; + public ConfigChanges GetChanges(Config? baseConfig = null) + { + Config reference = baseConfig ?? Defaults; + return new() + { + SteamDirectories = reference.SteamDirectories == SteamDirectories ? null : SteamDirectories + }; + } + + public static void LoadConfig(string basePath) + { + string fullPath = Path.Combine(basePath, FilePath); + + if (!File.Exists(fullPath)) + { + p_applied = Defaults; + p_changes = null; + return; + } + StreamReader reader = new(fullPath); + JsonTextReader jsonReader = new(reader); + p_changes = Serializer.Deserialize(jsonReader); + jsonReader.Close(); + reader.Close(); + + p_applied = p_changes is null ? Defaults : Defaults.ApplyChanges(p_changes.Value); + } + public static void SaveConfig(string basePath) + { + string fullPath = Path.Combine(basePath, FilePath); + + if (p_changes is null || !p_changes.Value.HasChange) + { + if (File.Exists(fullPath)) File.Delete(fullPath); + return; + } + + StreamWriter writer = new(fullPath); + JsonTextWriter jsonWriter = new(writer); + Serializer.Serialize(jsonWriter, p_changes); + jsonWriter.Close(); + writer.Close(); + } +} diff --git a/SrcMod/Shell/ObjectModels/ConfigChanges.cs b/SrcMod/Shell/ObjectModels/ConfigChanges.cs new file mode 100644 index 0000000..909e662 --- /dev/null +++ b/SrcMod/Shell/ObjectModels/ConfigChanges.cs @@ -0,0 +1,8 @@ +namespace SrcMod.Shell.ObjectModels; + +public record struct ConfigChanges +{ + public bool HasChange => SteamDirectories is not null; + + public string[]? SteamDirectories; +} diff --git a/SrcMod/Shell/ObjectModels/ShellConfig.cs b/SrcMod/Shell/ObjectModels/ShellConfig.cs deleted file mode 100644 index d347d11..0000000 --- a/SrcMod/Shell/ObjectModels/ShellConfig.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace SrcMod.Shell.ObjectModels; - -public class ShellConfig -{ - public const string FilePath = "config.json"; - - public static ShellConfig Defaults => new() - { - SteamDirectories = new[] - { - "Temp" - } - }; - public static ShellConfig LoadedConfig => p_data ?? Defaults; - - private static ShellConfig? p_data; - - public string[] SteamDirectories; - - public static void LoadConfig(string basePath) - { - string fullPath = Path.Combine(basePath, FilePath); - - if (!File.Exists(fullPath)) - { - p_data = null; - return; - } - StreamReader reader = new(fullPath); - JsonTextReader jsonReader = new(reader); - p_data = Serializer.Deserialize(jsonReader); - jsonReader.Close(); - reader.Close(); - } - - public static void SaveConfig(string basePath) - { - string fullPath = Path.Combine(basePath, FilePath); - - StreamWriter writer = new(fullPath); - JsonTextWriter jsonWriter = new(writer); - Serializer.Serialize(jsonWriter, p_data); - jsonWriter.Close(); - writer.Close(); - } -} diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 634ab0a..78acb5a 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -50,7 +50,7 @@ public class Shell // Load config. if (ShellDirectory is null) Write("[WARNING] Could not load config from shell location. Defaults will be used."); - else ShellConfig.LoadConfig(ShellDirectory); + else Config.LoadConfig(ShellDirectory); // Load modules and commands. List possibleAsms = new() @@ -254,7 +254,7 @@ public class Shell } if (ShellDirectory is null) Write("[WARNING] Could not save config to shell location. Any changes will be ignored."); - else ShellConfig.SaveConfig(ShellDirectory); + else Config.SaveConfig(ShellDirectory); return; } } -- 2.49.0.windows.1 From 0c07c9cfe59858cbc0696a14b72fdaff058f80be Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 10 Apr 2023 19:23:46 -0400 Subject: [PATCH 28/89] Some tiny stuff. More tomorrow --- SrcMod/Shell/Modules/ConfigModule.cs | 11 ++++++++ SrcMod/Shell/ObjectModels/AskMode.cs | 8 ++++++ SrcMod/Shell/ObjectModels/Config.cs | 9 ++++--- SrcMod/Shell/ObjectModels/ConfigChanges.cs | 6 +++-- SrcMod/Shell/Tools.cs | 31 ++++++++++++++++++++-- 5 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 SrcMod/Shell/Modules/ConfigModule.cs create mode 100644 SrcMod/Shell/ObjectModels/AskMode.cs diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs new file mode 100644 index 0000000..4399b6e --- /dev/null +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -0,0 +1,11 @@ +namespace SrcMod.Shell.Modules; + +[Module("config")] +public static class ConfigModule +{ + [Command("display")] + public static void DisplayConfig() + { + // TODO + } +} diff --git a/SrcMod/Shell/ObjectModels/AskMode.cs b/SrcMod/Shell/ObjectModels/AskMode.cs new file mode 100644 index 0000000..e425960 --- /dev/null +++ b/SrcMod/Shell/ObjectModels/AskMode.cs @@ -0,0 +1,8 @@ +namespace SrcMod.Shell.ObjectModels; + +public enum AskMode : sbyte +{ + Never = -1, + Ask = 0, + Always = 1 +} diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 87b5ed8..5a8ad60 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -24,18 +24,21 @@ public struct Config Defaults = new(); } - public string[] SteamDirectories; + public string[] GameDirectories; + public AskMode RunUnsafeCommands; public Config ApplyChanges(ConfigChanges changes) => this with { - SteamDirectories = changes.SteamDirectories ?? SteamDirectories + GameDirectories = changes.GameDirectories ?? GameDirectories, + RunUnsafeCommands = changes.RunUnsafeCommands ?? RunUnsafeCommands }; public ConfigChanges GetChanges(Config? baseConfig = null) { Config reference = baseConfig ?? Defaults; return new() { - SteamDirectories = reference.SteamDirectories == SteamDirectories ? null : SteamDirectories + GameDirectories = reference.GameDirectories == GameDirectories ? null : GameDirectories, + RunUnsafeCommands = reference.RunUnsafeCommands == RunUnsafeCommands ? null : RunUnsafeCommands }; } diff --git a/SrcMod/Shell/ObjectModels/ConfigChanges.cs b/SrcMod/Shell/ObjectModels/ConfigChanges.cs index 909e662..8328796 100644 --- a/SrcMod/Shell/ObjectModels/ConfigChanges.cs +++ b/SrcMod/Shell/ObjectModels/ConfigChanges.cs @@ -2,7 +2,9 @@ public record struct ConfigChanges { - public bool HasChange => SteamDirectories is not null; + [JsonIgnore] + public bool HasChange => GameDirectories is not null || RunUnsafeCommands is not null; - public string[]? SteamDirectories; + public string[]? GameDirectories; + public AskMode? RunUnsafeCommands; } diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 9de1e0f..8772ef8 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -1,4 +1,6 @@ -namespace SrcMod.Shell; +using System.Numerics; + +namespace SrcMod.Shell; public static class Tools { @@ -16,7 +18,8 @@ public static class Tools { Serializer = JsonSerializer.Create(new() { - Formatting = Formatting.Indented + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore }); } @@ -165,6 +168,30 @@ public static class Tools } } + public static void WriteAutoColor(object? message, bool newLine = true) + { + ConsoleColor? col = null; + if (message is null) col = ConsoleColor.DarkGray; + else if (message is bool typeBool) + { + if (typeBool) col = ConsoleColor.Green; + else col = ConsoleColor.Red; + } + else if (message is sbyte || message is byte || message is short || message is ushort || + message is int || message is uint || message is long || message is ulong || + message is float || message is double || message is decimal) col = ConsoleColor.DarkGreen; + else if (message is char) col = ConsoleColor.DarkYellow; + else if (message is AskMode typeAskMode) col = typeAskMode switch + { + AskMode.Never => ConsoleColor.Red, + AskMode.Ask => ConsoleColor.DarkGray, + AskMode.Always => ConsoleColor.Green, + _ => null + }; + + Write(message, col, newLine); + } + public static bool ValidateUnsafe() { Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false); -- 2.49.0.windows.1 From 3742b4a230f68918d706dba06bfc3578f4e5eb7d Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Mon, 17 Apr 2023 17:58:28 -0400 Subject: [PATCH 29/89] Some config display changes. WIP --- SrcMod/Shell/Modules/ConfigModule.cs | 63 +++++++++++++++++++++++++++- SrcMod/Shell/ObjectModels/Config.cs | 19 +++++++-- SrcMod/Shell/Tools.cs | 24 ----------- 3 files changed, 76 insertions(+), 30 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 4399b6e..426fb77 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -4,8 +4,67 @@ public static class ConfigModule { [Command("display")] - public static void DisplayConfig() + public static void DisplayConfig(ConfigDisplayMode mode = ConfigDisplayMode.Color) { - // TODO + switch (mode) + { + case ConfigDisplayMode.Raw: + DisplayConfigRaw(); + break; + + case ConfigDisplayMode.Color: + DisplayConfigColor(); + break; + } + } + + private static void DisplayConfigColor() + { + Config config = Config.LoadedConfig; + List dirs = config.GameDirectories is null ? new() : new(config.GameDirectories); + dirs.Add("config"); + config.GameDirectories = dirs.ToArray(); + Config.LoadedConfig = config; + + Write("Steam Game Directories: ", null, false); + if (config.GameDirectories is null || config.GameDirectories.Length <= 0) Write("None", ConsoleColor.DarkGray); + else + { + Write("[", ConsoleColor.DarkGray); + for (int i = 0; i < config.GameDirectories.Length; i++) + { + Write(" \"", ConsoleColor.DarkGray, false); + Write(config.GameDirectories[i], ConsoleColor.White, false); + if (i < config.GameDirectories.Length - 1) Write("\",", ConsoleColor.DarkGray); + else Write("\"", ConsoleColor.DarkGray); + } + Write("]", ConsoleColor.DarkGray); + } + } + private static void DisplayConfigRaw() + { + MemoryStream ms = new(); + StreamWriter writer = new(ms, leaveOpen: true); + JsonTextWriter jsonWriter = new(writer); + + Serializer.Serialize(jsonWriter, Config.LoadedConfig); + + jsonWriter.Close(); + writer.Close(); + ms.Position = 0; + + StreamReader reader = new(ms); + string msg = reader.ReadToEnd(); + + Write(msg); + + reader.Close(); + ms.Close(); + } + + public enum ConfigDisplayMode + { + Raw, + Color } } diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 5a8ad60..e76ce48 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -21,7 +21,15 @@ public struct Config static Config() { - Defaults = new(); + Defaults = new() + { + GameDirectories = new[] + { + "testing 1", + "testing 2" + }, + RunUnsafeCommands = AskMode.Ask + }; } public string[] GameDirectories; @@ -29,17 +37,20 @@ public struct Config public Config ApplyChanges(ConfigChanges changes) => this with { - GameDirectories = changes.GameDirectories ?? GameDirectories, + GameDirectories = GameDirectories.Union(changes.GameDirectories ?? Array.Empty()).ToArray(), RunUnsafeCommands = changes.RunUnsafeCommands ?? RunUnsafeCommands }; public ConfigChanges GetChanges(Config? baseConfig = null) { Config reference = baseConfig ?? Defaults; - return new() + ConfigChanges changes = new() { - GameDirectories = reference.GameDirectories == GameDirectories ? null : GameDirectories, + GameDirectories = reference.GameDirectories == GameDirectories ? null : + GameDirectories.Where(x => !reference.GameDirectories.Contains(x)).ToArray(), RunUnsafeCommands = reference.RunUnsafeCommands == RunUnsafeCommands ? null : RunUnsafeCommands }; + + return changes; } public static void LoadConfig(string basePath) diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 8772ef8..713ffea 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -168,30 +168,6 @@ public static class Tools } } - public static void WriteAutoColor(object? message, bool newLine = true) - { - ConsoleColor? col = null; - if (message is null) col = ConsoleColor.DarkGray; - else if (message is bool typeBool) - { - if (typeBool) col = ConsoleColor.Green; - else col = ConsoleColor.Red; - } - else if (message is sbyte || message is byte || message is short || message is ushort || - message is int || message is uint || message is long || message is ulong || - message is float || message is double || message is decimal) col = ConsoleColor.DarkGreen; - else if (message is char) col = ConsoleColor.DarkYellow; - else if (message is AskMode typeAskMode) col = typeAskMode switch - { - AskMode.Never => ConsoleColor.Red, - AskMode.Ask => ConsoleColor.DarkGray, - AskMode.Always => ConsoleColor.Green, - _ => null - }; - - Write(message, col, newLine); - } - public static bool ValidateUnsafe() { Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false); -- 2.49.0.windows.1 From 4d342ae9585d89e92ed1e6752e972bd4f6210ed3 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Mon, 17 Apr 2023 19:11:33 -0400 Subject: [PATCH 30/89] Added some config stuff. Next is modifying the config. --- SrcMod/Shell/Modules/ConfigModule.cs | 15 ++++++++--- SrcMod/Shell/Tools.cs | 37 ++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 426fb77..392d4cb 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -21,10 +21,6 @@ public static class ConfigModule private static void DisplayConfigColor() { Config config = Config.LoadedConfig; - List dirs = config.GameDirectories is null ? new() : new(config.GameDirectories); - dirs.Add("config"); - config.GameDirectories = dirs.ToArray(); - Config.LoadedConfig = config; Write("Steam Game Directories: ", null, false); if (config.GameDirectories is null || config.GameDirectories.Length <= 0) Write("None", ConsoleColor.DarkGray); @@ -40,9 +36,20 @@ public static class ConfigModule } Write("]", ConsoleColor.DarkGray); } + + Write("Run Unsafe Commands: ", null, false); + ConsoleColor color = config.RunUnsafeCommands switch + { + AskMode.Never => ConsoleColor.Red, + AskMode.Always => ConsoleColor.Green, + AskMode.Ask or _ => ConsoleColor.DarkGray + }; + Write(config.RunUnsafeCommands, color); } private static void DisplayConfigRaw() { + // This is definitely a bit inefficient, but shouldn't be too much of an issue. + MemoryStream ms = new(); StreamWriter writer = new(ms, leaveOpen: true); JsonTextWriter jsonWriter = new(writer); diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 713ffea..e9ff45b 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -170,15 +170,36 @@ public static class Tools public static bool ValidateUnsafe() { - Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false); + switch (Config.LoadedConfig.RunUnsafeCommands) + { + case AskMode.Always: + Write("[INFO] The shell has been configured to always run unsafe commands. " + + "This can be changed in the config.", ConsoleColor.DarkGray); + return true; - Console.ForegroundColor = ConsoleColor.Yellow; - Console.CursorVisible = true; - string result = Console.ReadLine()!.Trim().ToLower(); - Console.CursorVisible = false; - Console.ResetColor(); + case AskMode.Never: + Write("[ERROR] The shell has been configured to never run unsafe commands. " + + "This can be changed in the config.", ConsoleColor.Red); + return false; - return result == "y" || result == "yes" || result == "t" || - result == "true" || result == "p" || result == "proceed"; + case AskMode.Ask or _: + Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false); + Int2 start = (Console.CursorLeft, Console.CursorTop); + Write("\nTip: You can disable this dialog in the config.", ConsoleColor.DarkGray); + int finish = Console.CursorTop; + + Console.SetCursorPosition(start.x, start.y); + + Console.ForegroundColor = ConsoleColor.Yellow; + Console.CursorVisible = true; + string result = Console.ReadLine()!.Trim().ToLower(); + Console.CursorVisible = false; + Console.ResetColor(); + + Console.SetCursorPosition(0, finish); + + return result == "y" || result == "yes" || result == "t" || + result == "true" || result == "p" || result == "proceed"; + } } } -- 2.49.0.windows.1 From 8bfd8c142c3105b523bc07b3fc33baa7079f50f8 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 17 Apr 2023 19:38:31 -0400 Subject: [PATCH 31/89] Quick update, added some more config display options. --- SrcMod/Shell/Modules/ConfigModule.cs | 76 +++++++++++++++++----------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 392d4cb..a206493 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -4,7 +4,7 @@ public static class ConfigModule { [Command("display")] - public static void DisplayConfig(ConfigDisplayMode mode = ConfigDisplayMode.Color) + public static void DisplayConfig(ConfigDisplayMode mode = ConfigDisplayMode.All) { switch (mode) { @@ -12,39 +12,24 @@ public static class ConfigModule DisplayConfigRaw(); break; - case ConfigDisplayMode.Color: - DisplayConfigColor(); + case ConfigDisplayMode.All: + DisplayConfigAll(); + break; + + case ConfigDisplayMode.GameDirectories: + DisplayConfigGameDirectories(); + break; + + case ConfigDisplayMode.RunUnsafeCommands: + DisplayConfigUnsafeCommands(); break; } } - private static void DisplayConfigColor() + private static void DisplayConfigAll() { - Config config = Config.LoadedConfig; - - Write("Steam Game Directories: ", null, false); - if (config.GameDirectories is null || config.GameDirectories.Length <= 0) Write("None", ConsoleColor.DarkGray); - else - { - Write("[", ConsoleColor.DarkGray); - for (int i = 0; i < config.GameDirectories.Length; i++) - { - Write(" \"", ConsoleColor.DarkGray, false); - Write(config.GameDirectories[i], ConsoleColor.White, false); - if (i < config.GameDirectories.Length - 1) Write("\",", ConsoleColor.DarkGray); - else Write("\"", ConsoleColor.DarkGray); - } - Write("]", ConsoleColor.DarkGray); - } - - Write("Run Unsafe Commands: ", null, false); - ConsoleColor color = config.RunUnsafeCommands switch - { - AskMode.Never => ConsoleColor.Red, - AskMode.Always => ConsoleColor.Green, - AskMode.Ask or _ => ConsoleColor.DarkGray - }; - Write(config.RunUnsafeCommands, color); + DisplayConfigGameDirectories(); + DisplayConfigUnsafeCommands(); } private static void DisplayConfigRaw() { @@ -68,10 +53,41 @@ public static class ConfigModule reader.Close(); ms.Close(); } + private static void DisplayConfigGameDirectories() + { + Write("Steam Game Directories: ", null, false); + if (Config.LoadedConfig.GameDirectories is null || Config.LoadedConfig.GameDirectories.Length <= 0) + Write("None", ConsoleColor.DarkGray); + else + { + Write("[", ConsoleColor.DarkGray); + for (int i = 0; i < Config.LoadedConfig.GameDirectories.Length; i++) + { + Write(" \"", ConsoleColor.DarkGray, false); + Write(Config.LoadedConfig.GameDirectories[i], ConsoleColor.White, false); + if (i < Config.LoadedConfig.GameDirectories.Length - 1) Write("\",", ConsoleColor.DarkGray); + else Write("\"", ConsoleColor.DarkGray); + } + Write("]", ConsoleColor.DarkGray); + } + } + private static void DisplayConfigUnsafeCommands() + { + Write("Run Unsafe Commands: ", null, false); + ConsoleColor color = Config.LoadedConfig.RunUnsafeCommands switch + { + AskMode.Never => ConsoleColor.Red, + AskMode.Always => ConsoleColor.Green, + AskMode.Ask or _ => ConsoleColor.DarkGray + }; + Write(Config.LoadedConfig.RunUnsafeCommands, color); + } public enum ConfigDisplayMode { Raw, - Color + All, + GameDirectories, + RunUnsafeCommands } } -- 2.49.0.windows.1 From ec15e78564717d854f738d0811377359686b67cc Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 17 Apr 2023 20:12:52 -0400 Subject: [PATCH 32/89] Added some config modifier commands. Definitely not very automated, stuff to do later. --- SrcMod/Shell/Modules/ConfigModule.cs | 101 +++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index a206493..58e88a0 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -4,6 +4,7 @@ public static class ConfigModule { [Command("display")] + [Command("list")] public static void DisplayConfig(ConfigDisplayMode mode = ConfigDisplayMode.All) { switch (mode) @@ -26,6 +27,106 @@ public static class ConfigModule } } + [Command("add")] + [Command("append")] + public static void AppendConfigVariable(string name, string value) + { + Config config = Config.LoadedConfig; + + switch (name.Trim().ToLower()) + { + case "gamedirectories": + config.GameDirectories = config.GameDirectories.Append(value).ToArray(); + break; + + case "rununsafecommands": + throw new($"The config variable \"{name}\" is a single variable and cannot be appended to."); + + default: throw new($"Unknown config variable \"{name}\""); + } + + Config.LoadedConfig = config; + } + + [Command("delete")] + [Command("remove")] + public static void RemoveConfigVariable(string name, string value) + { + Config config = Config.LoadedConfig; + + switch (name.Trim().ToLower()) + { + case "gamedirectories": + config.GameDirectories = config.GameDirectories + .Where(x => x.Trim().ToLower() != value.Trim().ToLower()) + .ToArray(); + break; + + case "rununsafecommands": + throw new($"The config variable \"{name}\" is a single variable and cannot be appended to."); + + default: throw new($"Unknown config variable \"{name}\""); + } + + Config.LoadedConfig = config; + } + + [Command("reset")] + public static void ResetConfig(string name = "all") + { + Config config = Config.LoadedConfig; + + switch (name.Trim().ToLower()) + { + case "gamedirectories": + config.GameDirectories = Config.Defaults.GameDirectories; + break; + + case "rununsafecommands": + config.RunUnsafeCommands = Config.Defaults.RunUnsafeCommands; + break; + + case "all": + config = Config.Defaults; + break; + + default: throw new($"Unknown config variable \"{name}\""); + } + + Config.LoadedConfig = config; + } + + [Command("set")] + public static void SetConfigVariable(string name, string value) + { + Config config = Config.LoadedConfig; + + switch (name.Trim().ToLower()) + { + case "gamedirectories": + throw new($"The config variable \"{name}\" is a list and must be added or removed to."); + + case "rununsafecommands": + if (int.TryParse(value, out int intRes)) + { + AskMode mode = (AskMode)intRes; + if (!Enum.IsDefined(mode)) throw new($"(AskMode){value} is not a valid AskMode."); + config.RunUnsafeCommands = mode; + } + else if (Enum.TryParse(value, true, out AskMode modeRes)) + { + if (!Enum.IsDefined(modeRes)) throw new($"\"{value}\" is not a valid AskMode."); + config.RunUnsafeCommands = modeRes; + } + else throw new($"\"{value}\" is not a valid AskMode."); + break; + + default: throw new($"Unknown config variable \"{name}\""); + } + + Config.LoadedConfig = config; + } + private static void DisplayConfigAll() { DisplayConfigGameDirectories(); -- 2.49.0.windows.1 From b7a4333e2d39a2362c6d933996bcccd87748d718 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 17 Apr 2023 20:27:40 -0400 Subject: [PATCH 33/89] Added the ability to load custom assemblies to the shell. --- SrcMod/Shell/Shell.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 3a90b88..8516305 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -95,6 +95,26 @@ public class Shell ReloadDirectoryInfo(); } + public bool LoadModule(Type moduleType) + { + if (LoadedModules.Any(x => x.Type.FullName == moduleType.FullName)) return false; + + ModuleInfo? module = ModuleInfo.FromType(moduleType); + if (module is null) return false; + + LoadedModules.Add(module); + LoadedCommands.AddRange(module.Commands); + + return true; + } + public bool LoadModule() => LoadModule(typeof(T)); + public int LoadModules(Assembly moduleAssembly) + { + int loaded = 0; + foreach (Type moduleType in moduleAssembly.GetTypes()) if (LoadModule(moduleType)) loaded++; + return loaded; + } + public void AddHistory(HistoryItem item) => History.Add(item); public void UndoItem() { -- 2.49.0.windows.1 From b869de9be869dabb3ac23bda6254d77c03898923 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 17 Apr 2023 21:02:39 -0400 Subject: [PATCH 34/89] Directory info is now reloaded after every command. One liner fix. --- SrcMod/Shell/Shell.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 8516305..08de616 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -270,6 +270,8 @@ public class Shell activeCommand.Dispose(); activeCommand = null; } + + ReloadDirectoryInfo(); return; } } -- 2.49.0.windows.1 From 4d2e98ce427ad24ca104ed8060d6c0ec1db4d303 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 18 Apr 2023 08:31:40 -0400 Subject: [PATCH 35/89] Moved the loading bar to its own class. Small fix. --- SrcMod/Shell/LoadingBar.cs | 79 +++++++++++++++++++++ SrcMod/Shell/Modules/BaseModule.cs | 12 ++-- SrcMod/Shell/Modules/CompressionModule.cs | 6 +- SrcMod/Shell/Shell.cs | 4 +- SrcMod/Shell/Tools.cs | 83 ++--------------------- 5 files changed, 94 insertions(+), 90 deletions(-) create mode 100644 SrcMod/Shell/LoadingBar.cs diff --git a/SrcMod/Shell/LoadingBar.cs b/SrcMod/Shell/LoadingBar.cs new file mode 100644 index 0000000..f658c8e --- /dev/null +++ b/SrcMod/Shell/LoadingBar.cs @@ -0,0 +1,79 @@ +namespace SrcMod.Shell; + +internal static class LoadingBar +{ + public static int position = -1; + public static int bufferSize = 0; + public static int lastValue = -1; + public static float value = 0; + public static ConsoleColor color = Console.ForegroundColor; + + public static bool Enabled { get; private set; } + + public static void End(bool clear = true) + { + if (position == -1) throw new("No loading bar is active."); + + if (clear) + { + Int2 oldPos = (Console.CursorLeft, Console.CursorTop); + + Console.CursorLeft = 0; + Console.CursorTop = position; + Console.Write(new string(' ', Console.BufferWidth)); + Console.CursorLeft = 0; + + Console.SetCursorPosition(oldPos.x, oldPos.y); + } + position = -1; + Enabled = false; + } + public static void Set(float value, ConsoleColor? color = null) + { + const string left = " --- [", + right = "] --- "; + int barSize = Console.BufferWidth - left.Length - right.Length, + filled = (int)(barSize * value); + + if (filled == lastValue) return; + lastValue = filled; + + Int2 oldPos = (Console.CursorLeft, Console.CursorTop); + + LoadingBar.value = value; + LoadingBar.color = color ?? Console.ForegroundColor; + + // Erase last bar. + Console.SetCursorPosition(0, position); + Console.Write(new string(' ', bufferSize)); + Console.CursorLeft = 0; + + // Add new bar. + bufferSize = Console.BufferWidth; + + Write(left, newLine: false); + ConsoleColor oldFore = Console.ForegroundColor; + + if (color is not null) Console.ForegroundColor = color.Value; + Write(new string('=', filled), newLine: false); + if (color is not null) Console.ForegroundColor = oldFore; + Write(new string(' ', barSize - filled), newLine: false); + Write(right, newLine: false); + + if (oldPos.y == Console.CursorTop) oldPos.y++; + while (oldPos.y >= Console.BufferHeight) + { + Console.WriteLine(); + oldPos.y--; + position--; + } + Console.SetCursorPosition(oldPos.x, oldPos.y); + } + public static void Start(float value = 0, int? position = null, ConsoleColor? color = null) + { + if (LoadingBar.position != -1) throw new("The loading bar has already been enabled."); + LoadingBar.position = position ?? Console.CursorTop; + Enabled = true; + Set(value, color); + } +} diff --git a/SrcMod/Shell/Modules/BaseModule.cs b/SrcMod/Shell/Modules/BaseModule.cs index 0436cb5..eae1fd6 100644 --- a/SrcMod/Shell/Modules/BaseModule.cs +++ b/SrcMod/Shell/Modules/BaseModule.cs @@ -45,7 +45,7 @@ public static class BaseModule Write($"Copying directory \"{source}\" to \"{destination}\"..."); - LoadingBarStart(); + LoadingBar.Start(); for (int i = 0; i < files.Length; i++) { string file = files[i], @@ -53,7 +53,7 @@ public static class BaseModule destFile = Path.Combine(destination, file); Directory.CreateDirectory(Path.GetDirectoryName(destFile)!); File.Copy(sourceFile, destFile); - LoadingBarSet((i + 1) / (float)files.Length, ConsoleColor.DarkGreen); + LoadingBar.Set((i + 1) / (float)files.Length, ConsoleColor.DarkGreen); Console.CursorLeft = 0; string message = $"{sourceFile}"; int remainder = Console.BufferWidth - message.Length; @@ -63,7 +63,7 @@ public static class BaseModule Write(message, newLine: false); } - LoadingBarEnd(); + LoadingBar.End(); Console.CursorLeft = 0; Write(new string(' ', Console.BufferWidth), newLine: false); @@ -361,13 +361,13 @@ public static class BaseModule Thread.Sleep(rand.Next(500, 1000)); - LoadingBarStart(); + LoadingBar.Start(); for (int i = 0; i < files.Length; i++) { FileInfo file = new(files[i]); Thread.Sleep((int)(rand.Next(50, 100) * (file.Length >> 20))); - LoadingBarSet((i + 1) / (float)files.Length, ConsoleColor.Red); + LoadingBar.Set((i + 1) / (float)files.Length, ConsoleColor.Red); Console.CursorLeft = 0; string message = $"{files[i]}"; int remainder = Console.BufferWidth - message.Length; @@ -377,7 +377,7 @@ public static class BaseModule Write(message, newLine: false); } - LoadingBarEnd(); + LoadingBar.End(); Console.CursorLeft = 0; Write(new string(' ', Console.BufferWidth), newLine: false); diff --git a/SrcMod/Shell/Modules/CompressionModule.cs b/SrcMod/Shell/Modules/CompressionModule.cs index 43d5804..128dcf9 100644 --- a/SrcMod/Shell/Modules/CompressionModule.cs +++ b/SrcMod/Shell/Modules/CompressionModule.cs @@ -168,7 +168,7 @@ public static class CompressionModule int failed = 0; - LoadingBarStart(); + LoadingBar.Start(); for (int i = 0; i < files.Count; i++) { bool failedThisTime = false; @@ -181,7 +181,7 @@ public static class CompressionModule failedThisTime = true; failed++; } - LoadingBarSet((i + 1) / (float)files.Count, failedThisTime ? ConsoleColor.Red : ConsoleColor.DarkGreen); ; + LoadingBar.Set((i + 1) / (float)files.Count, failedThisTime ? ConsoleColor.Red : ConsoleColor.DarkGreen); ; Console.CursorLeft = 0; string message = $"{relative[i]}"; int remainder = Console.BufferWidth - message.Length; @@ -194,7 +194,7 @@ public static class CompressionModule archive.Dispose(); writer.Dispose(); - LoadingBarEnd(); + LoadingBar.End(); Console.CursorLeft = 0; Write(new string(' ', Console.BufferWidth), newLine: false); diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 08de616..58cd52e 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -247,12 +247,12 @@ public class Shell catch (TargetInvocationException ex) { Write($"[ERROR] {ex.InnerException!.Message}", ConsoleColor.Red); - if (LoadingBarEnabled) LoadingBarEnd(); + if (LoadingBar.Enabled) LoadingBar.End(); } catch (Exception ex) { Write($"[ERROR] {ex.Message}", ConsoleColor.Red); - if (LoadingBarEnabled) LoadingBarEnd(); + if (LoadingBar.Enabled) LoadingBar.End(); } #endif } diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 3fea015..ef6cc12 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -2,16 +2,8 @@ namespace SrcMod.Shell; -public static class Tools +internal static class Tools { - private static int loadingPosition = -1; - private static int lastLoadingBufferSize = 0; - private static int lastLoadingValue = -1; - private static float loadingBarValue = 0; - private static ConsoleColor loadingBarColor = Console.ForegroundColor; - - public static bool LoadingBarEnabled { get; private set; } - public static void DisplayWithPages(IEnumerable lines, ConsoleColor? color = null) { int written = 0; @@ -73,73 +65,6 @@ public static class Tools return allFiles; } - public static void LoadingBarEnd(bool clear = true) - { - if (loadingPosition == -1) throw new("No loading bar is active."); - - if (clear) - { - Int2 oldPos = (Console.CursorLeft, Console.CursorTop); - - Console.CursorLeft = 0; - Console.CursorTop = loadingPosition; - Console.Write(new string(' ', Console.BufferWidth)); - Console.CursorLeft = 0; - - Console.SetCursorPosition(oldPos.x, oldPos.y); - } - loadingPosition = -1; - LoadingBarEnabled = false; - } - public static void LoadingBarSet(float value, ConsoleColor? color = null) - { - const string left = " --- [", - right = "] --- "; - int barSize = Console.BufferWidth - left.Length - right.Length, - filled = (int)(barSize * value); - - if (filled == lastLoadingValue) return; - lastLoadingValue = filled; - - Int2 oldPos = (Console.CursorLeft, Console.CursorTop); - - loadingBarValue = value; - loadingBarColor = color ?? Console.ForegroundColor; - - // Erase last bar. - Console.SetCursorPosition(0, loadingPosition); - Console.Write(new string(' ', lastLoadingBufferSize)); - Console.CursorLeft = 0; - - // Add new bar. - lastLoadingBufferSize = Console.BufferWidth; - - Write(left, newLine: false); - ConsoleColor oldFore = Console.ForegroundColor; - - if (color is not null) Console.ForegroundColor = color.Value; - Write(new string('=', filled), newLine: false); - if (color is not null) Console.ForegroundColor = oldFore; - Write(new string(' ', barSize - filled), newLine: false); - Write(right, newLine: false); - - if (oldPos.y == Console.CursorTop) oldPos.y++; - while (oldPos.y >= Console.BufferHeight) - { - Console.WriteLine(); - oldPos.y--; - loadingPosition--; - } - Console.SetCursorPosition(oldPos.x, oldPos.y); - } - public static void LoadingBarStart(float value = 0, int? position = null, ConsoleColor? color = null) - { - if (loadingPosition != -1) throw new("The loading bar has already been enabled."); - loadingPosition = position ?? Console.CursorTop; - LoadingBarEnabled = true; - LoadingBarSet(value, color); - } - public static void Write(object? message, ConsoleColor? col = null, bool newLine = true) { ConsoleColor prevCol = Console.ForegroundColor; @@ -150,10 +75,10 @@ public static class Tools Console.ForegroundColor = prevCol; - if (newLine && LoadingBarEnabled && Console.CursorTop >= Console.BufferHeight - 1) + if (newLine && LoadingBar.Enabled && Console.CursorTop >= Console.BufferHeight - 1) { - loadingPosition--; - LoadingBarSet(loadingBarValue, loadingBarColor); + LoadingBar.position--; + LoadingBar.Set(LoadingBar.value, LoadingBar.color); } } -- 2.49.0.windows.1 From fd4162aa32b56328806c6267bfe2408a06cfaf66 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 18 Apr 2023 08:52:04 -0400 Subject: [PATCH 36/89] How on earth did I miss this? --- SrcMod/Shell/Tools.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index 3747dc6..cebd629 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -4,17 +4,8 @@ namespace SrcMod.Shell; internal static class Tools { -<<<<<<< HEAD public static JsonSerializer Serializer { get; private set; } - private static int loadingPosition = -1; - private static int lastLoadingBufferSize = 0; - private static int lastLoadingValue = -1; - private static float loadingBarValue = 0; - private static ConsoleColor loadingBarColor = Console.ForegroundColor; - - public static bool LoadingBarEnabled { get; private set; } - static Tools() { Serializer = JsonSerializer.Create(new() @@ -24,8 +15,6 @@ internal static class Tools }); } -======= ->>>>>>> origin/shell-systems public static void DisplayWithPages(IEnumerable lines, ConsoleColor? color = null) { int written = 0; -- 2.49.0.windows.1 From 25c6d152a2ead697d37ab913ebc072c155a72d5a Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 18 Apr 2023 08:57:45 -0400 Subject: [PATCH 37/89] Removed some test stuff. --- SrcMod/Shell/ObjectModels/Config.cs | 6 +----- SrcMod/Shell/Tools.cs | 4 +--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index e76ce48..a14e6df 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -23,11 +23,7 @@ public struct Config { Defaults = new() { - GameDirectories = new[] - { - "testing 1", - "testing 2" - }, + GameDirectories = Array.Empty(), RunUnsafeCommands = AskMode.Ask }; } diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index cebd629..c90265d 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -1,6 +1,4 @@ -using System.Numerics; - -namespace SrcMod.Shell; +namespace SrcMod.Shell; internal static class Tools { -- 2.49.0.windows.1 From 8677ff464d483fd79e41411883aea467fd428ff6 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 18 Apr 2023 16:03:01 -0400 Subject: [PATCH 38/89] Made the display system of the config data a gazillion times better. --- SrcMod/Shell/Modules/ConfigModule.cs | 124 ++++++++++++++------------- SrcMod/Shell/ObjectModels/Config.cs | 1 + 2 files changed, 66 insertions(+), 59 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 58e88a0..f9b617f 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -5,24 +5,20 @@ public static class ConfigModule { [Command("display")] [Command("list")] - public static void DisplayConfig(ConfigDisplayMode mode = ConfigDisplayMode.All) + public static void DisplayConfig(string display = "all") { - switch (mode) + switch (display.Trim().ToLower()) { - case ConfigDisplayMode.Raw: - DisplayConfigRaw(); - break; - - case ConfigDisplayMode.All: + case "all": DisplayConfigAll(); break; - case ConfigDisplayMode.GameDirectories: - DisplayConfigGameDirectories(); + case "raw": + DisplayConfigRaw(); break; - case ConfigDisplayMode.RunUnsafeCommands: - DisplayConfigUnsafeCommands(); + default: + DisplayConfigName(display); break; } } @@ -129,66 +125,76 @@ public static class ConfigModule private static void DisplayConfigAll() { - DisplayConfigGameDirectories(); - DisplayConfigUnsafeCommands(); + FieldInfo[] validFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); + + foreach (FieldInfo field in validFields) + DisplayConfigItem(field.GetValue(Config.LoadedConfig), name: field.Name); } - private static void DisplayConfigRaw() + private static void DisplayConfigItem(T item, int indents = 0, string name = "", bool newLine = true) { - // This is definitely a bit inefficient, but shouldn't be too much of an issue. + Write(new string(' ', indents * 4), newLine: false); + if (!string.IsNullOrWhiteSpace(name)) Write($"{name}: ", newLine: false); - MemoryStream ms = new(); - StreamWriter writer = new(ms, leaveOpen: true); - JsonTextWriter jsonWriter = new(writer); - - Serializer.Serialize(jsonWriter, Config.LoadedConfig); - - jsonWriter.Close(); - writer.Close(); - ms.Position = 0; - - StreamReader reader = new(ms); - string msg = reader.ReadToEnd(); - - Write(msg); - - reader.Close(); - ms.Close(); - } - private static void DisplayConfigGameDirectories() - { - Write("Steam Game Directories: ", null, false); - if (Config.LoadedConfig.GameDirectories is null || Config.LoadedConfig.GameDirectories.Length <= 0) - Write("None", ConsoleColor.DarkGray); - else + if (item is Array itemArray) { - Write("[", ConsoleColor.DarkGray); - for (int i = 0; i < Config.LoadedConfig.GameDirectories.Length; i++) + if (itemArray.Length < 1) { - Write(" \"", ConsoleColor.DarkGray, false); - Write(Config.LoadedConfig.GameDirectories[i], ConsoleColor.White, false); - if (i < Config.LoadedConfig.GameDirectories.Length - 1) Write("\",", ConsoleColor.DarkGray); - else Write("\"", ConsoleColor.DarkGray); + Write("[]", ConsoleColor.DarkGray, newLine); + return; } - Write("]", ConsoleColor.DarkGray); + + Write("[", ConsoleColor.DarkGray); + for (int i = 0; i < itemArray.Length; i++) + { + DisplayConfigItem(itemArray.GetValue(i), indents + 1, newLine: false); + if (i < itemArray.Length - 1) Write(',', newLine: false); + Write('\n', newLine: false); + } + Write(new string(' ', indents * 4) + "]", ConsoleColor.DarkGray, newLine); } - } - private static void DisplayConfigUnsafeCommands() - { - Write("Run Unsafe Commands: ", null, false); - ConsoleColor color = Config.LoadedConfig.RunUnsafeCommands switch + else if (item is byte itemByte) Write($"0x{itemByte:X2}", ConsoleColor.Yellow, newLine); + else if (item is sbyte or short or ushort or int or uint or long or ulong) + Write(item, ConsoleColor.Yellow, newLine); + else if (item is char) + { + Write("\'", ConsoleColor.DarkGray, false); + Write(item, ConsoleColor.Blue, false); + Write("\'", ConsoleColor.DarkGray, newLine); + } + else if (item is string) + { + Write("\"", ConsoleColor.DarkGray, false); + Write(item, ConsoleColor.DarkCyan, false); + Write("\"", ConsoleColor.DarkGray, newLine); + } + else if (item is AskMode) Write(item, item switch { AskMode.Never => ConsoleColor.Red, AskMode.Always => ConsoleColor.Green, AskMode.Ask or _ => ConsoleColor.DarkGray - }; - Write(Config.LoadedConfig.RunUnsafeCommands, color); + }, newLine); + else Write(item, newLine: newLine); } - - public enum ConfigDisplayMode + private static void DisplayConfigName(string name) { - Raw, - All, - GameDirectories, - RunUnsafeCommands + FieldInfo[] validFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); + + FieldInfo? chosenField = validFields.FirstOrDefault(x => x.Name.Trim().ToLower() == name.Trim().ToLower()); + if (chosenField is null) throw new($"No config variable named \"{name}\"."); + + DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); + } + private static void DisplayConfigRaw() + { + string json = JsonConvert.SerializeObject(Config.LoadedConfig, Formatting.Indented); + Write(json); } } diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index a14e6df..f66f5e7 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -79,6 +79,7 @@ public struct Config StreamWriter writer = new(fullPath); JsonTextWriter jsonWriter = new(writer); + jsonWriter.Indentation = 4; Serializer.Serialize(jsonWriter, p_changes); jsonWriter.Close(); writer.Close(); -- 2.49.0.windows.1 From 318c8119a0eaa3cf554f7da31f7f3e477fbb6a70 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 19 Apr 2023 07:21:59 -0400 Subject: [PATCH 39/89] Small change in the config display system. --- SrcMod/Shell/Modules/ConfigModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index f9b617f..4835833 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -157,8 +157,9 @@ public static class ConfigModule Write(new string(' ', indents * 4) + "]", ConsoleColor.DarkGray, newLine); } else if (item is byte itemByte) Write($"0x{itemByte:X2}", ConsoleColor.Yellow, newLine); - else if (item is sbyte or short or ushort or int or uint or long or ulong) + else if (item is sbyte or short or ushort or int or uint or long or ulong or float or double or decimal) Write(item, ConsoleColor.Yellow, newLine); + else if (item is bool itemBool) Write(item, itemBool ? ConsoleColor.Green : ConsoleColor.Red, newLine); else if (item is char) { Write("\'", ConsoleColor.DarkGray, false); -- 2.49.0.windows.1 From 647993ef1ff9a09d77422bdee55727479cafa68b Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 19 Apr 2023 07:28:40 -0400 Subject: [PATCH 40/89] One teeny tiny more thing. --- SrcMod/Shell/GlobalUsings.cs | 1 + SrcMod/Shell/Modules/ConfigModule.cs | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index 8ae847e..d5d9a6f 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -7,6 +7,7 @@ global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; global using System; +global using System.Collections; global using System.Collections.Generic; global using System.ComponentModel; global using System.Diagnostics; diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 4835833..98608c7 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -1,4 +1,6 @@ -namespace SrcMod.Shell.Modules; +using SharpCompress; + +namespace SrcMod.Shell.Modules; [Module("config")] public static class ConfigModule @@ -139,19 +141,27 @@ public static class ConfigModule Write(new string(' ', indents * 4), newLine: false); if (!string.IsNullOrWhiteSpace(name)) Write($"{name}: ", newLine: false); - if (item is Array itemArray) + if (item is IEnumerable itemEnumerable) { - if (itemArray.Length < 1) + // This is a bit inefficient. + int count = 0; + foreach (object _ in itemEnumerable) count++; + + object[] itemData = new object[count]; + count = 0; + foreach (object obj in itemEnumerable) itemData[count] = obj; + + if (itemData.Length < 1) { Write("[]", ConsoleColor.DarkGray, newLine); return; } Write("[", ConsoleColor.DarkGray); - for (int i = 0; i < itemArray.Length; i++) + for (int i = 0; i < itemData.Length; i++) { - DisplayConfigItem(itemArray.GetValue(i), indents + 1, newLine: false); - if (i < itemArray.Length - 1) Write(',', newLine: false); + DisplayConfigItem(itemData.GetValue(i), indents + 1, newLine: false); + if (i < itemData.Length - 1) Write(',', newLine: false); Write('\n', newLine: false); } Write(new string(' ', indents * 4) + "]", ConsoleColor.DarkGray, newLine); -- 2.49.0.windows.1 From dd62e66871cab8c55670cba34b2c7b2d27f91c5a Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 19 Apr 2023 14:02:23 -0400 Subject: [PATCH 41/89] Added automated config setting. Next up resetting. --- SrcMod/Shell/Modules/ConfigModule.cs | 38 +++++++++------------- SrcMod/Shell/ObjectModels/Config.cs | 30 ++++++++++++----- SrcMod/Shell/ObjectModels/ConfigChanges.cs | 2 +- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 98608c7..ffc5ca0 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -97,32 +97,24 @@ public static class ConfigModule [Command("set")] public static void SetConfigVariable(string name, string value) { - Config config = Config.LoadedConfig; + FieldInfo[] validFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); - switch (name.Trim().ToLower()) - { - case "gamedirectories": - throw new($"The config variable \"{name}\" is a list and must be added or removed to."); + FieldInfo? chosenField = validFields.FirstOrDefault(x => x.Name.Trim().ToLower() == name.Trim().ToLower()); + if (chosenField is null) throw new($"No valid config variable named \"{name}\"."); + else if (chosenField.FieldType.IsArray) throw new($"The variable \"{name}\" is an array and cannot be" + + " directly set. Instead, add or remove items from it."); - case "rununsafecommands": - if (int.TryParse(value, out int intRes)) - { - AskMode mode = (AskMode)intRes; - if (!Enum.IsDefined(mode)) throw new($"(AskMode){value} is not a valid AskMode."); - config.RunUnsafeCommands = mode; - } - else if (Enum.TryParse(value, true, out AskMode modeRes)) - { - if (!Enum.IsDefined(modeRes)) throw new($"\"{value}\" is not a valid AskMode."); - config.RunUnsafeCommands = modeRes; - } - else throw new($"\"{value}\" is not a valid AskMode."); - break; + object parsed = TypeParsers.ParseAll(value); + if (parsed is string parsedStr + && chosenField.FieldType.IsEnum + && Enum.TryParse(chosenField.FieldType, parsedStr, true, out object? obj)) parsed = obj; - default: throw new($"Unknown config variable \"{name}\""); - } - - Config.LoadedConfig = config; + chosenField.SetValue(Config.LoadedConfig, parsed); + DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } private static void DisplayConfigAll() diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index f66f5e7..0c272f8 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell.ObjectModels; -public struct Config +public class Config { public const string FilePath = "config.json"; @@ -26,16 +26,26 @@ public struct Config GameDirectories = Array.Empty(), RunUnsafeCommands = AskMode.Ask }; + p_applied = Defaults; } public string[] GameDirectories; public AskMode RunUnsafeCommands; - public Config ApplyChanges(ConfigChanges changes) => this with + internal Config() { - GameDirectories = GameDirectories.Union(changes.GameDirectories ?? Array.Empty()).ToArray(), - RunUnsafeCommands = changes.RunUnsafeCommands ?? RunUnsafeCommands - }; + GameDirectories = Array.Empty(); + } + + public Config ApplyChanges(ConfigChanges changes) + { + if (changes.GameDirectories is not null) + GameDirectories = GameDirectories.Union(changes.GameDirectories).ToArray(); + + if (changes.RunUnsafeCommands is not null) RunUnsafeCommands = changes.RunUnsafeCommands.Value; + + return this; + } public ConfigChanges GetChanges(Config? baseConfig = null) { Config reference = baseConfig ?? Defaults; @@ -65,21 +75,23 @@ public struct Config jsonReader.Close(); reader.Close(); - p_applied = p_changes is null ? Defaults : Defaults.ApplyChanges(p_changes.Value); + p_applied = p_changes is null ? Defaults : Defaults.ApplyChanges(p_changes); } public static void SaveConfig(string basePath) { string fullPath = Path.Combine(basePath, FilePath); - if (p_changes is null || !p_changes.Value.HasChange) + if (p_changes is null || !p_changes.HasChange) { if (File.Exists(fullPath)) File.Delete(fullPath); return; } StreamWriter writer = new(fullPath); - JsonTextWriter jsonWriter = new(writer); - jsonWriter.Indentation = 4; + JsonTextWriter jsonWriter = new(writer) + { + Indentation = 4 + }; Serializer.Serialize(jsonWriter, p_changes); jsonWriter.Close(); writer.Close(); diff --git a/SrcMod/Shell/ObjectModels/ConfigChanges.cs b/SrcMod/Shell/ObjectModels/ConfigChanges.cs index 8328796..e527d5f 100644 --- a/SrcMod/Shell/ObjectModels/ConfigChanges.cs +++ b/SrcMod/Shell/ObjectModels/ConfigChanges.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell.ObjectModels; -public record struct ConfigChanges +public record class ConfigChanges { [JsonIgnore] public bool HasChange => GameDirectories is not null || RunUnsafeCommands is not null; -- 2.49.0.windows.1 From b5517e724ae8ce9b76efb5f99efd25b3f4dab674 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 19 Apr 2023 19:28:30 -0400 Subject: [PATCH 42/89] Added automatic config resetting capabilities. --- SrcMod/Shell/Modules/ConfigModule.cs | 34 ++++++++++++++++------------ SrcMod/Shell/ObjectModels/Config.cs | 6 +++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index ffc5ca0..0977a3e 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -72,26 +72,17 @@ public static class ConfigModule [Command("reset")] public static void ResetConfig(string name = "all") { - Config config = Config.LoadedConfig; - switch (name.Trim().ToLower()) { - case "gamedirectories": - config.GameDirectories = Config.Defaults.GameDirectories; - break; - - case "rununsafecommands": - config.RunUnsafeCommands = Config.Defaults.RunUnsafeCommands; - break; - case "all": - config = Config.Defaults; + Config.LoadedConfig = Config.Defaults; + DisplayConfig("all"); break; - default: throw new($"Unknown config variable \"{name}\""); + default: + ResetConfigVar(name); + break; } - - Config.LoadedConfig = config; } [Command("set")] @@ -200,4 +191,19 @@ public static class ConfigModule string json = JsonConvert.SerializeObject(Config.LoadedConfig, Formatting.Indented); Write(json); } + + private static void ResetConfigVar(string name) + { + FieldInfo[] validFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); + + FieldInfo? chosenField = validFields.FirstOrDefault(x => x.Name.Trim().ToLower() == name.Trim().ToLower()); + if (chosenField is null) throw new($"No valid config variable named \"{name}\"."); + + chosenField.SetValue(Config.LoadedConfig, chosenField.GetValue(Config.Defaults)); + DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); + } } diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 0c272f8..e3cba13 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -4,7 +4,7 @@ public class Config { public const string FilePath = "config.json"; - public static readonly Config Defaults; + public static Config Defaults => (Config)p_defaults.MemberwiseClone(); public static Config LoadedConfig { @@ -19,9 +19,11 @@ public class Config private static Config p_applied; private static ConfigChanges? p_changes; + private static readonly Config p_defaults; + static Config() { - Defaults = new() + p_defaults = new() { GameDirectories = Array.Empty(), RunUnsafeCommands = AskMode.Ask -- 2.49.0.windows.1 From 2420e16fa40f61bd19c84cc2453fa8af1802419a Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 19 Apr 2023 20:37:54 -0400 Subject: [PATCH 43/89] Made the config append system fully automated. --- .../Shell/Extensions/ConversionExtension.cs | 20 +++++++ SrcMod/Shell/GlobalUsings.cs | 1 + SrcMod/Shell/Modules/ConfigModule.cs | 55 ++++++++++--------- SrcMod/Shell/Shell.csproj | 4 ++ 4 files changed, 54 insertions(+), 26 deletions(-) create mode 100644 SrcMod/Shell/Extensions/ConversionExtension.cs diff --git a/SrcMod/Shell/Extensions/ConversionExtension.cs b/SrcMod/Shell/Extensions/ConversionExtension.cs new file mode 100644 index 0000000..599c6ea --- /dev/null +++ b/SrcMod/Shell/Extensions/ConversionExtension.cs @@ -0,0 +1,20 @@ +namespace SrcMod.Shell.Extensions; + +public static class ConversionExtension +{ + public static T Cast(this object obj) => (T)Cast(obj, typeof(T)); + public static object Cast(this object obj, Type newType) => Convert.ChangeType(obj, newType); + + public static object CastArray(this object[] obj, Type newElementType) + { + Array result = Array.CreateInstance(newElementType, obj.Length); + for (int i = 0; i < obj.Length; i++) result.SetValue(obj[i].Cast(newElementType), i); + return result; + } + public static T[] CastArray(this object[] obj) + { + Array result = Array.CreateInstance(typeof(T), obj.Length); + for (int i = 0; i < obj.Length; i++) result.SetValue(obj[i].Cast(), i); + return (T[])result; + } +} diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index d5d9a6f..19bbcbb 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -3,6 +3,7 @@ global using Newtonsoft.Json; global using SharpCompress.Archives.Rar; global using SharpCompress.Archives.SevenZip; global using SharpCompress.Readers; +global using SrcMod.Shell.Extensions; global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 0977a3e..cea4cba 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -29,21 +29,30 @@ public static class ConfigModule [Command("append")] public static void AppendConfigVariable(string name, string value) { - Config config = Config.LoadedConfig; + FieldInfo[] validFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); - switch (name.Trim().ToLower()) - { - case "gamedirectories": - config.GameDirectories = config.GameDirectories.Append(value).ToArray(); - break; + FieldInfo? chosenField = validFields.FirstOrDefault(x => x.Name.Trim().ToLower() == name.Trim().ToLower()); + if (chosenField is null) throw new($"No valid config variable named \"{name}\"."); + else if (!chosenField.FieldType.IsArray) throw new($"The variable \"{chosenField.Name}\" is not an array" + + " and cannot have data added or removed from it." + + " Instead, set or reset the variable."); - case "rununsafecommands": - throw new($"The config variable \"{name}\" is a single variable and cannot be appended to."); + object parsed = TypeParsers.ParseAll(value); + if (parsed is string parsedStr + && chosenField.FieldType.IsEnum + && Enum.TryParse(chosenField.FieldType, parsedStr, true, out object? obj)) parsed = obj; - default: throw new($"Unknown config variable \"{name}\""); - } + Type arrayType = chosenField.FieldType.GetElementType()!; - Config.LoadedConfig = config; + Array arrayValue = (Array)chosenField.GetValue(Config.LoadedConfig)!; + ArrayList collection = new(arrayValue) { parsed }; + + chosenField.SetValue(Config.LoadedConfig, collection.ToArray()!.CastArray(arrayType)); + DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } [Command("delete")] @@ -96,8 +105,9 @@ public static class ConfigModule FieldInfo? chosenField = validFields.FirstOrDefault(x => x.Name.Trim().ToLower() == name.Trim().ToLower()); if (chosenField is null) throw new($"No valid config variable named \"{name}\"."); - else if (chosenField.FieldType.IsArray) throw new($"The variable \"{name}\" is an array and cannot be" + - " directly set. Instead, add or remove items from it."); + else if (chosenField.FieldType.IsArray) throw new($"The variable \"{chosenField.Name}\" is an array and" + + " cannot be directly set. Instead, add or remove items" + + " from it."); object parsed = TypeParsers.ParseAll(value); if (parsed is string parsedStr @@ -124,27 +134,20 @@ public static class ConfigModule Write(new string(' ', indents * 4), newLine: false); if (!string.IsNullOrWhiteSpace(name)) Write($"{name}: ", newLine: false); - if (item is IEnumerable itemEnumerable) + if (item is null) Write("null", ConsoleColor.DarkRed, newLine); + else if (item is Array itemArray) { - // This is a bit inefficient. - int count = 0; - foreach (object _ in itemEnumerable) count++; - - object[] itemData = new object[count]; - count = 0; - foreach (object obj in itemEnumerable) itemData[count] = obj; - - if (itemData.Length < 1) + if (itemArray.Length < 1) { Write("[]", ConsoleColor.DarkGray, newLine); return; } Write("[", ConsoleColor.DarkGray); - for (int i = 0; i < itemData.Length; i++) + for (int i = 0; i < itemArray.Length; i++) { - DisplayConfigItem(itemData.GetValue(i), indents + 1, newLine: false); - if (i < itemData.Length - 1) Write(',', newLine: false); + DisplayConfigItem(itemArray.GetValue(i), indents + 1, newLine: false); + if (i < itemArray.Length - 1) Write(',', newLine: false); Write('\n', newLine: false); } Write(new string(' ', indents * 4) + "]", ConsoleColor.DarkGray, newLine); diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index 253835f..804ac4f 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -36,4 +36,8 @@ + + + + -- 2.49.0.windows.1 From b446feefe759b74ab60597b67095ca55d845ce4a Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 20 Apr 2023 07:27:38 -0400 Subject: [PATCH 44/89] Made the config remove system automated. --- SrcMod/Shell/Modules/ConfigModule.cs | 35 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index cea4cba..25838ad 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -59,23 +59,32 @@ public static class ConfigModule [Command("remove")] public static void RemoveConfigVariable(string name, string value) { - Config config = Config.LoadedConfig; + FieldInfo[] validFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); - switch (name.Trim().ToLower()) - { - case "gamedirectories": - config.GameDirectories = config.GameDirectories - .Where(x => x.Trim().ToLower() != value.Trim().ToLower()) - .ToArray(); - break; + FieldInfo? chosenField = validFields.FirstOrDefault(x => x.Name.Trim().ToLower() == name.Trim().ToLower()); + if (chosenField is null) throw new($"No valid config variable named \"{name}\"."); + else if (!chosenField.FieldType.IsArray) throw new($"The variable \"{chosenField.Name}\" is not an array" + + " and cannot have data added or removed from it." + + " Instead, set or reset the variable."); - case "rununsafecommands": - throw new($"The config variable \"{name}\" is a single variable and cannot be appended to."); + object parsed = TypeParsers.ParseAll(value); + if (parsed is string parsedStr + && chosenField.FieldType.IsEnum + && Enum.TryParse(chosenField.FieldType, parsedStr, true, out object? obj)) parsed = obj; - default: throw new($"Unknown config variable \"{name}\""); - } + Type arrayType = chosenField.FieldType.GetElementType()!; - Config.LoadedConfig = config; + Array arrayValue = (Array)chosenField.GetValue(Config.LoadedConfig)!; + ArrayList collection = new(arrayValue); + if (!collection.Contains(parsed)) throw new($"The value \"{value}\" is not contained in this variable."); + collection.Remove(parsed); + + chosenField.SetValue(Config.LoadedConfig, collection.ToArray()!.CastArray(arrayType)); + DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } [Command("reset")] -- 2.49.0.windows.1 From 35885b8724d3ea5c4daa8350b6de6080c853dcbe Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 20 Apr 2023 08:20:18 -0400 Subject: [PATCH 45/89] Fixed the config not saving to its file. --- SrcMod/Shell/Modules/ConfigModule.cs | 4 +++ SrcMod/Shell/ObjectModels/Config.cs | 37 +++++++++++++--------- SrcMod/Shell/ObjectModels/ConfigChanges.cs | 10 ------ 3 files changed, 26 insertions(+), 25 deletions(-) delete mode 100644 SrcMod/Shell/ObjectModels/ConfigChanges.cs diff --git a/SrcMod/Shell/Modules/ConfigModule.cs b/SrcMod/Shell/Modules/ConfigModule.cs index 25838ad..27bb4bc 100644 --- a/SrcMod/Shell/Modules/ConfigModule.cs +++ b/SrcMod/Shell/Modules/ConfigModule.cs @@ -52,6 +52,7 @@ public static class ConfigModule ArrayList collection = new(arrayValue) { parsed }; chosenField.SetValue(Config.LoadedConfig, collection.ToArray()!.CastArray(arrayType)); + Config.UpdateChanges(); DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } @@ -84,6 +85,7 @@ public static class ConfigModule collection.Remove(parsed); chosenField.SetValue(Config.LoadedConfig, collection.ToArray()!.CastArray(arrayType)); + Config.UpdateChanges(); DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } @@ -124,6 +126,7 @@ public static class ConfigModule && Enum.TryParse(chosenField.FieldType, parsedStr, true, out object? obj)) parsed = obj; chosenField.SetValue(Config.LoadedConfig, parsed); + Config.UpdateChanges(); DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } @@ -216,6 +219,7 @@ public static class ConfigModule if (chosenField is null) throw new($"No valid config variable named \"{name}\"."); chosenField.SetValue(Config.LoadedConfig, chosenField.GetValue(Config.Defaults)); + Config.UpdateChanges(); DisplayConfigItem(chosenField.GetValue(Config.LoadedConfig), name: chosenField.Name); } } diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index e3cba13..60d1e90 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -4,7 +4,7 @@ public class Config { public const string FilePath = "config.json"; - public static Config Defaults => (Config)p_defaults.MemberwiseClone(); + public static Config Defaults => new(); public static Config LoadedConfig { @@ -12,22 +12,15 @@ public class Config set { p_applied = value; - p_changes = p_applied.GetChanges(Defaults); + UpdateChanges(); } } private static Config p_applied; - private static ConfigChanges? p_changes; - - private static readonly Config p_defaults; + private static Changes? p_changes; static Config() { - p_defaults = new() - { - GameDirectories = Array.Empty(), - RunUnsafeCommands = AskMode.Ask - }; p_applied = Defaults; } @@ -37,9 +30,10 @@ public class Config internal Config() { GameDirectories = Array.Empty(); + RunUnsafeCommands = AskMode.Ask; } - public Config ApplyChanges(ConfigChanges changes) + public Config ApplyChanges(Changes changes) { if (changes.GameDirectories is not null) GameDirectories = GameDirectories.Union(changes.GameDirectories).ToArray(); @@ -48,10 +42,10 @@ public class Config return this; } - public ConfigChanges GetChanges(Config? baseConfig = null) + public Changes GetChanges(Config? baseConfig = null) { Config reference = baseConfig ?? Defaults; - ConfigChanges changes = new() + Changes changes = new() { GameDirectories = reference.GameDirectories == GameDirectories ? null : GameDirectories.Where(x => !reference.GameDirectories.Contains(x)).ToArray(), @@ -73,7 +67,7 @@ public class Config } StreamReader reader = new(fullPath); JsonTextReader jsonReader = new(reader); - p_changes = Serializer.Deserialize(jsonReader); + p_changes = Serializer.Deserialize(jsonReader); jsonReader.Close(); reader.Close(); @@ -83,7 +77,7 @@ public class Config { string fullPath = Path.Combine(basePath, FilePath); - if (p_changes is null || !p_changes.HasChange) + if (p_changes is null || !p_changes.Any()) { if (File.Exists(fullPath)) File.Delete(fullPath); return; @@ -98,4 +92,17 @@ public class Config jsonWriter.Close(); writer.Close(); } + + public static void UpdateChanges() + { + p_changes = p_applied.GetChanges(Defaults); + } + + public class Changes + { + public string[]? GameDirectories; + public AskMode? RunUnsafeCommands; + + public bool Any() => typeof(Changes).GetFields().Any(x => x.GetValue(this) is not null); + } } diff --git a/SrcMod/Shell/ObjectModels/ConfigChanges.cs b/SrcMod/Shell/ObjectModels/ConfigChanges.cs deleted file mode 100644 index e527d5f..0000000 --- a/SrcMod/Shell/ObjectModels/ConfigChanges.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SrcMod.Shell.ObjectModels; - -public record class ConfigChanges -{ - [JsonIgnore] - public bool HasChange => GameDirectories is not null || RunUnsafeCommands is not null; - - public string[]? GameDirectories; - public AskMode? RunUnsafeCommands; -} -- 2.49.0.windows.1 From d8df50a928ac94e4929aaf6bb7fa4dda5aa46552 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Mon, 24 Apr 2023 17:33:51 -0400 Subject: [PATCH 46/89] Tiny change. --- SrcMod/Shell/LoadingBar.cs | 2 +- SrcMod/Shell/Tools.cs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/SrcMod/Shell/LoadingBar.cs b/SrcMod/Shell/LoadingBar.cs index f658c8e..b4102e8 100644 --- a/SrcMod/Shell/LoadingBar.cs +++ b/SrcMod/Shell/LoadingBar.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell; -internal static class LoadingBar +public static class LoadingBar { public static int position = -1; public static int bufferSize = 0; diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index ef6cc12..34c63b5 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -1,8 +1,6 @@ -using System.Text; +namespace SrcMod.Shell; -namespace SrcMod.Shell; - -internal static class Tools +public static class Tools { public static void DisplayWithPages(IEnumerable lines, ConsoleColor? color = null) { -- 2.49.0.windows.1 From 2dc37cd6accbda656fd2829431a931bd6f62d52b Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 25 Apr 2023 17:19:07 -0400 Subject: [PATCH 47/89] Debug mode gives better errors now (tiny patch) --- SrcMod/Shell/Shell.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 58cd52e..161cfa0 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -237,24 +237,27 @@ public class Shell void runCommand(object? sender, DoWorkEventArgs e) { -#if RELEASE try { -#endif command.Invoke(args); -#if RELEASE } +#if RELEASE catch (TargetInvocationException ex) { Write($"[ERROR] {ex.InnerException!.Message}", ConsoleColor.Red); if (LoadingBar.Enabled) LoadingBar.End(); } +#endif catch (Exception ex) { +#if RELEASE Write($"[ERROR] {ex.Message}", ConsoleColor.Red); if (LoadingBar.Enabled) LoadingBar.End(); - } +#else + Write($"[ERROR] {ex}", ConsoleColor.Red); + if (LoadingBar.Enabled) LoadingBar.End(); #endif + } } activeCommand = new(); -- 2.49.0.windows.1 From 2e61bcfbec911f0aa69f375dd00407e2fbf98d87 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 25 Apr 2023 17:27:14 -0400 Subject: [PATCH 48/89] Automated as much of the config system as possible. --- .../Shell/Extensions/ConversionExtension.cs | 13 +++ SrcMod/Shell/ObjectModels/Config.cs | 85 ++++++++++++++++--- SrcMod/Shell/Shell.csproj | 4 - 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/SrcMod/Shell/Extensions/ConversionExtension.cs b/SrcMod/Shell/Extensions/ConversionExtension.cs index 599c6ea..72a8e95 100644 --- a/SrcMod/Shell/Extensions/ConversionExtension.cs +++ b/SrcMod/Shell/Extensions/ConversionExtension.cs @@ -17,4 +17,17 @@ public static class ConversionExtension for (int i = 0; i < obj.Length; i++) result.SetValue(obj[i].Cast(), i); return (T[])result; } + + public static object CastArray(this Array obj, Type newElementType) + { + Array result = Array.CreateInstance(newElementType, obj.Length); + for (int i = 0; i < obj.Length; i++) result.SetValue(obj.GetValue(i)!.Cast(newElementType), i); + return result; + } + public static T[] CastArray(this Array obj) + { + Array result = Array.CreateInstance(typeof(T), obj.Length); + for (int i = 0; i < obj.Length; i++) result.SetValue(obj.GetValue(i)!.Cast(), i); + return (T[])result; + } } diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 60d1e90..197b7e6 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -6,6 +6,9 @@ public class Config public static Config Defaults => new(); + private static readonly FieldInfo[] p_configSharedFields; + private static readonly FieldInfo[] p_changeSharedFields; + public static Config LoadedConfig { get => p_applied; @@ -22,6 +25,39 @@ public class Config static Config() { p_applied = Defaults; + + FieldInfo[] configFields = (from field in typeof(Config).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(), + changeFields = (from field in typeof(Changes).GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + where isPublic && !isStatic + select field).ToArray(); + + List sharedConfigFields = new(), + sharedChangeFields = new(); + foreach (FieldInfo field in configFields) + { + FieldInfo? changeEquivalent = changeFields.FirstOrDefault( + x => x.Name == field.Name && + (x.FieldType == field.FieldType || Nullable.GetUnderlyingType(x.FieldType) == field.FieldType)); + + if (changeEquivalent is null) continue; + + sharedConfigFields.Add(field); + sharedChangeFields.Add(changeEquivalent); + } + + static int sortByName(FieldInfo a, FieldInfo b) => a.Name.CompareTo(b.Name); + + sharedConfigFields.Sort(sortByName); + sharedChangeFields.Sort(sortByName); + + p_configSharedFields = sharedConfigFields.ToArray(); + p_changeSharedFields = sharedChangeFields.ToArray(); } public string[] GameDirectories; @@ -35,22 +71,51 @@ public class Config public Config ApplyChanges(Changes changes) { - if (changes.GameDirectories is not null) - GameDirectories = GameDirectories.Union(changes.GameDirectories).ToArray(); + for (int i = 0; i < p_configSharedFields.Length; i++) + { + FieldInfo configField = p_configSharedFields[i], + changeField = p_changeSharedFields[i]; - if (changes.RunUnsafeCommands is not null) RunUnsafeCommands = changes.RunUnsafeCommands.Value; + object? toChange = changeField.GetValue(changes); + + if (toChange is null) continue; + + if (configField.FieldType.IsArray) + { + object[] currentArray = ((Array)configField.GetValue(this)!).CastArray(), + changeArray = ((Array)toChange).CastArray(); + + currentArray = currentArray.Union(changeArray).ToArray(); + configField.SetValue(this, currentArray.CastArray(configField.FieldType.GetElementType()!)); + } + else configField.SetValue(this, toChange); + } return this; } - public Changes GetChanges(Config? baseConfig = null) + public Changes GetChanges(Config? reference = null) { - Config reference = baseConfig ?? Defaults; - Changes changes = new() + reference ??= Defaults; + Changes changes = new(); + + for (int i = 0; i < p_configSharedFields.Length; i++) { - GameDirectories = reference.GameDirectories == GameDirectories ? null : - GameDirectories.Where(x => !reference.GameDirectories.Contains(x)).ToArray(), - RunUnsafeCommands = reference.RunUnsafeCommands == RunUnsafeCommands ? null : RunUnsafeCommands - }; + FieldInfo configField = p_configSharedFields[i], + changeField = p_changeSharedFields[i]; + + object? toSet = configField.GetValue(this); + + if (toSet is null) continue; + + if (configField.FieldType.IsArray) + { + object[] configArray = ((Array)toSet).CastArray(), + referenceArray = ((Array)configField.GetValue(Defaults)!).CastArray(), + changesArray = configArray.Where(x => !referenceArray.Contains(x)).ToArray(); + changeField.SetValue(changes, changesArray.CastArray(configField.FieldType.GetElementType()!)); + } + else changeField.SetValue(changes, toSet); + } return changes; } diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index 804ac4f..253835f 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -36,8 +36,4 @@ - - - - -- 2.49.0.windows.1 From a0c50c4cabb1d41fe58570a2141022e04b4c5951 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 25 Apr 2023 17:42:02 -0400 Subject: [PATCH 49/89] Changed version to 0.4.0 --- SrcMod/Shell/Shell.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 372d084..7fe1d15 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.3.3"; + public const string Version = "Alpha 0.4.0"; public readonly string? ShellDirectory; -- 2.49.0.windows.1 From 864c39be7f5eb8c74e0f9457af4a5a201f74efe2 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 26 Apr 2023 09:49:01 -0400 Subject: [PATCH 50/89] Tiny change. New testing module (for me obviously). --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 955d082..6671a1c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ SrcMod/Compiled SrcMod/Shell/obj/ # Personal Stuff +SrcMod/Shell/Modules/TestingModule.cs TODO.md -- 2.49.0.windows.1 From 4d64b0bae6938c7a4624ac1a96ff6959e39a57c9 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 26 Apr 2023 14:09:28 -0400 Subject: [PATCH 51/89] Small starts on the serializer. --- SrcMod/Shell/Valve/KeyValueConvert.cs | 30 +++++++++++++++++ SrcMod/Shell/Valve/KeyValueNode.cs | 18 +++++++++++ SrcMod/Shell/Valve/KeyValueSerializer.cs | 41 ++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 SrcMod/Shell/Valve/KeyValueConvert.cs create mode 100644 SrcMod/Shell/Valve/KeyValueNode.cs create mode 100644 SrcMod/Shell/Valve/KeyValueSerializer.cs diff --git a/SrcMod/Shell/Valve/KeyValueConvert.cs b/SrcMod/Shell/Valve/KeyValueConvert.cs new file mode 100644 index 0000000..a52b2fe --- /dev/null +++ b/SrcMod/Shell/Valve/KeyValueConvert.cs @@ -0,0 +1,30 @@ +namespace SrcMod.Shell.Valve; + +public static class KeyValueConvert +{ + private static readonly Dictionary p_escapeCodes = new() + { + { "\'", "\\\'" }, + { "\"", "\\\"" }, + { "\\", "\\\\" }, + { "\0", "\\\0" }, + { "\a", "\\\a" }, + { "\b", "\\\b" }, + { "\f", "\\\f" }, + { "\n", "\\\n" }, + { "\r", "\\\r" }, + { "\t", "\\\t" }, + { "\v", "\\\v" } + }; + + public static string SerializeName(string content, KeyValueSerializer.Options? options = null) + { + options ??= KeyValueSerializer.Options.Default; + if (options.useNameQuotes) content = $"\"{content}\""; + if (options.useEscapeCodes) + foreach (KeyValuePair escapeCode in p_escapeCodes) + content = content.Replace(escapeCode.Key, escapeCode.Value); + + return content; + } +} diff --git a/SrcMod/Shell/Valve/KeyValueNode.cs b/SrcMod/Shell/Valve/KeyValueNode.cs new file mode 100644 index 0000000..5d88f77 --- /dev/null +++ b/SrcMod/Shell/Valve/KeyValueNode.cs @@ -0,0 +1,18 @@ +namespace SrcMod.Shell.Valve; + +public class KeyValueNode +{ + public int SubNodeCount => p_subNodes.Count; + + public object value; + + private Dictionary p_subNodes; + + internal KeyValueNode() + { + value = new(); + p_subNodes = new(); + } + + public KeyValueNode this[string name] => p_subNodes[name]; +} diff --git a/SrcMod/Shell/Valve/KeyValueSerializer.cs b/SrcMod/Shell/Valve/KeyValueSerializer.cs new file mode 100644 index 0000000..399ac4a --- /dev/null +++ b/SrcMod/Shell/Valve/KeyValueSerializer.cs @@ -0,0 +1,41 @@ +namespace SrcMod.Shell.Valve; + +public class KeyValueSerializer +{ + public int? IndentSize => p_options.indentSize; + public bool UseEscapeCodes => p_options.useEscapeCodes; + public bool UseNameQuotes => p_options.useNameQuotes; + public bool UseValueQuotes => p_options.useValueQuotes; + + private readonly Options p_options; + + public KeyValueSerializer() : this(Options.Default) { } + public KeyValueSerializer(Options options) + { + p_options = options; + } + + public StringBuilder Serialize(StringBuilder builder, KeyValueNode parentNode, string? parentNodeName = null) + { + if (parentNodeName is not null) builder.AppendLine(KeyValueConvert.SerializeName(parentNodeName, p_options)); + return builder; + } + + public record class Options + { + public static Options Default => new(); + + public int? indentSize; + public bool useEscapeCodes; + public bool useNameQuotes; + public bool useValueQuotes; + + public Options() + { + indentSize = null; + useEscapeCodes = false; + useNameQuotes = true; + useValueQuotes = false; + } + } +} -- 2.49.0.windows.1 From 4e2a8ec05ce97b00f75e07543f127fa034546b03 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Wed, 26 Apr 2023 20:38:28 -0400 Subject: [PATCH 52/89] Some development with the serializer. --- SrcMod/Shell/GlobalUsings.cs | 1 + SrcMod/Shell/Valve/KeyValueConvert.cs | 30 ------------ SrcMod/Shell/Valve/KeyValueNode.cs | 18 -------- SrcMod/Shell/Valve/KeyValueSerializer.cs | 41 ----------------- SrcMod/Shell/Valve/VdfConvert.cs | 58 ++++++++++++++++++++++++ SrcMod/Shell/Valve/VdfNode.cs | 6 +++ SrcMod/Shell/Valve/VdfOptions.cs | 19 ++++++++ SrcMod/Shell/Valve/VdfSerializer.cs | 21 +++++++++ SrcMod/Shell/Valve/VdfSingleNode.cs | 11 +++++ SrcMod/Shell/Valve/VdfTreeNode.cs | 32 +++++++++++++ 10 files changed, 148 insertions(+), 89 deletions(-) delete mode 100644 SrcMod/Shell/Valve/KeyValueConvert.cs delete mode 100644 SrcMod/Shell/Valve/KeyValueNode.cs delete mode 100644 SrcMod/Shell/Valve/KeyValueSerializer.cs create mode 100644 SrcMod/Shell/Valve/VdfConvert.cs create mode 100644 SrcMod/Shell/Valve/VdfNode.cs create mode 100644 SrcMod/Shell/Valve/VdfOptions.cs create mode 100644 SrcMod/Shell/Valve/VdfSerializer.cs create mode 100644 SrcMod/Shell/Valve/VdfSingleNode.cs create mode 100644 SrcMod/Shell/Valve/VdfTreeNode.cs diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index 19bbcbb..a30eee1 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -7,6 +7,7 @@ global using SrcMod.Shell.Extensions; global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; +global using SrcMod.Shell.Valve; global using System; global using System.Collections; global using System.Collections.Generic; diff --git a/SrcMod/Shell/Valve/KeyValueConvert.cs b/SrcMod/Shell/Valve/KeyValueConvert.cs deleted file mode 100644 index a52b2fe..0000000 --- a/SrcMod/Shell/Valve/KeyValueConvert.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace SrcMod.Shell.Valve; - -public static class KeyValueConvert -{ - private static readonly Dictionary p_escapeCodes = new() - { - { "\'", "\\\'" }, - { "\"", "\\\"" }, - { "\\", "\\\\" }, - { "\0", "\\\0" }, - { "\a", "\\\a" }, - { "\b", "\\\b" }, - { "\f", "\\\f" }, - { "\n", "\\\n" }, - { "\r", "\\\r" }, - { "\t", "\\\t" }, - { "\v", "\\\v" } - }; - - public static string SerializeName(string content, KeyValueSerializer.Options? options = null) - { - options ??= KeyValueSerializer.Options.Default; - if (options.useNameQuotes) content = $"\"{content}\""; - if (options.useEscapeCodes) - foreach (KeyValuePair escapeCode in p_escapeCodes) - content = content.Replace(escapeCode.Key, escapeCode.Value); - - return content; - } -} diff --git a/SrcMod/Shell/Valve/KeyValueNode.cs b/SrcMod/Shell/Valve/KeyValueNode.cs deleted file mode 100644 index 5d88f77..0000000 --- a/SrcMod/Shell/Valve/KeyValueNode.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace SrcMod.Shell.Valve; - -public class KeyValueNode -{ - public int SubNodeCount => p_subNodes.Count; - - public object value; - - private Dictionary p_subNodes; - - internal KeyValueNode() - { - value = new(); - p_subNodes = new(); - } - - public KeyValueNode this[string name] => p_subNodes[name]; -} diff --git a/SrcMod/Shell/Valve/KeyValueSerializer.cs b/SrcMod/Shell/Valve/KeyValueSerializer.cs deleted file mode 100644 index 399ac4a..0000000 --- a/SrcMod/Shell/Valve/KeyValueSerializer.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace SrcMod.Shell.Valve; - -public class KeyValueSerializer -{ - public int? IndentSize => p_options.indentSize; - public bool UseEscapeCodes => p_options.useEscapeCodes; - public bool UseNameQuotes => p_options.useNameQuotes; - public bool UseValueQuotes => p_options.useValueQuotes; - - private readonly Options p_options; - - public KeyValueSerializer() : this(Options.Default) { } - public KeyValueSerializer(Options options) - { - p_options = options; - } - - public StringBuilder Serialize(StringBuilder builder, KeyValueNode parentNode, string? parentNodeName = null) - { - if (parentNodeName is not null) builder.AppendLine(KeyValueConvert.SerializeName(parentNodeName, p_options)); - return builder; - } - - public record class Options - { - public static Options Default => new(); - - public int? indentSize; - public bool useEscapeCodes; - public bool useNameQuotes; - public bool useValueQuotes; - - public Options() - { - indentSize = null; - useEscapeCodes = false; - useNameQuotes = true; - useValueQuotes = false; - } - } -} diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs new file mode 100644 index 0000000..5c64cda --- /dev/null +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -0,0 +1,58 @@ +namespace SrcMod.Shell.Valve; + +interface static class VdfConvert +{ + private static readonly Dictionary p_escapeCodes = new() + { + { "\'", "\\\'" }, + { "\"", "\\\"" }, + { "\\", "\\\\" }, + { "\0", "\\\0" }, + { "\a", "\\\a" }, + { "\b", "\\\b" }, + { "\f", "\\\f" }, + { "\n", "\\\n" }, + { "\r", "\\\r" }, + { "\t", "\\\t" }, + { "\v", "\\\v" } + }; + + public static void SerializeNode(StreamWriter writer, VdfNode node, string name, + ref VdfOptions options, int indentLevel) + { + if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, ref options, indentLevel); + else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, ref options, indentLevel); + else throw new("Unknown node type."); + } + + private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name, + ref VdfOptions options, int indentLevel) + { + string serializedName = SerializeString(name, ref options), + serializedValue = SerializeObject(node.value, ref options); + writer.WriteLine($"{new string(' ', indentLevel)}{serializedName} {serializedValue}"); + } + private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, + ref VdfOptions options, int indentLevel) + { + string serializedName = SerializeString(name, ref options), + serializedValue = ""; // TODO: serialize each value with a higher indent + + string indent = new(' ', indentLevel); + writer.WriteLine($"{indent}{serializedName}\n{indent}{{\n{serializedValue}\n{indent}}}"); + } + + private static string SerializeObject(object obj, ref VdfOptions options) + { + // TODO: serialize an object + return ""; + } + + private static string SerializeString(string content, ref VdfOptions options) + { + if (options.useEscapeCodes) + foreach (KeyValuePair escapeCode in p_escapeCodes) + content = content.Replace(escapeCode.Key, escapeCode.Value); + return content; + } +} diff --git a/SrcMod/Shell/Valve/VdfNode.cs b/SrcMod/Shell/Valve/VdfNode.cs new file mode 100644 index 0000000..36f3326 --- /dev/null +++ b/SrcMod/Shell/Valve/VdfNode.cs @@ -0,0 +1,6 @@ +namespace SrcMod.Shell.Valve; + +public abstract class VdfNode +{ + +} diff --git a/SrcMod/Shell/Valve/VdfOptions.cs b/SrcMod/Shell/Valve/VdfOptions.cs new file mode 100644 index 0000000..1d4fafa --- /dev/null +++ b/SrcMod/Shell/Valve/VdfOptions.cs @@ -0,0 +1,19 @@ +namespace SrcMod.Shell.Valve; + +public record class VdfOptions +{ + public static VdfOptions Default => new(); + + public bool closeWhenFinished; + public int indentSize; + public bool useEscapeCodes; + public bool useQuotes; + + public VdfOptions() + { + closeWhenFinished = true; + indentSize = 4; + useEscapeCodes = false; + useQuotes = false; + } +} diff --git a/SrcMod/Shell/Valve/VdfSerializer.cs b/SrcMod/Shell/Valve/VdfSerializer.cs new file mode 100644 index 0000000..da46265 --- /dev/null +++ b/SrcMod/Shell/Valve/VdfSerializer.cs @@ -0,0 +1,21 @@ +namespace SrcMod.Shell.Valve; + +public class VdfSerializer +{ + public VdfOptions Options => p_options; + + private VdfOptions p_options; + + public VdfSerializer() : this(VdfOptions.Default) { } + public VdfSerializer(VdfOptions options) + { + p_options = options; + } + + public void Serialize(Stream stream, VdfNode parentNode, string parentNodeName) + { + StreamWriter writer = p_options.closeWhenFinished ? new(stream) : new(stream, leaveOpen: true); + VdfConvert.SerializeNode(writer, parentNode, parentNodeName, ref p_options, 0); + writer.Close(); + } +} diff --git a/SrcMod/Shell/Valve/VdfSingleNode.cs b/SrcMod/Shell/Valve/VdfSingleNode.cs new file mode 100644 index 0000000..5e68b48 --- /dev/null +++ b/SrcMod/Shell/Valve/VdfSingleNode.cs @@ -0,0 +1,11 @@ +namespace SrcMod.Shell.Valve; + +public class VdfSingleNode : VdfNode +{ + public object value; + + public VdfSingleNode(object? value = null) : base() + { + this.value = value ?? new(); + } +} diff --git a/SrcMod/Shell/Valve/VdfTreeNode.cs b/SrcMod/Shell/Valve/VdfTreeNode.cs new file mode 100644 index 0000000..e39e8cf --- /dev/null +++ b/SrcMod/Shell/Valve/VdfTreeNode.cs @@ -0,0 +1,32 @@ +namespace SrcMod.Shell.Valve; + +public class VdfTreeNode : VdfNode +{ + public int SubNodeCount => p_subNodes.Count; + + private Dictionary p_subNodes; + + public VdfTreeNode(Dictionary? subNodes = null) : base() + { + p_subNodes = subNodes ?? new(); + } + + public VdfNode this[string key] + { + get => p_subNodes[key]; + set + { + if (p_subNodes.ContainsKey(key)) p_subNodes[key] = value; + else p_subNodes.Add(key, value); + } + } + public VdfNode this[int index] + { + get => p_subNodes.Values.ElementAt(index); + set + { + if (p_subNodes.Count >= index || index < 0) throw new IndexOutOfRangeException(); + p_subNodes[p_subNodes.Keys.ElementAt(index)] = value; + } + } +} -- 2.49.0.windows.1 From 46f4c779d2ad63b12dabfa53d3eda7b478af6857 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 27 Apr 2023 09:10:34 -0400 Subject: [PATCH 53/89] More development on the serializer. --- SrcMod/Shell/Valve/VdfConvert.cs | 73 +++++++++++++++++++---------- SrcMod/Shell/Valve/VdfOptions.cs | 2 + SrcMod/Shell/Valve/VdfSerializer.cs | 6 ++- SrcMod/Shell/Valve/VdfTreeNode.cs | 5 +- 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index 5c64cda..fa919dd 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -1,58 +1,79 @@ -namespace SrcMod.Shell.Valve; +using System.Security.Cryptography; -interface static class VdfConvert +namespace SrcMod.Shell.Valve; + +public static class VdfConvert { private static readonly Dictionary p_escapeCodes = new() { { "\'", "\\\'" }, { "\"", "\\\"" }, { "\\", "\\\\" }, - { "\0", "\\\0" }, - { "\a", "\\\a" }, - { "\b", "\\\b" }, - { "\f", "\\\f" }, - { "\n", "\\\n" }, - { "\r", "\\\r" }, - { "\t", "\\\t" }, - { "\v", "\\\v" } + { "\0", "\\0" }, + { "\a", "\\a" }, + { "\b", "\\b" }, + { "\f", "\\f" }, + { "\n", "\\n" }, + { "\r", "\\r" }, + { "\t", "\\t" }, + { "\v", "\\v" } }; public static void SerializeNode(StreamWriter writer, VdfNode node, string name, - ref VdfOptions options, int indentLevel) + VdfOptions options, int indentLevel) { - if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, ref options, indentLevel); - else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, ref options, indentLevel); + if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); + else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, options, indentLevel); else throw new("Unknown node type."); } private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name, - ref VdfOptions options, int indentLevel) + VdfOptions options, int indentLevel) { - string serializedName = SerializeString(name, ref options), - serializedValue = SerializeObject(node.value, ref options); - writer.WriteLine($"{new string(' ', indentLevel)}{serializedName} {serializedValue}"); + writer.Write(new string(' ', indentLevel)); + writer.Write(SerializeString(name, options)); + writer.Write(' '); + + string serializedValue = SerializeString(SerializeObject(node.value, options), options); + writer.WriteLine(serializedValue); } private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, - ref VdfOptions options, int indentLevel) + VdfOptions options, int indentLevel) { - string serializedName = SerializeString(name, ref options), - serializedValue = ""; // TODO: serialize each value with a higher indent + writer.Write(new string(' ', indentLevel)); + writer.WriteLine(SerializeString(name, options)); + writer.WriteLine(new string(' ', indentLevel) + '{'); - string indent = new(' ', indentLevel); - writer.WriteLine($"{indent}{serializedName}\n{indent}{{\n{serializedValue}\n{indent}}}"); + foreach (KeyValuePair subNode in node) + { + if (subNode.Value is VdfSingleNode singleSubNode && singleSubNode.value.GetType().IsArray) + { + Array array = (Array)singleSubNode.value; + Dictionary items = new(); + for (int i = 0; i < array.Length; i++) + { + object? item = array.GetValue(i); + if (item is VdfNode subNodeItem) items.Add(i.ToString(), subNodeItem); + else items.Add(i.ToString(), new VdfSingleNode(item)); + } + } + else SerializeNode(writer, subNode.Value, subNode.Key, options, indentLevel + options.indentSize); + } + + writer.WriteLine(new string(' ', indentLevel) + '}'); } - private static string SerializeObject(object obj, ref VdfOptions options) + private static string SerializeObject(object obj, VdfOptions options) { - // TODO: serialize an object - return ""; + return obj.ToString() ?? string.Empty; } - private static string SerializeString(string content, ref VdfOptions options) + private static string SerializeString(string content, VdfOptions options) { if (options.useEscapeCodes) foreach (KeyValuePair escapeCode in p_escapeCodes) content = content.Replace(escapeCode.Key, escapeCode.Value); + if (options.useQuotes) content = $"\"{content}\""; return content; } } diff --git a/SrcMod/Shell/Valve/VdfOptions.cs b/SrcMod/Shell/Valve/VdfOptions.cs index 1d4fafa..2287658 100644 --- a/SrcMod/Shell/Valve/VdfOptions.cs +++ b/SrcMod/Shell/Valve/VdfOptions.cs @@ -6,6 +6,7 @@ public record class VdfOptions public bool closeWhenFinished; public int indentSize; + public bool resetStreamPosition; public bool useEscapeCodes; public bool useQuotes; @@ -13,6 +14,7 @@ public record class VdfOptions { closeWhenFinished = true; indentSize = 4; + resetStreamPosition = false; useEscapeCodes = false; useQuotes = false; } diff --git a/SrcMod/Shell/Valve/VdfSerializer.cs b/SrcMod/Shell/Valve/VdfSerializer.cs index da46265..b0509b8 100644 --- a/SrcMod/Shell/Valve/VdfSerializer.cs +++ b/SrcMod/Shell/Valve/VdfSerializer.cs @@ -14,8 +14,10 @@ public class VdfSerializer public void Serialize(Stream stream, VdfNode parentNode, string parentNodeName) { - StreamWriter writer = p_options.closeWhenFinished ? new(stream) : new(stream, leaveOpen: true); - VdfConvert.SerializeNode(writer, parentNode, parentNodeName, ref p_options, 0); + StreamWriter writer = new(stream, leaveOpen: !p_options.closeWhenFinished); + VdfConvert.SerializeNode(writer, parentNode, parentNodeName, p_options, 0); writer.Close(); + + if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(0, SeekOrigin.Begin); } } diff --git a/SrcMod/Shell/Valve/VdfTreeNode.cs b/SrcMod/Shell/Valve/VdfTreeNode.cs index e39e8cf..e8e944e 100644 --- a/SrcMod/Shell/Valve/VdfTreeNode.cs +++ b/SrcMod/Shell/Valve/VdfTreeNode.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell.Valve; -public class VdfTreeNode : VdfNode +public class VdfTreeNode : VdfNode, IEnumerable> { public int SubNodeCount => p_subNodes.Count; @@ -29,4 +29,7 @@ public class VdfTreeNode : VdfNode p_subNodes[p_subNodes.Keys.ElementAt(index)] = value; } } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); } -- 2.49.0.windows.1 From 03128d3a5758a4543929978e84218efd646cda0b Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Sun, 7 May 2023 13:39:59 -0400 Subject: [PATCH 54/89] Improved serialization of node tree and began tree generation. --- SrcMod/Shell/Valve/VdfConvert.cs | 43 +++++++++++++++-------------- SrcMod/Shell/Valve/VdfSerializer.cs | 9 ++++-- SrcMod/Shell/Valve/VdfSingleNode.cs | 4 +-- SrcMod/Shell/Valve/VdfTreeNode.cs | 24 ++++++++++------ 4 files changed, 48 insertions(+), 32 deletions(-) diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index fa919dd..7f65ae0 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -6,9 +6,9 @@ public static class VdfConvert { private static readonly Dictionary p_escapeCodes = new() { + { "\\", "\\\\" }, { "\'", "\\\'" }, { "\"", "\\\"" }, - { "\\", "\\\\" }, { "\0", "\\0" }, { "\a", "\\a" }, { "\b", "\\b" }, @@ -19,10 +19,22 @@ public static class VdfConvert { "\v", "\\v" } }; - public static void SerializeNode(StreamWriter writer, VdfNode node, string name, + public static void SerializeNode(StreamWriter writer, VdfNode? node, string name, + VdfOptions options) => SerializeNode(writer, node, name, options, 0); + public static void SerializeNode(StreamWriter writer, VdfNode? node, string name) => + SerializeNode(writer, node, name, VdfOptions.Default, 0); + + public static VdfNode? ToNodeTree(object? obj) => ToNodeTree(obj, VdfOptions.Default); + public static VdfNode? ToNodeTree(object? obj, VdfOptions options) + { + return null; + } + + private static void SerializeNode(StreamWriter writer, VdfNode? node, string name, VdfOptions options, int indentLevel) { - if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); + if (node is null) return; + else if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, options, indentLevel); else throw new("Unknown node type."); } @@ -30,11 +42,14 @@ public static class VdfConvert private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name, VdfOptions options, int indentLevel) { + string? serializedValue = SerializeObject(node.value, options); + if (serializedValue is null) return; + writer.Write(new string(' ', indentLevel)); writer.Write(SerializeString(name, options)); writer.Write(' '); - string serializedValue = SerializeString(SerializeObject(node.value, options), options); + serializedValue = SerializeString(serializedValue, options); writer.WriteLine(serializedValue); } private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, @@ -44,27 +59,15 @@ public static class VdfConvert writer.WriteLine(SerializeString(name, options)); writer.WriteLine(new string(' ', indentLevel) + '{'); - foreach (KeyValuePair subNode in node) - { - if (subNode.Value is VdfSingleNode singleSubNode && singleSubNode.value.GetType().IsArray) - { - Array array = (Array)singleSubNode.value; - Dictionary items = new(); - for (int i = 0; i < array.Length; i++) - { - object? item = array.GetValue(i); - if (item is VdfNode subNodeItem) items.Add(i.ToString(), subNodeItem); - else items.Add(i.ToString(), new VdfSingleNode(item)); - } - } - else SerializeNode(writer, subNode.Value, subNode.Key, options, indentLevel + options.indentSize); - } + foreach (KeyValuePair subNode in node) + SerializeNode(writer, subNode.Value, subNode.Key, options, indentLevel + options.indentSize); writer.WriteLine(new string(' ', indentLevel) + '}'); } - private static string SerializeObject(object obj, VdfOptions options) + private static string? SerializeObject(object? obj, VdfOptions options) { + if (obj is null) return null; return obj.ToString() ?? string.Empty; } diff --git a/SrcMod/Shell/Valve/VdfSerializer.cs b/SrcMod/Shell/Valve/VdfSerializer.cs index b0509b8..4ae766b 100644 --- a/SrcMod/Shell/Valve/VdfSerializer.cs +++ b/SrcMod/Shell/Valve/VdfSerializer.cs @@ -12,10 +12,15 @@ public class VdfSerializer p_options = options; } - public void Serialize(Stream stream, VdfNode parentNode, string parentNodeName) + public void Serialize(Stream stream, object? value, string parentNodeName) + { + VdfNode? nodeTree = VdfConvert.ToNodeTree(value, p_options); + Serialize(stream, nodeTree, parentNodeName); + } + public void Serialize(Stream stream, VdfNode? parentNode, string parentNodeName) { StreamWriter writer = new(stream, leaveOpen: !p_options.closeWhenFinished); - VdfConvert.SerializeNode(writer, parentNode, parentNodeName, p_options, 0); + VdfConvert.SerializeNode(writer, parentNode, parentNodeName, p_options); writer.Close(); if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(0, SeekOrigin.Begin); diff --git a/SrcMod/Shell/Valve/VdfSingleNode.cs b/SrcMod/Shell/Valve/VdfSingleNode.cs index 5e68b48..429025f 100644 --- a/SrcMod/Shell/Valve/VdfSingleNode.cs +++ b/SrcMod/Shell/Valve/VdfSingleNode.cs @@ -2,10 +2,10 @@ public class VdfSingleNode : VdfNode { - public object value; + public object? value; public VdfSingleNode(object? value = null) : base() { - this.value = value ?? new(); + this.value = value; } } diff --git a/SrcMod/Shell/Valve/VdfTreeNode.cs b/SrcMod/Shell/Valve/VdfTreeNode.cs index e8e944e..2cef7cf 100644 --- a/SrcMod/Shell/Valve/VdfTreeNode.cs +++ b/SrcMod/Shell/Valve/VdfTreeNode.cs @@ -1,28 +1,36 @@ namespace SrcMod.Shell.Valve; -public class VdfTreeNode : VdfNode, IEnumerable> +public class VdfTreeNode : VdfNode, IEnumerable> { public int SubNodeCount => p_subNodes.Count; - private Dictionary p_subNodes; + private readonly Dictionary p_subNodes; - public VdfTreeNode(Dictionary? subNodes = null) : base() + public VdfTreeNode(Dictionary? subNodes = null) : base() { p_subNodes = subNodes ?? new(); } - public VdfNode this[string key] + public VdfNode? this[string key] { - get => p_subNodes[key]; + get + { + if (p_subNodes.TryGetValue(key, out VdfNode? value)) return value; + else return null; + } set { if (p_subNodes.ContainsKey(key)) p_subNodes[key] = value; else p_subNodes.Add(key, value); } } - public VdfNode this[int index] + public VdfNode? this[int index] { - get => p_subNodes.Values.ElementAt(index); + get + { + if (p_subNodes.Count >= index || index < 0) return null; + return p_subNodes.Values.ElementAt(index); + } set { if (p_subNodes.Count >= index || index < 0) throw new IndexOutOfRangeException(); @@ -31,5 +39,5 @@ public class VdfTreeNode : VdfNode, IEnumerable> } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); + public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); } -- 2.49.0.windows.1 From 20413603e34b8adee0617b49b8886eec6d0cf029 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Sun, 7 May 2023 13:54:25 -0400 Subject: [PATCH 55/89] Forgot we're in beta now. --- SrcMod/Shell/Shell.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index 7fe1d15..bc3aaa7 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Alpha 0.4.0"; + public const string Version = "Beta 0.4.0"; public readonly string? ShellDirectory; -- 2.49.0.windows.1 From 54ea2b52037cdad16e8026c746b7a064a3d791fc Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Sun, 7 May 2023 14:21:24 -0400 Subject: [PATCH 56/89] Some progress in creating the vdf node tree. --- SrcMod/Shell/Valve/VdfConvert.cs | 63 ++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index 7f65ae0..94f7427 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -1,22 +1,20 @@ -using System.Security.Cryptography; - -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve; public static class VdfConvert { private static readonly Dictionary p_escapeCodes = new() { - { "\\", "\\\\" }, - { "\'", "\\\'" }, - { "\"", "\\\"" }, - { "\0", "\\0" }, - { "\a", "\\a" }, - { "\b", "\\b" }, - { "\f", "\\f" }, - { "\n", "\\n" }, - { "\r", "\\r" }, - { "\t", "\\t" }, - { "\v", "\\v" } + { "\\", @"\\" }, // This must be first. + { "\'", @"\'" }, + { "\"", @"\""" }, + { "\0", @"\0" }, + { "\a", @"\a" }, + { "\b", @"\b" }, + { "\f", @"\f" }, + { "\n", @"\n" }, + { "\r", @"\r" }, + { "\t", @"\t" }, + { "\v", @"\v" } }; public static void SerializeNode(StreamWriter writer, VdfNode? node, string name, @@ -27,7 +25,40 @@ public static class VdfConvert public static VdfNode? ToNodeTree(object? obj) => ToNodeTree(obj, VdfOptions.Default); public static VdfNode? ToNodeTree(object? obj, VdfOptions options) { - return null; + if (obj is null) return null; + Type type = obj.GetType(); + + if (type.IsPrimitive) return new VdfSingleNode(obj); + else if (type.IsPointer) throw new("Cannot serialize a pointer."); + + VdfTreeNode tree = new(); + + if (obj is IDictionary dictionary) + { + object[] keys = new object[dictionary.Count], + values = new object[dictionary.Count]; + dictionary.Keys.CopyTo(keys, 0); + dictionary.Values.CopyTo(values, 0); + for (int i = 0; i < dictionary.Count; i++) + { + tree[SerializeObject(keys.GetValue(i), options)!] = ToNodeTree(values.GetValue(i)); + } + return tree; + } + else if (obj is IEnumerable enumerable) + { + int index = 0; + foreach (object item in enumerable) + { + tree[SerializeObject(index, options)!] = ToNodeTree(item); + index++; + } + return tree; + } + + // TODO: serialize object + + return tree; } private static void SerializeNode(StreamWriter writer, VdfNode? node, string name, @@ -55,6 +86,8 @@ public static class VdfConvert private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, VdfOptions options, int indentLevel) { + if (node.SubNodeCount <= 0) return; + writer.Write(new string(' ', indentLevel)); writer.WriteLine(SerializeString(name, options)); writer.WriteLine(new string(' ', indentLevel) + '{'); -- 2.49.0.windows.1 From bb520424ac9aea61da76ad0f0ad77862bde7e338 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Sun, 7 May 2023 21:23:04 -0400 Subject: [PATCH 57/89] More tree construction progress. Small. --- SrcMod/Shell/Valve/IVdfSerializable.cs | 6 ++++++ SrcMod/Shell/Valve/VdfConvert.cs | 25 ++++++++++++++++++++++-- SrcMod/Shell/Valve/VdfIgnoreAttribute.cs | 4 ++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 SrcMod/Shell/Valve/IVdfSerializable.cs create mode 100644 SrcMod/Shell/Valve/VdfIgnoreAttribute.cs diff --git a/SrcMod/Shell/Valve/IVdfSerializable.cs b/SrcMod/Shell/Valve/IVdfSerializable.cs new file mode 100644 index 0000000..4170e6e --- /dev/null +++ b/SrcMod/Shell/Valve/IVdfSerializable.cs @@ -0,0 +1,6 @@ +namespace SrcMod.Shell.Valve; + +public interface IVdfSerializable +{ + public VdfNode ToNodeTree(); +} \ No newline at end of file diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index 94f7427..ff69a19 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -33,7 +33,8 @@ public static class VdfConvert VdfTreeNode tree = new(); - if (obj is IDictionary dictionary) + if (obj is IVdfSerializable vdf) return vdf.ToNodeTree(); + else if (obj is IDictionary dictionary) { object[] keys = new object[dictionary.Count], values = new object[dictionary.Count]; @@ -45,7 +46,7 @@ public static class VdfConvert } return tree; } - else if (obj is IEnumerable enumerable) + else if (obj is ICollection enumerable) { int index = 0; foreach (object item in enumerable) @@ -57,6 +58,26 @@ public static class VdfConvert } // TODO: serialize object + IEnumerable validFields = from field in type.GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + let isIgnored = field.CustomAttributes.Any(x => + x.AttributeType == typeof(VdfIgnoreAttribute)) + let isConst = field.IsLiteral + where isPublic && !isStatic && !isIgnored && !isConst + select field; + + IEnumerable validProperties = from prop in type.GetProperties() + let canGet = prop.GetMethod is not null + let isPublic = canGet && prop.GetMethod!.IsPublic + let isStatic = canGet && prop.GetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VdfIgnoreAttribute)) + where canGet && isPublic && !isStatic && !isIgnored + select prop; + + foreach (FieldInfo field in validFields) Write($"field: {field.Name}"); + foreach (PropertyInfo prop in validProperties) Write($"prop: {prop.Name}"); return tree; } diff --git a/SrcMod/Shell/Valve/VdfIgnoreAttribute.cs b/SrcMod/Shell/Valve/VdfIgnoreAttribute.cs new file mode 100644 index 0000000..10e04e5 --- /dev/null +++ b/SrcMod/Shell/Valve/VdfIgnoreAttribute.cs @@ -0,0 +1,4 @@ +namespace SrcMod.Shell.Valve; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] +public class VdfIgnoreAttribute : Attribute { } -- 2.49.0.windows.1 From 1ee60cdf65b5cf1fde06257aee7a84d64f89c3c3 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Mon, 8 May 2023 08:44:50 -0400 Subject: [PATCH 58/89] Finished the first complete VDF tree creator. --- SrcMod/Shell/Valve/VdfConvert.cs | 36 ++++++++++++++++++++----------- SrcMod/Shell/Valve/VdfOptions.cs | 2 ++ SrcMod/Shell/Valve/VdfTreeNode.cs | 2 ++ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index ff69a19..156ae9f 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -34,6 +34,7 @@ public static class VdfConvert VdfTreeNode tree = new(); if (obj is IVdfSerializable vdf) return vdf.ToNodeTree(); + else if (obj is string str) return new VdfSingleNode(str); else if (obj is IDictionary dictionary) { object[] keys = new object[dictionary.Count], @@ -42,7 +43,7 @@ public static class VdfConvert dictionary.Values.CopyTo(values, 0); for (int i = 0; i < dictionary.Count; i++) { - tree[SerializeObject(keys.GetValue(i), options)!] = ToNodeTree(values.GetValue(i)); + tree[SerializeObject(keys.GetValue(i), options)!] = ToNodeTree(values.GetValue(i), options); } return tree; } @@ -51,7 +52,7 @@ public static class VdfConvert int index = 0; foreach (object item in enumerable) { - tree[SerializeObject(index, options)!] = ToNodeTree(item); + tree[SerializeObject(index, options)!] = ToNodeTree(item, options); index++; } return tree; @@ -67,17 +68,28 @@ public static class VdfConvert where isPublic && !isStatic && !isIgnored && !isConst select field; - IEnumerable validProperties = from prop in type.GetProperties() - let canGet = prop.GetMethod is not null - let isPublic = canGet && prop.GetMethod!.IsPublic - let isStatic = canGet && prop.GetMethod!.IsStatic - let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VdfIgnoreAttribute)) - where canGet && isPublic && !isStatic && !isIgnored - select prop; + IEnumerable validProperties; + if (options.serializeProperties) + { + validProperties = from prop in type.GetProperties() + let canGet = prop.GetMethod is not null + let isPublic = canGet && prop.GetMethod!.IsPublic + let isStatic = canGet && prop.GetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VdfIgnoreAttribute)) + where canGet && isPublic && !isStatic && !isIgnored + select prop; + } + else validProperties = Array.Empty(); - foreach (FieldInfo field in validFields) Write($"field: {field.Name}"); - foreach (PropertyInfo prop in validProperties) Write($"prop: {prop.Name}"); + foreach (FieldInfo field in validFields) + { + tree[field.Name] = ToNodeTree(field.GetValue(obj), options); + } + foreach (PropertyInfo prop in validProperties) + { + tree[prop.Name] = ToNodeTree(prop.GetValue(obj), options); + } return tree; } diff --git a/SrcMod/Shell/Valve/VdfOptions.cs b/SrcMod/Shell/Valve/VdfOptions.cs index 2287658..6e5e03d 100644 --- a/SrcMod/Shell/Valve/VdfOptions.cs +++ b/SrcMod/Shell/Valve/VdfOptions.cs @@ -7,6 +7,7 @@ public record class VdfOptions public bool closeWhenFinished; public int indentSize; public bool resetStreamPosition; + public bool serializeProperties; public bool useEscapeCodes; public bool useQuotes; @@ -15,6 +16,7 @@ public record class VdfOptions closeWhenFinished = true; indentSize = 4; resetStreamPosition = false; + serializeProperties = true; useEscapeCodes = false; useQuotes = false; } diff --git a/SrcMod/Shell/Valve/VdfTreeNode.cs b/SrcMod/Shell/Valve/VdfTreeNode.cs index 2cef7cf..610b231 100644 --- a/SrcMod/Shell/Valve/VdfTreeNode.cs +++ b/SrcMod/Shell/Valve/VdfTreeNode.cs @@ -38,6 +38,8 @@ public class VdfTreeNode : VdfNode, IEnumerable> } } + public void Add(string key, VdfNode? value) => this[key] = value; + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); } -- 2.49.0.windows.1 From 7428ac9110a7f94898832502aa88b3613b8eeae1 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 9 May 2023 09:46:55 -0400 Subject: [PATCH 59/89] Hopefully VDF deserialization works now. --- SrcMod/Shell/Valve/VdfConvert.cs | 207 +++++++++++++----- .../Shell/Valve/VdfSerializationException.cs | 8 + SrcMod/Shell/Valve/VdfSerializer.cs | 14 +- 3 files changed, 174 insertions(+), 55 deletions(-) create mode 100644 SrcMod/Shell/Valve/VdfSerializationException.cs diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index 156ae9f..209d854 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -17,11 +17,161 @@ public static class VdfConvert { "\v", @"\v" } }; + #region DeserializeNode + public static VdfNode? DeserializeNode(StreamReader reader, VdfOptions options) => + DeserializeNode(reader, options, out _, null); + + private static VdfNode? DeserializeNode(StreamReader reader, VdfOptions options, out string name, + string? first) + { + string? header = first ?? (reader.ReadLine()?.Trim()); + if (header is null || string.IsNullOrEmpty(header)) + { + name = string.Empty; + return null; + } + + string[] parts = SplitContent(header, options); + if (parts.Length > 2) throw new VdfSerializationException("Too many values in node."); + + VdfNode node; + + name = DeserializeString(parts[0], options); + if (parts.Length == 2) + { + object value = DeserializeObject(DeserializeString(parts[1], options)); + node = new VdfSingleNode(value); + } + else + { + string? next = reader.ReadLine()?.Trim(); + if (next is null) throw new VdfSerializationException("Expected starting '{', found end-of-file."); + else if (next != "{") throw new VdfSerializationException($"Expected starting '{{', found \"{next}\"."); + VdfTreeNode tree = new(); + string? current; + while ((current = reader.ReadLine()?.Trim()) is not null) + { + if (current == "}") break; + VdfNode? output = DeserializeNode(reader, options, out string subName, current); + if (output is null) throw new VdfSerializationException("Error deserializing sub-node."); + tree[subName] = output; + } + if (current is null) throw new VdfSerializationException("Reached end-of-file while deserializing group."); + node = tree; + } + + return node; + } + + private static object DeserializeObject(string content) => + TypeParsers.ParseAll(content); + private static string DeserializeString(string content, VdfOptions options) + { + if (options.useQuotes) + { + if (!content.StartsWith('\"') || !content.EndsWith('\"')) + throw new VdfSerializationException("No quotes found around content."); + content = content[1..^1]; + } + if (options.useEscapeCodes) + { + foreach (KeyValuePair escapeCode in p_escapeCodes.Reverse()) + content = content.Replace(escapeCode.Value, escapeCode.Key); + } + return content; + } + + private static string[] SplitContent(string content, VdfOptions options) + { + content = content.Replace('\t', ' '); + if (options.useQuotes) + { + List values = new(); + string current = string.Empty; + bool inQuote = false; + for (int i = 0; i < content.Length; i++) + { + char c = content[i]; + if (c == '\"' && !(i > 0 && content[i - 1] == '\\')) inQuote = !inQuote; + + if (c == ' ' && !inQuote) + { + if (!string.IsNullOrEmpty(current)) values.Add(current); + current = string.Empty; + } + else current += c; + } + if (inQuote) throw new VdfSerializationException("Reached end-of-line while inside quotations."); + if (!string.IsNullOrEmpty(current)) values.Add(current); + return values.ToArray(); + } + else return content.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); + } + #endregion + + #region SerializeNode public static void SerializeNode(StreamWriter writer, VdfNode? node, string name, VdfOptions options) => SerializeNode(writer, node, name, options, 0); public static void SerializeNode(StreamWriter writer, VdfNode? node, string name) => SerializeNode(writer, node, name, VdfOptions.Default, 0); + private static void SerializeNode(StreamWriter writer, VdfNode? node, string name, + VdfOptions options, int indentLevel) + { + if (node is null) return; + else if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); + else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, options, indentLevel); + else throw new("Unknown node type."); + } + + private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name, + VdfOptions options, int indentLevel) + { + string? serializedValue = SerializeObject(node.value); + if (serializedValue is null) return; + + writer.Write(new string(' ', indentLevel)); + writer.Write(SerializeString(name, options)); + writer.Write(' '); + + serializedValue = SerializeString(serializedValue, options); + writer.WriteLine(serializedValue); + } + private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, + VdfOptions options, int indentLevel) + { + if (node.SubNodeCount <= 0) return; + + writer.Write(new string(' ', indentLevel)); + writer.WriteLine(SerializeString(name, options)); + writer.WriteLine(new string(' ', indentLevel) + '{'); + + foreach (KeyValuePair subNode in node) + SerializeNode(writer, subNode.Value, subNode.Key, options, indentLevel + options.indentSize); + + writer.WriteLine(new string(' ', indentLevel) + '}'); + } + + private static string? SerializeObject(object? obj) + { + if (obj is null) return null; + return obj.ToString() ?? string.Empty; + } + + private static string SerializeString(string content, VdfOptions options) + { + if (options.useEscapeCodes) + { + foreach (KeyValuePair escapeCode in p_escapeCodes) + content = content.Replace(escapeCode.Key, escapeCode.Value); + } + if (options.useQuotes) content = $"\"{content}\""; + return content; + } + + #endregion + + #region ToNodeTree public static VdfNode? ToNodeTree(object? obj) => ToNodeTree(obj, VdfOptions.Default); public static VdfNode? ToNodeTree(object? obj, VdfOptions options) { @@ -43,7 +193,7 @@ public static class VdfConvert dictionary.Values.CopyTo(values, 0); for (int i = 0; i < dictionary.Count; i++) { - tree[SerializeObject(keys.GetValue(i), options)!] = ToNodeTree(values.GetValue(i), options); + tree[SerializeObject(keys.GetValue(i))!] = ToNodeTree(values.GetValue(i), options); } return tree; } @@ -52,7 +202,7 @@ public static class VdfConvert int index = 0; foreach (object item in enumerable) { - tree[SerializeObject(index, options)!] = ToNodeTree(item, options); + tree[SerializeObject(index)!] = ToNodeTree(item, options); index++; } return tree; @@ -93,56 +243,5 @@ public static class VdfConvert return tree; } - - private static void SerializeNode(StreamWriter writer, VdfNode? node, string name, - VdfOptions options, int indentLevel) - { - if (node is null) return; - else if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); - else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, options, indentLevel); - else throw new("Unknown node type."); - } - - private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name, - VdfOptions options, int indentLevel) - { - string? serializedValue = SerializeObject(node.value, options); - if (serializedValue is null) return; - - writer.Write(new string(' ', indentLevel)); - writer.Write(SerializeString(name, options)); - writer.Write(' '); - - serializedValue = SerializeString(serializedValue, options); - writer.WriteLine(serializedValue); - } - private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, - VdfOptions options, int indentLevel) - { - if (node.SubNodeCount <= 0) return; - - writer.Write(new string(' ', indentLevel)); - writer.WriteLine(SerializeString(name, options)); - writer.WriteLine(new string(' ', indentLevel) + '{'); - - foreach (KeyValuePair subNode in node) - SerializeNode(writer, subNode.Value, subNode.Key, options, indentLevel + options.indentSize); - - writer.WriteLine(new string(' ', indentLevel) + '}'); - } - - private static string? SerializeObject(object? obj, VdfOptions options) - { - if (obj is null) return null; - return obj.ToString() ?? string.Empty; - } - - private static string SerializeString(string content, VdfOptions options) - { - if (options.useEscapeCodes) - foreach (KeyValuePair escapeCode in p_escapeCodes) - content = content.Replace(escapeCode.Key, escapeCode.Value); - if (options.useQuotes) content = $"\"{content}\""; - return content; - } + #endregion } diff --git a/SrcMod/Shell/Valve/VdfSerializationException.cs b/SrcMod/Shell/Valve/VdfSerializationException.cs new file mode 100644 index 0000000..fa7c764 --- /dev/null +++ b/SrcMod/Shell/Valve/VdfSerializationException.cs @@ -0,0 +1,8 @@ +namespace SrcMod.Shell.Valve; + +public class VdfSerializationException : Exception +{ + public VdfSerializationException() : base() { } + public VdfSerializationException(string message) : base(message) { } + public VdfSerializationException(string message, Exception inner) : base(message, inner) { } +} diff --git a/SrcMod/Shell/Valve/VdfSerializer.cs b/SrcMod/Shell/Valve/VdfSerializer.cs index 4ae766b..fd61521 100644 --- a/SrcMod/Shell/Valve/VdfSerializer.cs +++ b/SrcMod/Shell/Valve/VdfSerializer.cs @@ -12,6 +12,17 @@ public class VdfSerializer p_options = options; } + public VdfNode? Deserialize(Stream stream) + { + long pos = stream.Position; + StreamReader reader = new(stream, leaveOpen: !p_options.closeWhenFinished); + VdfNode? result = VdfConvert.DeserializeNode(reader, p_options); + reader.Close(); + + if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); + return result; + } + public void Serialize(Stream stream, object? value, string parentNodeName) { VdfNode? nodeTree = VdfConvert.ToNodeTree(value, p_options); @@ -19,10 +30,11 @@ public class VdfSerializer } public void Serialize(Stream stream, VdfNode? parentNode, string parentNodeName) { + long pos = stream.Position; StreamWriter writer = new(stream, leaveOpen: !p_options.closeWhenFinished); VdfConvert.SerializeNode(writer, parentNode, parentNodeName, p_options); writer.Close(); - if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(0, SeekOrigin.Begin); + if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); } } -- 2.49.0.windows.1 From e6198cd0354d5a723f612640262ffc966f370c10 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 9 May 2023 14:08:28 -0400 Subject: [PATCH 60/89] Some small node tree conversion progress. --- .../Shell/Modules/ObjectModels/TypeParsers.cs | 3 + ...IVdfSerializable.cs => IVdfConvertible.cs} | 2 +- SrcMod/Shell/Valve/VdfConvert.cs | 64 +++++++++++++++++-- 3 files changed, 64 insertions(+), 5 deletions(-) rename SrcMod/Shell/Valve/{IVdfSerializable.cs => IVdfConvertible.cs} (67%) diff --git a/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs b/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs index 954f9be..f2affd8 100644 --- a/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs +++ b/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs @@ -2,6 +2,9 @@ public static class TypeParsers { + public static bool CanParse(object? obj) => obj is not null && obj is sbyte or byte or short or ushort or int + or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal + or char or DateOnly or DateTime or DateTimeOffset or Guid or TimeOnly or TimeSpan; public static object ParseAll(string msg) { if (TryParse(msg, out sbyte int8)) return int8; diff --git a/SrcMod/Shell/Valve/IVdfSerializable.cs b/SrcMod/Shell/Valve/IVdfConvertible.cs similarity index 67% rename from SrcMod/Shell/Valve/IVdfSerializable.cs rename to SrcMod/Shell/Valve/IVdfConvertible.cs index 4170e6e..21bff1c 100644 --- a/SrcMod/Shell/Valve/IVdfSerializable.cs +++ b/SrcMod/Shell/Valve/IVdfConvertible.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell.Valve; -public interface IVdfSerializable +public interface IVdfConvertible { public VdfNode ToNodeTree(); } \ No newline at end of file diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index 209d854..5759215 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -18,6 +18,8 @@ public static class VdfConvert }; #region DeserializeNode + public static VdfNode? DeserializeNode(StreamReader reader) => + DeserializeNode(reader, VdfOptions.Default, out _, null); public static VdfNode? DeserializeNode(StreamReader reader, VdfOptions options) => DeserializeNode(reader, options, out _, null); @@ -109,6 +111,62 @@ public static class VdfConvert } #endregion + #region FromNodeTree + public static object? FromNodeTree(Type outputType, VdfNode? node, VdfOptions options) + { + if (node is null) return null; + + object? instance = Activator.CreateInstance(outputType); + if (instance is null) return null; + + IEnumerable validFields = from field in outputType.GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + let isIgnored = field.CustomAttributes.Any(x => + x.AttributeType == typeof(VdfIgnoreAttribute)) + let isConst = field.IsLiteral + where isPublic && !isStatic && !isIgnored && !isConst + select field; + + IEnumerable validProperties; + if (options.serializeProperties) + { + validProperties = from prop in outputType.GetProperties() + let canSet = prop.SetMethod is not null + let isPublic = canSet && prop.SetMethod!.IsPublic + let isStatic = canSet && prop.SetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VdfIgnoreAttribute)) + where canSet && isPublic && !isStatic && !isIgnored + select prop; + } + else validProperties = Array.Empty(); + + foreach (FieldInfo field in validFields) + { + // TODO: check if the node tree has that field. + + Type castType = field.FieldType; + if (TypeParsers.CanParse(instance)) + { + + } + } + foreach (PropertyInfo prop in validProperties) + { + // TODO: check if the node tree has that field. + + Type castType = prop.PropertyType; + if (TypeParsers.CanParse(instance)) + { + + } + } + + return null; + } + #endregion + #region SerializeNode public static void SerializeNode(StreamWriter writer, VdfNode? node, string name, VdfOptions options) => SerializeNode(writer, node, name, options, 0); @@ -178,13 +236,12 @@ public static class VdfConvert if (obj is null) return null; Type type = obj.GetType(); - if (type.IsPrimitive) return new VdfSingleNode(obj); + if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VdfSingleNode(obj); else if (type.IsPointer) throw new("Cannot serialize a pointer."); VdfTreeNode tree = new(); - if (obj is IVdfSerializable vdf) return vdf.ToNodeTree(); - else if (obj is string str) return new VdfSingleNode(str); + if (obj is IVdfConvertible vdf) return vdf.ToNodeTree(); else if (obj is IDictionary dictionary) { object[] keys = new object[dictionary.Count], @@ -208,7 +265,6 @@ public static class VdfConvert return tree; } - // TODO: serialize object IEnumerable validFields = from field in type.GetFields() let isPublic = field.IsPublic let isStatic = field.IsStatic -- 2.49.0.windows.1 From 71edd4fffa78cc8721800fbfd6a34a196935b5ed Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 9 May 2023 17:56:43 -0400 Subject: [PATCH 61/89] Moved some vkv objects into an objectmodels folder --- SrcMod/Shell/Valve/{ => ObjectModels}/IVdfConvertible.cs | 2 +- SrcMod/Shell/Valve/{ => ObjectModels}/VdfIgnoreAttribute.cs | 2 +- .../Valve/{ => ObjectModels}/VdfSerializationException.cs | 2 +- SrcMod/Shell/Valve/VdfConvert.cs | 4 +++- SrcMod/Shell/Valve/VdfSerializer.cs | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) rename SrcMod/Shell/Valve/{ => ObjectModels}/IVdfConvertible.cs (60%) rename SrcMod/Shell/Valve/{ => ObjectModels}/VdfIgnoreAttribute.cs (77%) rename SrcMod/Shell/Valve/{ => ObjectModels}/VdfSerializationException.cs (85%) diff --git a/SrcMod/Shell/Valve/IVdfConvertible.cs b/SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs similarity index 60% rename from SrcMod/Shell/Valve/IVdfConvertible.cs rename to SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs index 21bff1c..a522adf 100644 --- a/SrcMod/Shell/Valve/IVdfConvertible.cs +++ b/SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.ObjectModels; public interface IVdfConvertible { diff --git a/SrcMod/Shell/Valve/VdfIgnoreAttribute.cs b/SrcMod/Shell/Valve/ObjectModels/VdfIgnoreAttribute.cs similarity index 77% rename from SrcMod/Shell/Valve/VdfIgnoreAttribute.cs rename to SrcMod/Shell/Valve/ObjectModels/VdfIgnoreAttribute.cs index 10e04e5..26ecb15 100644 --- a/SrcMod/Shell/Valve/VdfIgnoreAttribute.cs +++ b/SrcMod/Shell/Valve/ObjectModels/VdfIgnoreAttribute.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.ObjectModels; [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public class VdfIgnoreAttribute : Attribute { } diff --git a/SrcMod/Shell/Valve/VdfSerializationException.cs b/SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs similarity index 85% rename from SrcMod/Shell/Valve/VdfSerializationException.cs rename to SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs index fa7c764..10379a7 100644 --- a/SrcMod/Shell/Valve/VdfSerializationException.cs +++ b/SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.ObjectModels; public class VdfSerializationException : Exception { diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/VdfConvert.cs index 5759215..b3b2a8a 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/VdfConvert.cs @@ -1,4 +1,6 @@ -namespace SrcMod.Shell.Valve; +using SrcMod.Shell.Valve.ObjectModels; + +namespace SrcMod.Shell.Valve; public static class VdfConvert { diff --git a/SrcMod/Shell/Valve/VdfSerializer.cs b/SrcMod/Shell/Valve/VdfSerializer.cs index fd61521..e59ac67 100644 --- a/SrcMod/Shell/Valve/VdfSerializer.cs +++ b/SrcMod/Shell/Valve/VdfSerializer.cs @@ -4,7 +4,7 @@ public class VdfSerializer { public VdfOptions Options => p_options; - private VdfOptions p_options; + private readonly VdfOptions p_options; public VdfSerializer() : this(VdfOptions.Default) { } public VdfSerializer(VdfOptions options) -- 2.49.0.windows.1 From 856811687e46a6d43adebdc4267f570cebe06041 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 9 May 2023 18:01:12 -0400 Subject: [PATCH 62/89] Renamed VDF stuff to VKV as it should be and moved to subfolder. --- .../Valve/ObjectModels/IVdfConvertible.cs | 6 -- .../ObjectModels/VdfSerializationException.cs | 8 -- SrcMod/Shell/Valve/VdfNode.cs | 6 -- SrcMod/Shell/Valve/VdfSingleNode.cs | 11 --- .../Valve/Vkv/ObjectModels/IVkvConvertible.cs | 8 ++ .../ObjectModels/VkvIgnoreAttribute.cs} | 4 +- .../ObjectModels/VkvSerializationException.cs | 8 ++ .../{VdfConvert.cs => Vkv/VkvConvert.cs} | 90 +++++++++---------- SrcMod/Shell/Valve/Vkv/VkvNode.cs | 3 + .../{VdfOptions.cs => Vkv/VkvOptions.cs} | 8 +- .../VkvSerializer.cs} | 22 ++--- SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs | 11 +++ .../{VdfTreeNode.cs => Vkv/VkvTreeNode.cs} | 18 ++-- 13 files changed, 101 insertions(+), 102 deletions(-) delete mode 100644 SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs delete mode 100644 SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs delete mode 100644 SrcMod/Shell/Valve/VdfNode.cs delete mode 100644 SrcMod/Shell/Valve/VdfSingleNode.cs create mode 100644 SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs rename SrcMod/Shell/Valve/{ObjectModels/VdfIgnoreAttribute.cs => Vkv/ObjectModels/VkvIgnoreAttribute.cs} (53%) create mode 100644 SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs rename SrcMod/Shell/Valve/{VdfConvert.cs => Vkv/VkvConvert.cs} (79%) create mode 100644 SrcMod/Shell/Valve/Vkv/VkvNode.cs rename SrcMod/Shell/Valve/{VdfOptions.cs => Vkv/VkvOptions.cs} (74%) rename SrcMod/Shell/Valve/{VdfSerializer.cs => Vkv/VkvSerializer.cs} (59%) create mode 100644 SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs rename SrcMod/Shell/Valve/{VdfTreeNode.cs => Vkv/VkvTreeNode.cs} (62%) diff --git a/SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs b/SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs deleted file mode 100644 index a522adf..0000000 --- a/SrcMod/Shell/Valve/ObjectModels/IVdfConvertible.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SrcMod.Shell.Valve.ObjectModels; - -public interface IVdfConvertible -{ - public VdfNode ToNodeTree(); -} \ No newline at end of file diff --git a/SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs b/SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs deleted file mode 100644 index 10379a7..0000000 --- a/SrcMod/Shell/Valve/ObjectModels/VdfSerializationException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SrcMod.Shell.Valve.ObjectModels; - -public class VdfSerializationException : Exception -{ - public VdfSerializationException() : base() { } - public VdfSerializationException(string message) : base(message) { } - public VdfSerializationException(string message, Exception inner) : base(message, inner) { } -} diff --git a/SrcMod/Shell/Valve/VdfNode.cs b/SrcMod/Shell/Valve/VdfNode.cs deleted file mode 100644 index 36f3326..0000000 --- a/SrcMod/Shell/Valve/VdfNode.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SrcMod.Shell.Valve; - -public abstract class VdfNode -{ - -} diff --git a/SrcMod/Shell/Valve/VdfSingleNode.cs b/SrcMod/Shell/Valve/VdfSingleNode.cs deleted file mode 100644 index 429025f..0000000 --- a/SrcMod/Shell/Valve/VdfSingleNode.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SrcMod.Shell.Valve; - -public class VdfSingleNode : VdfNode -{ - public object? value; - - public VdfSingleNode(object? value = null) : base() - { - this.value = value; - } -} diff --git a/SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs b/SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs new file mode 100644 index 0000000..8bc6364 --- /dev/null +++ b/SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs @@ -0,0 +1,8 @@ +using SrcMod.Shell.Valve.Vkv; + +namespace SrcMod.Shell.Valve.Vkv.ObjectModels; + +public interface IVkvConvertible +{ + public VkvNode ToNodeTree(); +} \ No newline at end of file diff --git a/SrcMod/Shell/Valve/ObjectModels/VdfIgnoreAttribute.cs b/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvIgnoreAttribute.cs similarity index 53% rename from SrcMod/Shell/Valve/ObjectModels/VdfIgnoreAttribute.cs rename to SrcMod/Shell/Valve/Vkv/ObjectModels/VkvIgnoreAttribute.cs index 26ecb15..7fab5fa 100644 --- a/SrcMod/Shell/Valve/ObjectModels/VdfIgnoreAttribute.cs +++ b/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvIgnoreAttribute.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.ObjectModels; +namespace SrcMod.Shell.Valve.Vkv.ObjectModels; [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] -public class VdfIgnoreAttribute : Attribute { } +public class VkvIgnoreAttribute : Attribute { } diff --git a/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs b/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs new file mode 100644 index 0000000..2995971 --- /dev/null +++ b/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs @@ -0,0 +1,8 @@ +namespace SrcMod.Shell.Valve.Vkv.ObjectModels; + +public class VkvSerializationException : Exception +{ + public VkvSerializationException() : base() { } + public VkvSerializationException(string message) : base(message) { } + public VkvSerializationException(string message, Exception inner) : base(message, inner) { } +} diff --git a/SrcMod/Shell/Valve/VdfConvert.cs b/SrcMod/Shell/Valve/Vkv/VkvConvert.cs similarity index 79% rename from SrcMod/Shell/Valve/VdfConvert.cs rename to SrcMod/Shell/Valve/Vkv/VkvConvert.cs index b3b2a8a..76007b0 100644 --- a/SrcMod/Shell/Valve/VdfConvert.cs +++ b/SrcMod/Shell/Valve/Vkv/VkvConvert.cs @@ -1,8 +1,8 @@ -using SrcMod.Shell.Valve.ObjectModels; +using SrcMod.Shell.Valve.Vkv.ObjectModels; -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.Vkv; -public static class VdfConvert +public static class VkvConvert { private static readonly Dictionary p_escapeCodes = new() { @@ -20,12 +20,12 @@ public static class VdfConvert }; #region DeserializeNode - public static VdfNode? DeserializeNode(StreamReader reader) => - DeserializeNode(reader, VdfOptions.Default, out _, null); - public static VdfNode? DeserializeNode(StreamReader reader, VdfOptions options) => + public static VkvNode? DeserializeNode(StreamReader reader) => + DeserializeNode(reader, VkvOptions.Default, out _, null); + public static VkvNode? DeserializeNode(StreamReader reader, VkvOptions options) => DeserializeNode(reader, options, out _, null); - private static VdfNode? DeserializeNode(StreamReader reader, VdfOptions options, out string name, + private static VkvNode? DeserializeNode(StreamReader reader, VkvOptions options, out string name, string? first) { string? header = first ?? (reader.ReadLine()?.Trim()); @@ -36,31 +36,31 @@ public static class VdfConvert } string[] parts = SplitContent(header, options); - if (parts.Length > 2) throw new VdfSerializationException("Too many values in node."); + if (parts.Length > 2) throw new VkvSerializationException("Too many values in node."); - VdfNode node; + VkvNode node; name = DeserializeString(parts[0], options); if (parts.Length == 2) { object value = DeserializeObject(DeserializeString(parts[1], options)); - node = new VdfSingleNode(value); + node = new VkvSingleNode(value); } else { string? next = reader.ReadLine()?.Trim(); - if (next is null) throw new VdfSerializationException("Expected starting '{', found end-of-file."); - else if (next != "{") throw new VdfSerializationException($"Expected starting '{{', found \"{next}\"."); - VdfTreeNode tree = new(); + if (next is null) throw new VkvSerializationException("Expected starting '{', found end-of-file."); + else if (next != "{") throw new VkvSerializationException($"Expected starting '{{', found \"{next}\"."); + VkvTreeNode tree = new(); string? current; while ((current = reader.ReadLine()?.Trim()) is not null) { if (current == "}") break; - VdfNode? output = DeserializeNode(reader, options, out string subName, current); - if (output is null) throw new VdfSerializationException("Error deserializing sub-node."); + VkvNode? output = DeserializeNode(reader, options, out string subName, current); + if (output is null) throw new VkvSerializationException("Error deserializing sub-node."); tree[subName] = output; } - if (current is null) throw new VdfSerializationException("Reached end-of-file while deserializing group."); + if (current is null) throw new VkvSerializationException("Reached end-of-file while deserializing group."); node = tree; } @@ -69,12 +69,12 @@ public static class VdfConvert private static object DeserializeObject(string content) => TypeParsers.ParseAll(content); - private static string DeserializeString(string content, VdfOptions options) + private static string DeserializeString(string content, VkvOptions options) { if (options.useQuotes) { if (!content.StartsWith('\"') || !content.EndsWith('\"')) - throw new VdfSerializationException("No quotes found around content."); + throw new VkvSerializationException("No quotes found around content."); content = content[1..^1]; } if (options.useEscapeCodes) @@ -85,7 +85,7 @@ public static class VdfConvert return content; } - private static string[] SplitContent(string content, VdfOptions options) + private static string[] SplitContent(string content, VkvOptions options) { content = content.Replace('\t', ' '); if (options.useQuotes) @@ -105,7 +105,7 @@ public static class VdfConvert } else current += c; } - if (inQuote) throw new VdfSerializationException("Reached end-of-line while inside quotations."); + if (inQuote) throw new VkvSerializationException("Reached end-of-line while inside quotations."); if (!string.IsNullOrEmpty(current)) values.Add(current); return values.ToArray(); } @@ -114,7 +114,7 @@ public static class VdfConvert #endregion #region FromNodeTree - public static object? FromNodeTree(Type outputType, VdfNode? node, VdfOptions options) + public static object? FromNodeTree(Type outputType, VkvNode? node, VkvOptions options) { if (node is null) return null; @@ -125,7 +125,7 @@ public static class VdfConvert let isPublic = field.IsPublic let isStatic = field.IsStatic let isIgnored = field.CustomAttributes.Any(x => - x.AttributeType == typeof(VdfIgnoreAttribute)) + x.AttributeType == typeof(VkvIgnoreAttribute)) let isConst = field.IsLiteral where isPublic && !isStatic && !isIgnored && !isConst select field; @@ -138,7 +138,7 @@ public static class VdfConvert let isPublic = canSet && prop.SetMethod!.IsPublic let isStatic = canSet && prop.SetMethod!.IsStatic let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VdfIgnoreAttribute)) + x.AttributeType == typeof(VkvIgnoreAttribute)) where canSet && isPublic && !isStatic && !isIgnored select prop; } @@ -151,7 +151,7 @@ public static class VdfConvert Type castType = field.FieldType; if (TypeParsers.CanParse(instance)) { - + } } foreach (PropertyInfo prop in validProperties) @@ -170,22 +170,22 @@ public static class VdfConvert #endregion #region SerializeNode - public static void SerializeNode(StreamWriter writer, VdfNode? node, string name, - VdfOptions options) => SerializeNode(writer, node, name, options, 0); - public static void SerializeNode(StreamWriter writer, VdfNode? node, string name) => - SerializeNode(writer, node, name, VdfOptions.Default, 0); + public static void SerializeNode(StreamWriter writer, VkvNode? node, string name, + VkvOptions options) => SerializeNode(writer, node, name, options, 0); + public static void SerializeNode(StreamWriter writer, VkvNode? node, string name) => + SerializeNode(writer, node, name, VkvOptions.Default, 0); - private static void SerializeNode(StreamWriter writer, VdfNode? node, string name, - VdfOptions options, int indentLevel) + private static void SerializeNode(StreamWriter writer, VkvNode? node, string name, + VkvOptions options, int indentLevel) { if (node is null) return; - else if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); - else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, options, indentLevel); + else if (node is VkvSingleNode single) SerializeSingleNode(writer, single, name, options, indentLevel); + else if (node is VkvTreeNode tree) SerializeTreeNode(writer, tree, name, options, indentLevel); else throw new("Unknown node type."); } - private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name, - VdfOptions options, int indentLevel) + private static void SerializeSingleNode(StreamWriter writer, VkvSingleNode node, string name, + VkvOptions options, int indentLevel) { string? serializedValue = SerializeObject(node.value); if (serializedValue is null) return; @@ -197,8 +197,8 @@ public static class VdfConvert serializedValue = SerializeString(serializedValue, options); writer.WriteLine(serializedValue); } - private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name, - VdfOptions options, int indentLevel) + private static void SerializeTreeNode(StreamWriter writer, VkvTreeNode node, string name, + VkvOptions options, int indentLevel) { if (node.SubNodeCount <= 0) return; @@ -206,7 +206,7 @@ public static class VdfConvert writer.WriteLine(SerializeString(name, options)); writer.WriteLine(new string(' ', indentLevel) + '{'); - foreach (KeyValuePair subNode in node) + foreach (KeyValuePair subNode in node) SerializeNode(writer, subNode.Value, subNode.Key, options, indentLevel + options.indentSize); writer.WriteLine(new string(' ', indentLevel) + '}'); @@ -218,7 +218,7 @@ public static class VdfConvert return obj.ToString() ?? string.Empty; } - private static string SerializeString(string content, VdfOptions options) + private static string SerializeString(string content, VkvOptions options) { if (options.useEscapeCodes) { @@ -232,18 +232,18 @@ public static class VdfConvert #endregion #region ToNodeTree - public static VdfNode? ToNodeTree(object? obj) => ToNodeTree(obj, VdfOptions.Default); - public static VdfNode? ToNodeTree(object? obj, VdfOptions options) + public static VkvNode? ToNodeTree(object? obj) => ToNodeTree(obj, VkvOptions.Default); + public static VkvNode? ToNodeTree(object? obj, VkvOptions options) { if (obj is null) return null; Type type = obj.GetType(); - if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VdfSingleNode(obj); + if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj); else if (type.IsPointer) throw new("Cannot serialize a pointer."); - VdfTreeNode tree = new(); + VkvTreeNode tree = new(); - if (obj is IVdfConvertible vdf) return vdf.ToNodeTree(); + if (obj is IVkvConvertible vdf) return vdf.ToNodeTree(); else if (obj is IDictionary dictionary) { object[] keys = new object[dictionary.Count], @@ -271,7 +271,7 @@ public static class VdfConvert let isPublic = field.IsPublic let isStatic = field.IsStatic let isIgnored = field.CustomAttributes.Any(x => - x.AttributeType == typeof(VdfIgnoreAttribute)) + x.AttributeType == typeof(VkvIgnoreAttribute)) let isConst = field.IsLiteral where isPublic && !isStatic && !isIgnored && !isConst select field; @@ -284,7 +284,7 @@ public static class VdfConvert let isPublic = canGet && prop.GetMethod!.IsPublic let isStatic = canGet && prop.GetMethod!.IsStatic let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VdfIgnoreAttribute)) + x.AttributeType == typeof(VkvIgnoreAttribute)) where canGet && isPublic && !isStatic && !isIgnored select prop; } diff --git a/SrcMod/Shell/Valve/Vkv/VkvNode.cs b/SrcMod/Shell/Valve/Vkv/VkvNode.cs new file mode 100644 index 0000000..2f7a9da --- /dev/null +++ b/SrcMod/Shell/Valve/Vkv/VkvNode.cs @@ -0,0 +1,3 @@ +namespace SrcMod.Shell.Valve.Vkv; + +public abstract class VkvNode { } diff --git a/SrcMod/Shell/Valve/VdfOptions.cs b/SrcMod/Shell/Valve/Vkv/VkvOptions.cs similarity index 74% rename from SrcMod/Shell/Valve/VdfOptions.cs rename to SrcMod/Shell/Valve/Vkv/VkvOptions.cs index 6e5e03d..de8ce23 100644 --- a/SrcMod/Shell/Valve/VdfOptions.cs +++ b/SrcMod/Shell/Valve/Vkv/VkvOptions.cs @@ -1,8 +1,8 @@ -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.Vkv; -public record class VdfOptions +public record class VkvOptions { - public static VdfOptions Default => new(); + public static VkvOptions Default => new(); public bool closeWhenFinished; public int indentSize; @@ -11,7 +11,7 @@ public record class VdfOptions public bool useEscapeCodes; public bool useQuotes; - public VdfOptions() + public VkvOptions() { closeWhenFinished = true; indentSize = 4; diff --git a/SrcMod/Shell/Valve/VdfSerializer.cs b/SrcMod/Shell/Valve/Vkv/VkvSerializer.cs similarity index 59% rename from SrcMod/Shell/Valve/VdfSerializer.cs rename to SrcMod/Shell/Valve/Vkv/VkvSerializer.cs index e59ac67..53e25c4 100644 --- a/SrcMod/Shell/Valve/VdfSerializer.cs +++ b/SrcMod/Shell/Valve/Vkv/VkvSerializer.cs @@ -1,22 +1,22 @@ -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.Vkv; -public class VdfSerializer +public class VkvSerializer { - public VdfOptions Options => p_options; + public VkvOptions Options => p_options; - private readonly VdfOptions p_options; + private readonly VkvOptions p_options; - public VdfSerializer() : this(VdfOptions.Default) { } - public VdfSerializer(VdfOptions options) + public VkvSerializer() : this(VkvOptions.Default) { } + public VkvSerializer(VkvOptions options) { p_options = options; } - public VdfNode? Deserialize(Stream stream) + public VkvNode? Deserialize(Stream stream) { long pos = stream.Position; StreamReader reader = new(stream, leaveOpen: !p_options.closeWhenFinished); - VdfNode? result = VdfConvert.DeserializeNode(reader, p_options); + VkvNode? result = VkvConvert.DeserializeNode(reader, p_options); reader.Close(); if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); @@ -25,14 +25,14 @@ public class VdfSerializer public void Serialize(Stream stream, object? value, string parentNodeName) { - VdfNode? nodeTree = VdfConvert.ToNodeTree(value, p_options); + VkvNode? nodeTree = VkvConvert.ToNodeTree(value, p_options); Serialize(stream, nodeTree, parentNodeName); } - public void Serialize(Stream stream, VdfNode? parentNode, string parentNodeName) + public void Serialize(Stream stream, VkvNode? parentNode, string parentNodeName) { long pos = stream.Position; StreamWriter writer = new(stream, leaveOpen: !p_options.closeWhenFinished); - VdfConvert.SerializeNode(writer, parentNode, parentNodeName, p_options); + VkvConvert.SerializeNode(writer, parentNode, parentNodeName, p_options); writer.Close(); if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); diff --git a/SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs b/SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs new file mode 100644 index 0000000..7285ed2 --- /dev/null +++ b/SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs @@ -0,0 +1,11 @@ +namespace SrcMod.Shell.Valve.Vkv; + +public class VkvSingleNode : VkvNode +{ + public object? value; + + public VkvSingleNode(object? value = null) : base() + { + this.value = value; + } +} diff --git a/SrcMod/Shell/Valve/VdfTreeNode.cs b/SrcMod/Shell/Valve/Vkv/VkvTreeNode.cs similarity index 62% rename from SrcMod/Shell/Valve/VdfTreeNode.cs rename to SrcMod/Shell/Valve/Vkv/VkvTreeNode.cs index 610b231..bdb9cde 100644 --- a/SrcMod/Shell/Valve/VdfTreeNode.cs +++ b/SrcMod/Shell/Valve/Vkv/VkvTreeNode.cs @@ -1,21 +1,21 @@ -namespace SrcMod.Shell.Valve; +namespace SrcMod.Shell.Valve.Vkv; -public class VdfTreeNode : VdfNode, IEnumerable> +public class VkvTreeNode : VkvNode, IEnumerable> { public int SubNodeCount => p_subNodes.Count; - private readonly Dictionary p_subNodes; + private readonly Dictionary p_subNodes; - public VdfTreeNode(Dictionary? subNodes = null) : base() + public VkvTreeNode(Dictionary? subNodes = null) : base() { p_subNodes = subNodes ?? new(); } - public VdfNode? this[string key] + public VkvNode? this[string key] { get { - if (p_subNodes.TryGetValue(key, out VdfNode? value)) return value; + if (p_subNodes.TryGetValue(key, out VkvNode? value)) return value; else return null; } set @@ -24,7 +24,7 @@ public class VdfTreeNode : VdfNode, IEnumerable> else p_subNodes.Add(key, value); } } - public VdfNode? this[int index] + public VkvNode? this[int index] { get { @@ -38,8 +38,8 @@ public class VdfTreeNode : VdfNode, IEnumerable> } } - public void Add(string key, VdfNode? value) => this[key] = value; + public void Add(string key, VkvNode? value) => this[key] = value; IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); + public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); } -- 2.49.0.windows.1 From 3c0c3068a483a31f2aa6c55cc22e7ae2982a8d3c Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 9 May 2023 19:55:13 -0400 Subject: [PATCH 63/89] Moved the valve parsers to their own library. --- .gitignore | 1 - SrcMod/Shell/GlobalUsings.cs | 2 +- SrcMod/Shell/Shell.csproj | 14 +--- .../Valve/Vkv/ObjectModels/IVkvConvertible.cs | 8 -- SrcMod/Shell/Valve/Vkv/VkvNode.cs | 3 - SrcMod/SrcMod.sln | 31 ++++++++ .../Valve.NET/Miscellaneous/GlobalUsings.cs | 16 ++++ SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs | 39 ++++++++++ SrcMod/Valve.NET/Valve.NET.csproj | 17 ++++ .../Vkv/ObjectModels/IVkvConvertible.cs | 6 ++ .../Vkv/ObjectModels/VkvIgnoreAttribute.cs | 2 +- .../ObjectModels/VkvSerializationException.cs | 2 +- .../Valve => Valve.NET}/Vkv/VkvConvert.cs | 4 +- SrcMod/Valve.NET/Vkv/VkvNode.cs | 3 + .../Valve => Valve.NET}/Vkv/VkvOptions.cs | 2 +- .../Valve => Valve.NET}/Vkv/VkvSerializer.cs | 2 +- .../Valve => Valve.NET}/Vkv/VkvSingleNode.cs | 2 +- .../Valve => Valve.NET}/Vkv/VkvTreeNode.cs | 2 +- ...CoreApp,Version=v7.0.AssemblyAttributes.cs | 4 + .../obj/Debug/Valve.NET.AssemblyInfo.cs | 23 ++++++ .../Debug/Valve.NET.AssemblyInfoInputs.cache | 1 + ....GeneratedMSBuildEditorConfig.editorconfig | 11 +++ .../obj/Debug/Valve.NET.assets.cache | Bin 0 -> 224 bytes .../Valve.NET.csproj.AssemblyReference.cache | Bin 0 -> 93295 bytes .../Valve.NET.csproj.CoreCompileInputs.cache | 1 + .../Valve.NET.csproj.FileListAbsolute.txt | 12 +++ ...CoreApp,Version=v7.0.AssemblyAttributes.cs | 4 + .../Debug/net7.0/Valve.NET.AssemblyInfo.cs | 23 ++++++ .../net7.0/Valve.NET.AssemblyInfoInputs.cache | 1 + ....GeneratedMSBuildEditorConfig.editorconfig | 11 +++ .../Debug/net7.0/Valve.NET.GlobalUsings.g.cs | 8 ++ .../obj/Debug/net7.0/Valve.NET.assets.cache | Bin 0 -> 224 bytes .../Valve.NET.csproj.AssemblyReference.cache | Bin 0 -> 93295 bytes SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll | Bin 0 -> 10240 bytes .../Valve.NET/obj/Debug/refint/valve.net.dll | Bin 0 -> 10240 bytes SrcMod/Valve.NET/obj/Debug/valve.net.dll | Bin 0 -> 32256 bytes SrcMod/Valve.NET/obj/Debug/valve.net.pdb | Bin 0 -> 17564 bytes .../obj/Valve.NET.csproj.nuget.dgspec.json | 67 ++++++++++++++++ .../obj/Valve.NET.csproj.nuget.g.props | 16 ++++ .../obj/Valve.NET.csproj.nuget.g.targets | 2 + SrcMod/Valve.NET/obj/project.assets.json | 73 ++++++++++++++++++ SrcMod/Valve.NET/obj/project.nuget.cache | 8 ++ 42 files changed, 390 insertions(+), 31 deletions(-) delete mode 100644 SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs delete mode 100644 SrcMod/Shell/Valve/Vkv/VkvNode.cs create mode 100644 SrcMod/SrcMod.sln create mode 100644 SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs create mode 100644 SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs create mode 100644 SrcMod/Valve.NET/Valve.NET.csproj create mode 100644 SrcMod/Valve.NET/Vkv/ObjectModels/IVkvConvertible.cs rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/ObjectModels/VkvIgnoreAttribute.cs (76%) rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/ObjectModels/VkvSerializationException.cs (84%) rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/VkvConvert.cs (99%) create mode 100644 SrcMod/Valve.NET/Vkv/VkvNode.cs rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/VkvOptions.cs (93%) rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/VkvSerializer.cs (97%) rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/VkvSingleNode.cs (81%) rename SrcMod/{Shell/Valve => Valve.NET}/Vkv/VkvTreeNode.cs (97%) create mode 100644 SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.assets.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.AssemblyReference.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.assets.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.csproj.AssemblyReference.cache create mode 100644 SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll create mode 100644 SrcMod/Valve.NET/obj/Debug/refint/valve.net.dll create mode 100644 SrcMod/Valve.NET/obj/Debug/valve.net.dll create mode 100644 SrcMod/Valve.NET/obj/Debug/valve.net.pdb create mode 100644 SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json create mode 100644 SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props create mode 100644 SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets create mode 100644 SrcMod/Valve.NET/obj/project.assets.json create mode 100644 SrcMod/Valve.NET/obj/project.nuget.cache diff --git a/.gitignore b/.gitignore index 6671a1c..31b0e33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # Visual Studio stuff .vs/ SrcMod/.vs/ -*.sln # Compiled Files SrcMod/Compiled diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/GlobalUsings.cs index a30eee1..92bd543 100644 --- a/SrcMod/Shell/GlobalUsings.cs +++ b/SrcMod/Shell/GlobalUsings.cs @@ -7,7 +7,6 @@ global using SrcMod.Shell.Extensions; global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; -global using SrcMod.Shell.Valve; global using System; global using System.Collections; global using System.Collections.Generic; @@ -21,4 +20,5 @@ global using System.Reflection; global using System.Runtime.InteropServices; global using System.Text; global using System.Threading; +global using Valve.Vkv; global using static SrcMod.Shell.Tools; diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index 253835f..56f71be 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -16,16 +16,6 @@ true - - embedded - 9999 - - - - embedded - 9999 - - @@ -36,4 +26,8 @@ + + + + diff --git a/SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs b/SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs deleted file mode 100644 index 8bc6364..0000000 --- a/SrcMod/Shell/Valve/Vkv/ObjectModels/IVkvConvertible.cs +++ /dev/null @@ -1,8 +0,0 @@ -using SrcMod.Shell.Valve.Vkv; - -namespace SrcMod.Shell.Valve.Vkv.ObjectModels; - -public interface IVkvConvertible -{ - public VkvNode ToNodeTree(); -} \ No newline at end of file diff --git a/SrcMod/Shell/Valve/Vkv/VkvNode.cs b/SrcMod/Shell/Valve/Vkv/VkvNode.cs deleted file mode 100644 index 2f7a9da..0000000 --- a/SrcMod/Shell/Valve/Vkv/VkvNode.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace SrcMod.Shell.Valve.Vkv; - -public abstract class VkvNode { } diff --git a/SrcMod/SrcMod.sln b/SrcMod/SrcMod.sln new file mode 100644 index 0000000..22100d5 --- /dev/null +++ b/SrcMod/SrcMod.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33213.308 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shell", "Shell\Shell.csproj", "{6EC87235-F2A5-4313-A6DE-A4EE7CB7B341}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Valve.NET", "Valve.NET\Valve.NET.csproj", "{8FC96202-2F7E-4FBE-B08E-FCC38AA62D96}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6EC87235-F2A5-4313-A6DE-A4EE7CB7B341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EC87235-F2A5-4313-A6DE-A4EE7CB7B341}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6EC87235-F2A5-4313-A6DE-A4EE7CB7B341}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6EC87235-F2A5-4313-A6DE-A4EE7CB7B341}.Release|Any CPU.Build.0 = Release|Any CPU + {8FC96202-2F7E-4FBE-B08E-FCC38AA62D96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FC96202-2F7E-4FBE-B08E-FCC38AA62D96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FC96202-2F7E-4FBE-B08E-FCC38AA62D96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FC96202-2F7E-4FBE-B08E-FCC38AA62D96}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4E25AC28-DD70-4BB6-9083-07D6371DECCF} + EndGlobalSection +EndGlobal diff --git a/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs b/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs new file mode 100644 index 0000000..fcfd555 --- /dev/null +++ b/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs @@ -0,0 +1,16 @@ +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.ComponentModel; +global using System.Diagnostics; +global using System.Formats.Tar; +global using System.IO; +global using System.IO.Compression; +global using System.Linq; +global using System.Reflection; +global using System.Runtime.InteropServices; +global using System.Text; +global using System.Threading; +global using Valve; +global using Valve.Miscellaneous; +global using Valve.Vkv; diff --git a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs new file mode 100644 index 0000000..c9b4ced --- /dev/null +++ b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs @@ -0,0 +1,39 @@ +namespace Valve.Miscellaneous; + +internal static class TypeParsers +{ + public static bool CanParse(object? obj) => obj is not null && obj is sbyte or byte or short or ushort or int + or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal + or char or DateOnly or DateTime or DateTimeOffset or Guid or TimeOnly or TimeSpan; + public static object ParseAll(string msg) + { + if (TryParse(msg, out sbyte int8)) return int8; + if (TryParse(msg, out byte uInt8)) return uInt8; + if (TryParse(msg, out short int16)) return int16; + if (TryParse(msg, out ushort uInt16)) return uInt16; + if (TryParse(msg, out int int32)) return int32; + if (TryParse(msg, out uint uInt32)) return uInt32; + if (TryParse(msg, out long int64)) return int64; + if (TryParse(msg, out ulong uInt64)) return uInt64; + if (TryParse(msg, out Int128 int128)) return int128; + if (TryParse(msg, out UInt128 uInt128)) return uInt128; + if (TryParse(msg, out nint intPtr)) return intPtr; + if (TryParse(msg, out nuint uIntPtr)) return uIntPtr; + if (TryParse(msg, out Half float16)) return float16; + if (TryParse(msg, out float float32)) return float32; + if (TryParse(msg, out double float64)) return float64; + if (TryParse(msg, out decimal float128)) return float128; + if (TryParse(msg, out char resChar)) return resChar; + if (TryParse(msg, out DateOnly dateOnly)) return dateOnly; + if (TryParse(msg, out DateTime dateTime)) return dateTime; + if (TryParse(msg, out DateTimeOffset dateTimeOffset)) return dateTimeOffset; + if (TryParse(msg, out Guid guid)) return guid; + if (TryParse(msg, out TimeOnly timeOnly)) return timeOnly; + if (TryParse(msg, out TimeSpan timeSpan)) return timeSpan; + + return msg; + } + + public static bool TryParse(string msg, out T? result) where T : IParsable + => T.TryParse(msg, null, out result); +} diff --git a/SrcMod/Valve.NET/Valve.NET.csproj b/SrcMod/Valve.NET/Valve.NET.csproj new file mode 100644 index 0000000..cfa86ac --- /dev/null +++ b/SrcMod/Valve.NET/Valve.NET.csproj @@ -0,0 +1,17 @@ + + + + Library + net7.0 + disable + enable + valve.net + Valve + ../Compiled/Valve.NET + Valve.NET + That_One_Nerd + false + true + + + diff --git a/SrcMod/Valve.NET/Vkv/ObjectModels/IVkvConvertible.cs b/SrcMod/Valve.NET/Vkv/ObjectModels/IVkvConvertible.cs new file mode 100644 index 0000000..c52e3a0 --- /dev/null +++ b/SrcMod/Valve.NET/Vkv/ObjectModels/IVkvConvertible.cs @@ -0,0 +1,6 @@ +namespace Valve.Vkv.ObjectModels; + +public interface IVkvConvertible +{ + public VkvNode ToNodeTree(); +} \ No newline at end of file diff --git a/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvIgnoreAttribute.cs b/SrcMod/Valve.NET/Vkv/ObjectModels/VkvIgnoreAttribute.cs similarity index 76% rename from SrcMod/Shell/Valve/Vkv/ObjectModels/VkvIgnoreAttribute.cs rename to SrcMod/Valve.NET/Vkv/ObjectModels/VkvIgnoreAttribute.cs index 7fab5fa..6872087 100644 --- a/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvIgnoreAttribute.cs +++ b/SrcMod/Valve.NET/Vkv/ObjectModels/VkvIgnoreAttribute.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.Vkv.ObjectModels; +namespace Valve.Vkv.ObjectModels; [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public class VkvIgnoreAttribute : Attribute { } diff --git a/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs b/SrcMod/Valve.NET/Vkv/ObjectModels/VkvSerializationException.cs similarity index 84% rename from SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs rename to SrcMod/Valve.NET/Vkv/ObjectModels/VkvSerializationException.cs index 2995971..4714ce8 100644 --- a/SrcMod/Shell/Valve/Vkv/ObjectModels/VkvSerializationException.cs +++ b/SrcMod/Valve.NET/Vkv/ObjectModels/VkvSerializationException.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.Vkv.ObjectModels; +namespace Valve.Vkv.ObjectModels; public class VkvSerializationException : Exception { diff --git a/SrcMod/Shell/Valve/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs similarity index 99% rename from SrcMod/Shell/Valve/Vkv/VkvConvert.cs rename to SrcMod/Valve.NET/Vkv/VkvConvert.cs index 76007b0..4c91189 100644 --- a/SrcMod/Shell/Valve/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -1,6 +1,6 @@ -using SrcMod.Shell.Valve.Vkv.ObjectModels; +using Valve.Vkv.ObjectModels; -namespace SrcMod.Shell.Valve.Vkv; +namespace Valve.Vkv; public static class VkvConvert { diff --git a/SrcMod/Valve.NET/Vkv/VkvNode.cs b/SrcMod/Valve.NET/Vkv/VkvNode.cs new file mode 100644 index 0000000..70fbcd9 --- /dev/null +++ b/SrcMod/Valve.NET/Vkv/VkvNode.cs @@ -0,0 +1,3 @@ +namespace Valve.Vkv; + +public abstract class VkvNode { } diff --git a/SrcMod/Shell/Valve/Vkv/VkvOptions.cs b/SrcMod/Valve.NET/Vkv/VkvOptions.cs similarity index 93% rename from SrcMod/Shell/Valve/Vkv/VkvOptions.cs rename to SrcMod/Valve.NET/Vkv/VkvOptions.cs index de8ce23..72ad902 100644 --- a/SrcMod/Shell/Valve/Vkv/VkvOptions.cs +++ b/SrcMod/Valve.NET/Vkv/VkvOptions.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.Vkv; +namespace Valve.Vkv; public record class VkvOptions { diff --git a/SrcMod/Shell/Valve/Vkv/VkvSerializer.cs b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs similarity index 97% rename from SrcMod/Shell/Valve/Vkv/VkvSerializer.cs rename to SrcMod/Valve.NET/Vkv/VkvSerializer.cs index 53e25c4..0724a0a 100644 --- a/SrcMod/Shell/Valve/Vkv/VkvSerializer.cs +++ b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.Vkv; +namespace Valve.Vkv; public class VkvSerializer { diff --git a/SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs b/SrcMod/Valve.NET/Vkv/VkvSingleNode.cs similarity index 81% rename from SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs rename to SrcMod/Valve.NET/Vkv/VkvSingleNode.cs index 7285ed2..9b77410 100644 --- a/SrcMod/Shell/Valve/Vkv/VkvSingleNode.cs +++ b/SrcMod/Valve.NET/Vkv/VkvSingleNode.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.Vkv; +namespace Valve.Vkv; public class VkvSingleNode : VkvNode { diff --git a/SrcMod/Shell/Valve/Vkv/VkvTreeNode.cs b/SrcMod/Valve.NET/Vkv/VkvTreeNode.cs similarity index 97% rename from SrcMod/Shell/Valve/Vkv/VkvTreeNode.cs rename to SrcMod/Valve.NET/Vkv/VkvTreeNode.cs index bdb9cde..6073922 100644 --- a/SrcMod/Shell/Valve/Vkv/VkvTreeNode.cs +++ b/SrcMod/Valve.NET/Vkv/VkvTreeNode.cs @@ -1,4 +1,4 @@ -namespace SrcMod.Shell.Valve.Vkv; +namespace Valve.Vkv; public class VkvTreeNode : VkvNode, IEnumerable> { diff --git a/SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs b/SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs new file mode 100644 index 0000000..4257f4b --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")] diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs b/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs new file mode 100644 index 0000000..d2f66ad --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("That_One_Nerd")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("valve.net")] +[assembly: System.Reflection.AssemblyTitleAttribute("valve.net")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache b/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache new file mode 100644 index 0000000..0f86789 --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +8384044beff55be9a171a490a3f710f4f9552cee diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig b/SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..ddd2b10 --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,11 @@ +is_global = true +build_property.TargetFramework = net7.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = Valve +build_property.ProjectDir = C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\ diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.assets.cache b/SrcMod/Valve.NET/obj/Debug/Valve.NET.assets.cache new file mode 100644 index 0000000000000000000000000000000000000000..ba0ef2b9abf450b214c62c778a924b9e1b6bb6b8 GIT binary patch literal 224 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 M?PUj*s9CrFKOus5lmGw# literal 0 HcmV?d00001 diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache b/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..6dce354 --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +78977cdcf4d04d878ec8161bd57fe5f8f0d3f8af diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt b/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..fac96e7 --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt @@ -0,0 +1,12 @@ +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.csproj.AssemblyReference.cache +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.AssemblyInfoInputs.cache +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.AssemblyInfo.cs +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.csproj.CoreCompileInputs.cache +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Compiled\Valve.NET\valve.net.deps.json +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Compiled\Valve.NET\valve.net.dll +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Compiled\Valve.NET\valve.net.pdb +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\valve.net.dll +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\refint\valve.net.dll +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\valve.net.pdb +C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\ref\valve.net.dll diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs b/SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs new file mode 100644 index 0000000..4257f4b --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")] diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs new file mode 100644 index 0000000..a2a47af --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("Valve.NET")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("Valve.NET")] +[assembly: System.Reflection.AssemblyTitleAttribute("Valve.NET")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache new file mode 100644 index 0000000..bd887cd --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +ebac0703b803bca2e82867dfb1a594d2351f56a0 diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..9d8e0ad --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,11 @@ +is_global = true +build_property.TargetFramework = net7.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = Valve.NET +build_property.ProjectDir = C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\ diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs new file mode 100644 index 0000000..8578f3d --- /dev/null +++ b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs @@ -0,0 +1,8 @@ +// +global using global::System; +global using global::System.Collections.Generic; +global using global::System.IO; +global using global::System.Linq; +global using global::System.Net.Http; +global using global::System.Threading; +global using global::System.Threading.Tasks; diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.assets.cache b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.assets.cache new file mode 100644 index 0000000000000000000000000000000000000000..d08c285018dafd277d89f3f19fbcc898156ed0a3 GIT binary patch literal 224 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 M?PUj*s9CrFKOus5lmGw# literal 0 HcmV?d00001 diff --git a/SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll b/SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll new file mode 100644 index 0000000000000000000000000000000000000000..810100aea8bddc91db3b3f78b421f19362a890e9 GIT binary patch literal 10240 zcmeHNe{dA{b$`2ids<0Bh%2HP3pfzixZtw{GMI!P5|RMf76^1ep>d_v-AY>PZdcmf z6IN#8isCSdn~r05N}RUwKuJ7Fnr58V9y^`s6l%wHJL68K88@A2riB_h;|b$V+G(14 z8oQtO_Q#!s>~#89r}m2d?0cX0zVG|K-+lYtyBYIFt(ZgTtxfJ(ymDXn)m3E?5Fh1-b`@*vRwd1ibf-! zVORcFJw_^1*bKxy%)$uK2A+t8+Z@ryz}-9C2e*m!MH zNvC`l(bKmPDNOz^wua@OqJ2a6?^B`(yw1#Y=Gt@H+P8J=#KT0p9yX%liO;jGGO{ zeENWzriX-iT;xwH%fQ<(o0=79Jtm4r76enRkw;5aZ%0dcg6 z^o)_Fzt*|0$0WCv+Ou_O`evH(6iqU(OsWm^Tfj7(5oTLj+9CpXx`!tVGlj59GX>go z-OfaN9b;sT&rvho#LVr4jGGg*-xWFjH z#B8K{NL$xT<4Bjat++K7>IQ(1>PLY8uIG{8KUyQU@>G#xn?Y2bwY~7NorhK+8qpgZ32+o(O#{#p4!+Sb~+bg;du z>)Nc=5x0|b^!{2i)!H7_wnpvF)2Mb%>rAv4_21C$O|(hv3)=Qb3uo}Yuyde7X7X$t z$|`*iD?qp@bOOt}O8_7lR_a~)T~wgAP;ZU& z67U!33h;Ki3TzX8GrbLY8*NGD=o7RT*hBXNAD|P!AsPk#3UHgm?2%|a7}Hx?AMP1X zs|8^S!W3wdPN#~JgC+iF#d=n(XJLINbxD{@!dwFL-PG5`|7HBZx|w=eTD>C7UkYjp z^P0jVN&%-+ZNjt((*t=r)g$tV$fn2z@hL>IPyd=KLY_{|iO(6~&x+4QkuNEe^k1pV z3eVLQVO|#N%OYPBd{dY=MZON4PAMv9rC|=<(z1fS(q!rTovZ3FxP}3jr&zJ&LJ!EI+42tO~EsQ7X`lpoK9U4`I?}T zl34{#r`CzwEocfBg+C+mg%pqCqR5v;z9RA~sa4dbUlaK{a5~kiGhWr%|GLPj^eVbX zzn*5^z*Sj~>$8!cT4GxAboc{*k6q6TDSCW$M6HR0mv# z2r9K9hJt!;guIdX$>t7VBMstiemkzM9h92mHK2CeifcN#^kLXb2hq<$?pbkZ#M6O7wPyqE+Oul!fWrgU>~XVHu?9`sgW78s0^4;=Z&n&cXJuP5 zA(4a$Nw_N28M{RSyzY&uNC34xrXm5mIjRxeI9S`=cR9=BAoWQ2b1faO@8U7+q_kqRZ(w@yr0&VJjm z{Ryi`2dv1+4TZk)s8uXl#bk=8$1P9UCCiifFoRlC;&hDjN;K-VMl0jvd=XW-LzPl# zKGW^{R(Z5Eo412nM+~Tc+;P2{wt3SVw}Sn6F>9T6y~%3OIK+M=c--=Ql;*9*erL?} z%BIw9>3zL0iDUM7#S_13kX~!dtdxQQWNLX;`lvNFWR6+E>`|1MU**Hek{Cy=lKF^8 zHTF2+K@Y`Q2&xU^=|LL&*0gFsPZr9gV8u zImZfeMQCuh%rg1m0q1kLAD1Qhu@F`%MO`F4TVv4`Ngk35!YG5TZ}a)&OE1n|rn>Ku zf;AhDiGya~kWY{n&lg(Zk?KkS?<)HLa}O_aVL*abh15}nIjd>LZ6Gj_r9 zsp4CGe!-lwcn$KSYYyYUvIo_#jPkkxAzpH#X|ThlM=EXrDK0xc***=}1<&=}u>idl zt!|vmS>N`FZ;2(Ja38?w#ISRRM<2#2$sK`?R+pO55}(||avIQTawZnth#JInM^}_j zybejlcs?Z+9A5Bomjkw6u&{bK7Vf7KTrxsY^VQ;+g@D40suf2iYb+pC&ncO#o~6v(mzO}hsI)Ab`>NWMX=U3B${I4B+dKSg%id`C zI6uFUmR_x^Y5X(Pw5q0CwREPdDczDere;pIWF7*lD@BczmW-)JqH2VGmbyOjsG3?b zHr%SZx+QX1K(}Pd@LNEtt&#I$Hg)v}7&9lM+^1VI6*V)R1O2G2=m!M*qVg5ge_fWloO{y9BI?|etxffzfUY>P)uc6c?PS!vcEM>J#WayhXxS(Mu z(bwBG{AMt(t~lYDQ-@q9xxwToJomJ(z^_hz^`sbgA77@XwnR6x-7`CK z?TFH}Jb8xcwf(7*Im-`e2Diw@*L1EyjxN5&e5eZzQ1rEvlx*H&64#>ttEV|<)X7JIME#o>tOndH3V z@v#=p$_Mq;i8rhGa)cNz`mbO@ne}`J? literal 0 HcmV?d00001 diff --git a/SrcMod/Valve.NET/obj/Debug/refint/valve.net.dll b/SrcMod/Valve.NET/obj/Debug/refint/valve.net.dll new file mode 100644 index 0000000000000000000000000000000000000000..810100aea8bddc91db3b3f78b421f19362a890e9 GIT binary patch literal 10240 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 literal 0 HcmV?d00001 diff --git a/SrcMod/Valve.NET/obj/Debug/valve.net.dll b/SrcMod/Valve.NET/obj/Debug/valve.net.dll new file mode 100644 index 0000000000000000000000000000000000000000..a82e5e2394cc2a67ef02d7592eae232a8abb9a7a GIT binary patch literal 32256 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�=zw&PWA4< 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 literal 0 HcmV?d00001 diff --git a/SrcMod/Valve.NET/obj/Debug/valve.net.pdb b/SrcMod/Valve.NET/obj/Debug/valve.net.pdb new file mode 100644 index 0000000000000000000000000000000000000000..ee52091284bf0fa2bb749f89deb52520615cfbd7 GIT binary patch literal 17564 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 Wr)#U1r)#H|r*qKD)3xtR$o~PwU8dUr literal 0 HcmV?d00001 diff --git a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json new file mode 100644 index 0000000..9f65cfa --- /dev/null +++ b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "restore": { + "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj": {} + }, + "projects": { + "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", + "projectName": "valve.net", + "projectPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", + "packagesPath": "C:\\Users\\kyley\\.nuget\\packages\\", + "outputPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\kyley\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net7.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net7.0": { + "targetAlias": "net7.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "net7.0": { + "targetAlias": "net7.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.102\\RuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props new file mode 100644 index 0000000..23595a9 --- /dev/null +++ b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props @@ -0,0 +1,16 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\kyley\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages + PackageReference + 6.4.0 + + + + + + \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets new file mode 100644 index 0000000..3dc06ef --- /dev/null +++ b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/project.assets.json b/SrcMod/Valve.NET/obj/project.assets.json new file mode 100644 index 0000000..e417e12 --- /dev/null +++ b/SrcMod/Valve.NET/obj/project.assets.json @@ -0,0 +1,73 @@ +{ + "version": 3, + "targets": { + "net7.0": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + "net7.0": [] + }, + "packageFolders": { + "C:\\Users\\kyley\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", + "projectName": "valve.net", + "projectPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", + "packagesPath": "C:\\Users\\kyley\\.nuget\\packages\\", + "outputPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\kyley\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net7.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net7.0": { + "targetAlias": "net7.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "net7.0": { + "targetAlias": "net7.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.102\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/project.nuget.cache b/SrcMod/Valve.NET/obj/project.nuget.cache new file mode 100644 index 0000000..2cdec42 --- /dev/null +++ b/SrcMod/Valve.NET/obj/project.nuget.cache @@ -0,0 +1,8 @@ +{ + "version": 2, + "dgSpecHash": "VNCH38jqwFWTxqqhzzVLR2Jf7UiV9/z5LUDVmpzOUafOLLW71x935fAZ5UA8qi4cycxqviPPFxSNjR5kf0EesQ==", + "success": true, + "projectFilePath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", + "expectedPackageFiles": [], + "logs": [] +} \ No newline at end of file -- 2.49.0.windows.1 From 154d21ee139f93b98f9a6b5e0de55e38cee5a550 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 9 May 2023 22:18:00 -0400 Subject: [PATCH 64/89] Whoops. --- ...CoreApp,Version=v7.0.AssemblyAttributes.cs | 4 - .../obj/Debug/Valve.NET.AssemblyInfo.cs | 23 ------ .../Debug/Valve.NET.AssemblyInfoInputs.cache | 1 - ....GeneratedMSBuildEditorConfig.editorconfig | 11 --- .../obj/Debug/Valve.NET.assets.cache | Bin 224 -> 0 bytes .../Valve.NET.csproj.AssemblyReference.cache | Bin 93295 -> 0 bytes .../Valve.NET.csproj.CoreCompileInputs.cache | 1 - .../Valve.NET.csproj.FileListAbsolute.txt | 12 --- ...CoreApp,Version=v7.0.AssemblyAttributes.cs | 4 - .../Debug/net7.0/Valve.NET.AssemblyInfo.cs | 23 ------ .../net7.0/Valve.NET.AssemblyInfoInputs.cache | 1 - ....GeneratedMSBuildEditorConfig.editorconfig | 11 --- .../Debug/net7.0/Valve.NET.GlobalUsings.g.cs | 8 -- .../obj/Debug/net7.0/Valve.NET.assets.cache | Bin 224 -> 0 bytes .../Valve.NET.csproj.AssemblyReference.cache | Bin 93295 -> 0 bytes SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll | Bin 10240 -> 0 bytes .../Valve.NET/obj/Debug/refint/valve.net.dll | Bin 10240 -> 0 bytes SrcMod/Valve.NET/obj/Debug/valve.net.dll | Bin 32256 -> 0 bytes SrcMod/Valve.NET/obj/Debug/valve.net.pdb | Bin 17564 -> 0 bytes .../obj/Valve.NET.csproj.nuget.dgspec.json | 67 ---------------- .../obj/Valve.NET.csproj.nuget.g.props | 16 ---- .../obj/Valve.NET.csproj.nuget.g.targets | 2 - SrcMod/Valve.NET/obj/project.assets.json | 73 ------------------ SrcMod/Valve.NET/obj/project.nuget.cache | 8 -- 24 files changed, 265 deletions(-) delete mode 100644 SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.assets.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.AssemblyReference.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.assets.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.csproj.AssemblyReference.cache delete mode 100644 SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll delete mode 100644 SrcMod/Valve.NET/obj/Debug/refint/valve.net.dll delete mode 100644 SrcMod/Valve.NET/obj/Debug/valve.net.dll delete mode 100644 SrcMod/Valve.NET/obj/Debug/valve.net.pdb delete mode 100644 SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json delete mode 100644 SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props delete mode 100644 SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets delete mode 100644 SrcMod/Valve.NET/obj/project.assets.json delete mode 100644 SrcMod/Valve.NET/obj/project.nuget.cache diff --git a/SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs b/SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs deleted file mode 100644 index 4257f4b..0000000 --- a/SrcMod/Valve.NET/obj/Debug/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs +++ /dev/null @@ -1,4 +0,0 @@ -// -using System; -using System.Reflection; -[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")] diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs b/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs deleted file mode 100644 index d2f66ad..0000000 --- a/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Reflection; - -[assembly: System.Reflection.AssemblyCompanyAttribute("That_One_Nerd")] -[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] -[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] -[assembly: System.Reflection.AssemblyProductAttribute("valve.net")] -[assembly: System.Reflection.AssemblyTitleAttribute("valve.net")] -[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] - -// Generated by the MSBuild WriteCodeFragment class. - diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache b/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache deleted file mode 100644 index 0f86789..0000000 --- a/SrcMod/Valve.NET/obj/Debug/Valve.NET.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -8384044beff55be9a171a490a3f710f4f9552cee diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig b/SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig deleted file mode 100644 index ddd2b10..0000000 --- a/SrcMod/Valve.NET/obj/Debug/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -is_global = true -build_property.TargetFramework = net7.0 -build_property.TargetPlatformMinVersion = -build_property.UsingMicrosoftNETSdkWeb = -build_property.ProjectTypeGuids = -build_property.InvariantGlobalization = -build_property.PlatformNeutralAssembly = -build_property.EnforceExtendedAnalyzerRules = -build_property._SupportedPlatformList = Linux,macOS,Windows -build_property.RootNamespace = Valve -build_property.ProjectDir = C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\ diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.assets.cache b/SrcMod/Valve.NET/obj/Debug/Valve.NET.assets.cache deleted file mode 100644 index ba0ef2b9abf450b214c62c778a924b9e1b6bb6b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 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 M?PUj*s9CrFKOus5lmGw# diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache b/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache deleted file mode 100644 index 6dce354..0000000 --- a/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.CoreCompileInputs.cache +++ /dev/null @@ -1 +0,0 @@ -78977cdcf4d04d878ec8161bd57fe5f8f0d3f8af diff --git a/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt b/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt deleted file mode 100644 index fac96e7..0000000 --- a/SrcMod/Valve.NET/obj/Debug/Valve.NET.csproj.FileListAbsolute.txt +++ /dev/null @@ -1,12 +0,0 @@ -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.csproj.AssemblyReference.cache -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.GeneratedMSBuildEditorConfig.editorconfig -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.AssemblyInfoInputs.cache -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.AssemblyInfo.cs -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\Valve.NET.csproj.CoreCompileInputs.cache -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Compiled\Valve.NET\valve.net.deps.json -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Compiled\Valve.NET\valve.net.dll -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Compiled\Valve.NET\valve.net.pdb -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\valve.net.dll -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\refint\valve.net.dll -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\valve.net.pdb -C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\obj\Debug\ref\valve.net.dll diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs b/SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs deleted file mode 100644 index 4257f4b..0000000 --- a/SrcMod/Valve.NET/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs +++ /dev/null @@ -1,4 +0,0 @@ -// -using System; -using System.Reflection; -[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")] diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs deleted file mode 100644 index a2a47af..0000000 --- a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Reflection; - -[assembly: System.Reflection.AssemblyCompanyAttribute("Valve.NET")] -[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] -[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] -[assembly: System.Reflection.AssemblyProductAttribute("Valve.NET")] -[assembly: System.Reflection.AssemblyTitleAttribute("Valve.NET")] -[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] - -// Generated by the MSBuild WriteCodeFragment class. - diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache deleted file mode 100644 index bd887cd..0000000 --- a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -ebac0703b803bca2e82867dfb1a594d2351f56a0 diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig deleted file mode 100644 index 9d8e0ad..0000000 --- a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -is_global = true -build_property.TargetFramework = net7.0 -build_property.TargetPlatformMinVersion = -build_property.UsingMicrosoftNETSdkWeb = -build_property.ProjectTypeGuids = -build_property.InvariantGlobalization = -build_property.PlatformNeutralAssembly = -build_property.EnforceExtendedAnalyzerRules = -build_property._SupportedPlatformList = Linux,macOS,Windows -build_property.RootNamespace = Valve.NET -build_property.ProjectDir = C:\Users\kyley\Desktop\GitHub\SrcMod\SrcMod\Valve.NET\ diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs deleted file mode 100644 index 8578f3d..0000000 --- a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.GlobalUsings.g.cs +++ /dev/null @@ -1,8 +0,0 @@ -// -global using global::System; -global using global::System.Collections.Generic; -global using global::System.IO; -global using global::System.Linq; -global using global::System.Net.Http; -global using global::System.Threading; -global using global::System.Threading.Tasks; diff --git a/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.assets.cache b/SrcMod/Valve.NET/obj/Debug/net7.0/Valve.NET.assets.cache deleted file mode 100644 index d08c285018dafd277d89f3f19fbcc898156ed0a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 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 M?PUj*s9CrFKOus5lmGw# diff --git a/SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll b/SrcMod/Valve.NET/obj/Debug/ref/valve.net.dll deleted file mode 100644 index 810100aea8bddc91db3b3f78b421f19362a890e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10240 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 diff --git a/SrcMod/Valve.NET/obj/Debug/refint/valve.net.dll b/SrcMod/Valve.NET/obj/Debug/refint/valve.net.dll deleted file mode 100644 index 810100aea8bddc91db3b3f78b421f19362a890e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10240 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 diff --git a/SrcMod/Valve.NET/obj/Debug/valve.net.dll b/SrcMod/Valve.NET/obj/Debug/valve.net.dll deleted file mode 100644 index a82e5e2394cc2a67ef02d7592eae232a8abb9a7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32256 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�=zw&PWA4< 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 diff --git a/SrcMod/Valve.NET/obj/Debug/valve.net.pdb b/SrcMod/Valve.NET/obj/Debug/valve.net.pdb deleted file mode 100644 index ee52091284bf0fa2bb749f89deb52520615cfbd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17564 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 Wr)#U1r)#H|r*qKD)3xtR$o~PwU8dUr diff --git a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json deleted file mode 100644 index 9f65cfa..0000000 --- a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.dgspec.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "format": 1, - "restore": { - "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj": {} - }, - "projects": { - "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", - "projectName": "valve.net", - "projectPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", - "packagesPath": "C:\\Users\\kyley\\.nuget\\packages\\", - "outputPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\obj\\", - "projectStyle": "PackageReference", - "fallbackFolders": [ - "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" - ], - "configFilePaths": [ - "C:\\Users\\kyley\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net7.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net7.0": { - "targetAlias": "net7.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - } - }, - "frameworks": { - "net7.0": { - "targetAlias": "net7.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.102\\RuntimeIdentifierGraph.json" - } - } - } - } -} \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props deleted file mode 100644 index 23595a9..0000000 --- a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - True - NuGet - $(MSBuildThisFileDirectory)project.assets.json - $(UserProfile)\.nuget\packages\ - C:\Users\kyley\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages - PackageReference - 6.4.0 - - - - - - \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets b/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets deleted file mode 100644 index 3dc06ef..0000000 --- a/SrcMod/Valve.NET/obj/Valve.NET.csproj.nuget.g.targets +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/project.assets.json b/SrcMod/Valve.NET/obj/project.assets.json deleted file mode 100644 index e417e12..0000000 --- a/SrcMod/Valve.NET/obj/project.assets.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "version": 3, - "targets": { - "net7.0": {} - }, - "libraries": {}, - "projectFileDependencyGroups": { - "net7.0": [] - }, - "packageFolders": { - "C:\\Users\\kyley\\.nuget\\packages\\": {}, - "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} - }, - "project": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", - "projectName": "valve.net", - "projectPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", - "packagesPath": "C:\\Users\\kyley\\.nuget\\packages\\", - "outputPath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\obj\\", - "projectStyle": "PackageReference", - "fallbackFolders": [ - "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" - ], - "configFilePaths": [ - "C:\\Users\\kyley\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net7.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net7.0": { - "targetAlias": "net7.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - } - }, - "frameworks": { - "net7.0": { - "targetAlias": "net7.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.102\\RuntimeIdentifierGraph.json" - } - } - } -} \ No newline at end of file diff --git a/SrcMod/Valve.NET/obj/project.nuget.cache b/SrcMod/Valve.NET/obj/project.nuget.cache deleted file mode 100644 index 2cdec42..0000000 --- a/SrcMod/Valve.NET/obj/project.nuget.cache +++ /dev/null @@ -1,8 +0,0 @@ -{ - "version": 2, - "dgSpecHash": "VNCH38jqwFWTxqqhzzVLR2Jf7UiV9/z5LUDVmpzOUafOLLW71x935fAZ5UA8qi4cycxqviPPFxSNjR5kf0EesQ==", - "success": true, - "projectFilePath": "C:\\Users\\kyley\\Desktop\\GitHub\\SrcMod\\SrcMod\\Valve.NET\\Valve.NET.csproj", - "expectedPackageFiles": [], - "logs": [] -} \ No newline at end of file -- 2.49.0.windows.1 From ab372b3eec93c610c3a19e09b693bb3a4f2d1726 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 9 May 2023 22:19:26 -0400 Subject: [PATCH 65/89] Man, I meant to do this too. Double whoops. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 31b0e33..af9d72e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ SrcMod/.vs/ SrcMod/Compiled SrcMod/Shell/obj/ +SrcMod/Valve.NET/obj + # Personal Stuff SrcMod/Shell/Modules/TestingModule.cs TODO.md -- 2.49.0.windows.1 From 7e1492c664a23f31051f58f14bfac08f9be86072 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 07:59:15 -0400 Subject: [PATCH 66/89] Small improvements. --- SrcMod/Shell/Shell.cs | 2 +- SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs | 9 +- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 99 +++++++++++-------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index bc3aaa7..d353fb2 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -4,7 +4,7 @@ public class Shell { public const string Author = "That_One_Nerd"; public const string Name = "SrcMod"; - public const string Version = "Beta 0.4.0"; + public const string Version = "Beta 0.5.0"; public readonly string? ShellDirectory; diff --git a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs index c9b4ced..0369d68 100644 --- a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs +++ b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs @@ -1,10 +1,17 @@ namespace Valve.Miscellaneous; -internal static class TypeParsers +public static class TypeParsers { public static bool CanParse(object? obj) => obj is not null && obj is sbyte or byte or short or ushort or int or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal or char or DateOnly or DateTime or DateTimeOffset or Guid or TimeOnly or TimeSpan; + public static bool CanParse(Type type) => type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) + || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) + || type == typeof(ulong) || type == typeof(Int128) || type == typeof(UInt128) || type == typeof(nint) + || type == typeof(nuint) || type == typeof(Half) || type == typeof(float) || type == typeof(double) + || type == typeof(decimal) || type == typeof(char) || type == typeof(DateOnly) || type == typeof(DateTime) + || type == typeof(DateTimeOffset) || type == typeof(Guid) || type == typeof(TimeOnly) + || type == typeof(TimeSpan); public static object ParseAll(string msg) { if (TryParse(msg, out sbyte int8)) return int8; diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index 4c91189..d4af015 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -1,5 +1,7 @@ using Valve.Vkv.ObjectModels; +using ValveParsers = Valve.Miscellaneous.TypeParsers; + namespace Valve.Vkv; public static class VkvConvert @@ -68,7 +70,7 @@ public static class VkvConvert } private static object DeserializeObject(string content) => - TypeParsers.ParseAll(content); + ValveParsers.ParseAll(content); private static string DeserializeString(string content, VkvOptions options) { if (options.useQuotes) @@ -118,54 +120,67 @@ public static class VkvConvert { if (node is null) return null; - object? instance = Activator.CreateInstance(outputType); - if (instance is null) return null; - - IEnumerable validFields = from field in outputType.GetFields() - let isPublic = field.IsPublic - let isStatic = field.IsStatic - let isIgnored = field.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - let isConst = field.IsLiteral - where isPublic && !isStatic && !isIgnored && !isConst - select field; - - IEnumerable validProperties; - if (options.serializeProperties) + if (node is VkvSingleNode single) { - validProperties = from prop in outputType.GetProperties() - let canSet = prop.SetMethod is not null - let isPublic = canSet && prop.SetMethod!.IsPublic - let isStatic = canSet && prop.SetMethod!.IsStatic - let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - where canSet && isPublic && !isStatic && !isIgnored - select prop; - } - else validProperties = Array.Empty(); - - foreach (FieldInfo field in validFields) - { - // TODO: check if the node tree has that field. - - Type castType = field.FieldType; - if (TypeParsers.CanParse(instance)) + object? value = single.value; + if (value is null) return null; + else if (value is string str) { - + value = ValveParsers.ParseAll(str); + if (value is string still && outputType.IsEnum) + { + if (Enum.TryParse(outputType, still, true, out object? res) && res is not null) + value = res; + } } + return Convert.ChangeType(value, outputType); } - foreach (PropertyInfo prop in validProperties) + else if (node is VkvTreeNode tree) { - // TODO: check if the node tree has that field. + object? instance = Activator.CreateInstance(outputType); + if (instance is null) return null; - Type castType = prop.PropertyType; - if (TypeParsers.CanParse(instance)) + IEnumerable validFields = from field in outputType.GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + let isIgnored = field.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + let isConst = field.IsLiteral + where isPublic && !isStatic && !isIgnored && !isConst + select field; + + IEnumerable validProperties; + if (options.serializeProperties) { - + validProperties = from prop in outputType.GetProperties() + let canSet = prop.SetMethod is not null + let isPublic = canSet && prop.SetMethod!.IsPublic + let isStatic = canSet && prop.SetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + where canSet && isPublic && !isStatic && !isIgnored + select prop; } - } + else validProperties = Array.Empty(); - return null; + foreach (FieldInfo field in validFields) + { + // TODO: check if the node tree has that field. + + // TODO: + // parsables + // enums + // casting + // sub-conversion + } + foreach (PropertyInfo prop in validProperties) + { + // TODO: check if the node tree has that field. + } + + return null; + } + else throw new VkvSerializationException("Unknown VKV node type."); } #endregion @@ -238,12 +253,12 @@ public static class VkvConvert if (obj is null) return null; Type type = obj.GetType(); - if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj); + if (type.IsPrimitive || ValveParsers.CanParse(obj)) return new VkvSingleNode(obj); else if (type.IsPointer) throw new("Cannot serialize a pointer."); VkvTreeNode tree = new(); - if (obj is IVkvConvertible vdf) return vdf.ToNodeTree(); + if (obj is IVkvConvertible vkv) return vkv.ToNodeTree(); else if (obj is IDictionary dictionary) { object[] keys = new object[dictionary.Count], -- 2.49.0.windows.1 From ab0453e0aba1459a9567b1424faa185c4d203e76 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 09:56:12 -0400 Subject: [PATCH 67/89] Nice progress on the node tree conversion. --- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index d4af015..02a7d8e 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -165,20 +165,28 @@ public static class VkvConvert foreach (FieldInfo field in validFields) { - // TODO: check if the node tree has that field. + string name = field.Name; - // TODO: - // parsables - // enums - // casting - // sub-conversion + VkvNode? subNode = tree[name]; + if (subNode is null) continue; + + object? result = FromNodeTree(field.FieldType, subNode, options); + if (result is null) continue; + field.SetValue(instance, result); } foreach (PropertyInfo prop in validProperties) { - // TODO: check if the node tree has that field. + string name = prop.Name; + + VkvNode? subNode = tree[name]; + if (subNode is null) continue; + + object? result = FromNodeTree(prop.PropertyType, subNode, options); + if (result is null) continue; + prop.SetValue(instance, result); } - return null; + return instance; } else throw new VkvSerializationException("Unknown VKV node type."); } -- 2.49.0.windows.1 From c1a90cfc997f3f3241946f01c8dccebaa0b9bac8 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 12:50:30 -0400 Subject: [PATCH 68/89] Array and list support for VKV. --- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 189 ++++++++++++++++++----------- 1 file changed, 117 insertions(+), 72 deletions(-) diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index 02a7d8e..2b8c4d2 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -1,4 +1,5 @@ -using Valve.Vkv.ObjectModels; +using System; +using Valve.Vkv.ObjectModels; using ValveParsers = Valve.Miscellaneous.TypeParsers; @@ -45,7 +46,7 @@ public static class VkvConvert name = DeserializeString(parts[0], options); if (parts.Length == 2) { - object value = DeserializeObject(DeserializeString(parts[1], options)); + string value = DeserializeString(parts[1], options); node = new VkvSingleNode(value); } else @@ -69,8 +70,6 @@ public static class VkvConvert return node; } - private static object DeserializeObject(string content) => - ValveParsers.ParseAll(content); private static string DeserializeString(string content, VkvOptions options) { if (options.useQuotes) @@ -120,76 +119,122 @@ public static class VkvConvert { if (node is null) return null; - if (node is VkvSingleNode single) - { - object? value = single.value; - if (value is null) return null; - else if (value is string str) - { - value = ValveParsers.ParseAll(str); - if (value is string still && outputType.IsEnum) - { - if (Enum.TryParse(outputType, still, true, out object? res) && res is not null) - value = res; - } - } - return Convert.ChangeType(value, outputType); - } - else if (node is VkvTreeNode tree) - { - object? instance = Activator.CreateInstance(outputType); - if (instance is null) return null; - - IEnumerable validFields = from field in outputType.GetFields() - let isPublic = field.IsPublic - let isStatic = field.IsStatic - let isIgnored = field.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - let isConst = field.IsLiteral - where isPublic && !isStatic && !isIgnored && !isConst - select field; - - IEnumerable validProperties; - if (options.serializeProperties) - { - validProperties = from prop in outputType.GetProperties() - let canSet = prop.SetMethod is not null - let isPublic = canSet && prop.SetMethod!.IsPublic - let isStatic = canSet && prop.SetMethod!.IsStatic - let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - where canSet && isPublic && !isStatic && !isIgnored - select prop; - } - else validProperties = Array.Empty(); - - foreach (FieldInfo field in validFields) - { - string name = field.Name; - - VkvNode? subNode = tree[name]; - if (subNode is null) continue; - - object? result = FromNodeTree(field.FieldType, subNode, options); - if (result is null) continue; - field.SetValue(instance, result); - } - foreach (PropertyInfo prop in validProperties) - { - string name = prop.Name; - - VkvNode? subNode = tree[name]; - if (subNode is null) continue; - - object? result = FromNodeTree(prop.PropertyType, subNode, options); - if (result is null) continue; - prop.SetValue(instance, result); - } - - return instance; - } + if (node is VkvSingleNode single) return FromSingleNode(outputType, single); + else if (node is VkvTreeNode tree) return FromTreeNode(outputType, tree, options); else throw new VkvSerializationException("Unknown VKV node type."); } + + private static object? FromSingleNode(Type outputType, VkvSingleNode node) + { + object? value = node.value; + if (value is null) return null; + else if (value is string str) + { + value = ValveParsers.ParseAll(str); + if (value is string still && outputType.IsEnum) + { + if (Enum.TryParse(outputType, still, true, out object? res) && res is not null) + value = res; + } + } + return Convert.ChangeType(value, outputType); + } + + private static object? FromTreeNode(Type outputType, VkvTreeNode node, VkvOptions options) + { + if (outputType.IsArray) + return FromTreeNodeArray(outputType, node, options); + + else if (outputType.GetInterface("IList") is not null) + return FromTreeNodeList(outputType, node, options); + + object? instance = Activator.CreateInstance(outputType); + if (instance is null) return null; + + IEnumerable validFields = from field in outputType.GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + let isIgnored = field.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + let isConst = field.IsLiteral + where isPublic && !isStatic && !isIgnored && !isConst + select field; + + IEnumerable validProperties; + if (options.serializeProperties) + { + validProperties = from prop in outputType.GetProperties() + let canSet = prop.SetMethod is not null + let isPublic = canSet && prop.SetMethod!.IsPublic + let isStatic = canSet && prop.SetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + where canSet && isPublic && !isStatic && !isIgnored + select prop; + } + else validProperties = Array.Empty(); + + foreach (FieldInfo field in validFields) + { + string name = field.Name; + + VkvNode? subNode = node[name]; + if (subNode is null) continue; + + object? result = FromNodeTree(field.FieldType, subNode, options); + if (result is null) continue; + field.SetValue(instance, result); + } + foreach (PropertyInfo prop in validProperties) + { + string name = prop.Name; + + VkvNode? subNode = node[name]; + if (subNode is null) continue; + + object? result = FromNodeTree(prop.PropertyType, subNode, options); + if (result is null) continue; + prop.SetValue(instance, result); + } + + return instance; + } + + private static object? FromTreeNodeArray(Type outputType, VkvTreeNode node, VkvOptions options) + { + Type elementType = outputType.GetElementType()!; + Array array = Array.CreateInstance(elementType, node.SubNodeCount); + + int index = 0; + foreach (KeyValuePair subNode in node) + { + string indexStr = index.ToString(); + if (subNode.Key != indexStr) throw new VkvSerializationException($"Cannot convert node tree to array."); + array.SetValue(FromNodeTree(elementType, subNode.Value, options), index); + index++; + } + return array; + } + + private static object? FromTreeNodeList(Type outputType, VkvTreeNode node, VkvOptions options) + { + IList? instance = (IList?)Activator.CreateInstance(outputType); + if (instance is null) return null; + + // There is no guarentee that the first type argument corresponds to the element type, + // but as far as I know there isn't a better way. + Type elementType = outputType.IsGenericType ? outputType.GetGenericArguments().First() : typeof(object); + + int index = 0; + foreach (KeyValuePair subNode in node) + { + string indexStr = index.ToString(); + if (subNode.Key != indexStr) throw new VkvSerializationException($"Cannot convert node tree to array."); + instance.Add(FromNodeTree(elementType, subNode.Value, options)); + index++; + } + return instance; + } #endregion #region SerializeNode -- 2.49.0.windows.1 From 7c96f30d1b47ceaa8e8c49f2c3b261e3e7b255a5 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 13:34:22 -0400 Subject: [PATCH 69/89] Finished VKV deserialization development :) --- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 43 ++++++++++++++++++++++----- SrcMod/Valve.NET/Vkv/VkvSerializer.cs | 10 +++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index 2b8c4d2..dad6678 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -1,7 +1,4 @@ -using System; -using Valve.Vkv.ObjectModels; - -using ValveParsers = Valve.Miscellaneous.TypeParsers; +using Valve.Vkv.ObjectModels; namespace Valve.Vkv; @@ -115,6 +112,7 @@ public static class VkvConvert #endregion #region FromNodeTree + public static T? FromNodeTree(VkvNode? node, VkvOptions options) => (T?)FromNodeTree(typeof(T), node, options); public static object? FromNodeTree(Type outputType, VkvNode? node, VkvOptions options) { if (node is null) return null; @@ -130,7 +128,7 @@ public static class VkvConvert if (value is null) return null; else if (value is string str) { - value = ValveParsers.ParseAll(str); + value = TypeParsers.ParseAll(str); if (value is string still && outputType.IsEnum) { if (Enum.TryParse(outputType, still, true, out object? res) && res is not null) @@ -148,6 +146,9 @@ public static class VkvConvert else if (outputType.GetInterface("IList") is not null) return FromTreeNodeList(outputType, node, options); + else if (outputType.GetInterface("IDictionary") is not null) + return FromTreeNodeDictionary(outputType, node, options); + object? instance = Activator.CreateInstance(outputType); if (instance is null) return null; @@ -223,7 +224,7 @@ public static class VkvConvert // There is no guarentee that the first type argument corresponds to the element type, // but as far as I know there isn't a better way. - Type elementType = outputType.IsGenericType ? outputType.GetGenericArguments().First() : typeof(object); + Type elementType = outputType.IsGenericType ? outputType.GenericTypeArguments[0] : typeof(object); int index = 0; foreach (KeyValuePair subNode in node) @@ -235,6 +236,34 @@ public static class VkvConvert } return instance; } + + private static object? FromTreeNodeDictionary(Type outputType, VkvTreeNode node, VkvOptions options) + { + IDictionary? instance = (IDictionary?)Activator.CreateInstance(outputType); + if (instance is null) return null; + + // There is no guarentee that the first and second type arguments represent the + // key and value types, but as far as I know there isn't a better way. + bool canUseGenerics = outputType.GenericTypeArguments.Length >= 2; + Type keyType = canUseGenerics ? outputType.GenericTypeArguments[0] : typeof(object), + valueType = canUseGenerics ? outputType.GenericTypeArguments[1] : typeof(object); + + foreach (KeyValuePair subNode in node) + { + object key = TypeParsers.ParseAll(subNode.Key); + if (key is string still && keyType.IsEnum) + { + if (Enum.TryParse(keyType, still, true, out object? res) && res is not null) + key = res; + } + key = Convert.ChangeType(key, keyType); + + object? value = FromNodeTree(valueType, subNode.Value, options); + + instance.Add(key, value); + } + return instance; + } #endregion #region SerializeNode @@ -306,7 +335,7 @@ public static class VkvConvert if (obj is null) return null; Type type = obj.GetType(); - if (type.IsPrimitive || ValveParsers.CanParse(obj)) return new VkvSingleNode(obj); + if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj); else if (type.IsPointer) throw new("Cannot serialize a pointer."); VkvTreeNode tree = new(); diff --git a/SrcMod/Valve.NET/Vkv/VkvSerializer.cs b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs index 0724a0a..135845b 100644 --- a/SrcMod/Valve.NET/Vkv/VkvSerializer.cs +++ b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs @@ -22,6 +22,16 @@ public class VkvSerializer if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); return result; } + public T? Deserialize(Stream stream) + { + VkvNode? result = Deserialize(stream); + return VkvConvert.FromNodeTree(result, p_options); + } + public object? Deserialize(Type outputType, Stream stream) + { + VkvNode? result = Deserialize(stream); + return VkvConvert.FromNodeTree(outputType, result, p_options); + } public void Serialize(Stream stream, object? value, string parentNodeName) { -- 2.49.0.windows.1 From 13c9adf78198d9f1f53b5142fc509859fc4063c1 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 13:55:46 -0400 Subject: [PATCH 70/89] Added different tabbing options for VKV key and value seperation. --- SrcMod/Shell/{ => Miscellaneous}/GlobalUsings.cs | 0 SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs | 1 + SrcMod/Valve.NET/Vkv/SpacingMode.cs | 8 ++++++++ SrcMod/Valve.NET/Vkv/VkvConvert.cs | 16 ++++++++++++++-- SrcMod/Valve.NET/Vkv/VkvOptions.cs | 2 ++ 5 files changed, 25 insertions(+), 2 deletions(-) rename SrcMod/Shell/{ => Miscellaneous}/GlobalUsings.cs (100%) create mode 100644 SrcMod/Valve.NET/Vkv/SpacingMode.cs diff --git a/SrcMod/Shell/GlobalUsings.cs b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs similarity index 100% rename from SrcMod/Shell/GlobalUsings.cs rename to SrcMod/Shell/Miscellaneous/GlobalUsings.cs diff --git a/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs b/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs index fcfd555..1e3c341 100644 --- a/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs +++ b/SrcMod/Valve.NET/Miscellaneous/GlobalUsings.cs @@ -14,3 +14,4 @@ global using System.Threading; global using Valve; global using Valve.Miscellaneous; global using Valve.Vkv; +global using Valve.Vkv.ObjectModels; diff --git a/SrcMod/Valve.NET/Vkv/SpacingMode.cs b/SrcMod/Valve.NET/Vkv/SpacingMode.cs new file mode 100644 index 0000000..6f5064b --- /dev/null +++ b/SrcMod/Valve.NET/Vkv/SpacingMode.cs @@ -0,0 +1,8 @@ +namespace Valve.Vkv; + +public enum SpacingMode +{ + SingleSpace = 0, + IndentSizeSpacing, + DoubleTab, +} diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index dad6678..b5defb5 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -289,7 +289,20 @@ public static class VkvConvert writer.Write(new string(' ', indentLevel)); writer.Write(SerializeString(name, options)); - writer.Write(' '); + + switch (options.spacing) + { + case SpacingMode.SingleSpace: writer.Write(' '); + break; + + case SpacingMode.IndentSizeSpacing: writer.Write(new string(' ', options.indentSize)); + break; + + case SpacingMode.DoubleTab: writer.Write("\t\t"); + break; + + default: throw new VkvSerializationException($"Unknown spacing mode \"{options.spacing}\"."); + } serializedValue = SerializeString(serializedValue, options); writer.WriteLine(serializedValue); @@ -325,7 +338,6 @@ public static class VkvConvert if (options.useQuotes) content = $"\"{content}\""; return content; } - #endregion #region ToNodeTree diff --git a/SrcMod/Valve.NET/Vkv/VkvOptions.cs b/SrcMod/Valve.NET/Vkv/VkvOptions.cs index 72ad902..4bf92f3 100644 --- a/SrcMod/Valve.NET/Vkv/VkvOptions.cs +++ b/SrcMod/Valve.NET/Vkv/VkvOptions.cs @@ -8,6 +8,7 @@ public record class VkvOptions public int indentSize; public bool resetStreamPosition; public bool serializeProperties; + public SpacingMode spacing; public bool useEscapeCodes; public bool useQuotes; @@ -17,6 +18,7 @@ public record class VkvOptions indentSize = 4; resetStreamPosition = false; serializeProperties = true; + spacing = SpacingMode.DoubleTab; useEscapeCodes = false; useQuotes = false; } -- 2.49.0.windows.1 From d83c16827f008e307fc089c23da89473faca363b Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Wed, 10 May 2023 14:07:43 -0400 Subject: [PATCH 71/89] Shell now automatically detects steam directories (prone to bugs). --- SrcMod/Shell/Miscellaneous/GlobalUsings.cs | 1 + SrcMod/Shell/ObjectModels/Config.cs | 23 ++++++++++++++++++- .../Shell/ObjectModels/Steam/LibraryFolder.cs | 13 +++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs diff --git a/SrcMod/Shell/Miscellaneous/GlobalUsings.cs b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs index 92bd543..03f416c 100644 --- a/SrcMod/Shell/Miscellaneous/GlobalUsings.cs +++ b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs @@ -7,6 +7,7 @@ global using SrcMod.Shell.Extensions; global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; +global using SrcMod.Shell.ObjectModels.Steam; global using System; global using System.Collections; global using System.Collections.Generic; diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 197b7e6..db93907 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -65,7 +65,28 @@ public class Config internal Config() { - GameDirectories = Array.Empty(); + // TODO: This won't work if the steam installation is somewhere else. + const string gameDirDataPath = @"C:\Program Files (x86)\Steam\steamapps\libraryfolders.vdf"; + + VkvSerializer serializer = new(new() + { + useEscapeCodes = true, + useQuotes = true + }); + FileStream gameDirData = new(gameDirDataPath, FileMode.Open); + + LibraryFolder[]? folders = serializer.Deserialize(gameDirData); + if (folders is null) + { + Write("[WARNING] Error parsing steam game directories."); + GameDirectories = Array.Empty(); + } + else + { + GameDirectories = new string[folders.Length]; + for (int i = 0; i < folders.Length; i++) GameDirectories[i] = folders[i].path; + } + RunUnsafeCommands = AskMode.Ask; } diff --git a/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs b/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs new file mode 100644 index 0000000..a93cbb0 --- /dev/null +++ b/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs @@ -0,0 +1,13 @@ +namespace SrcMod.Shell.ObjectModels.Steam; + +public class LibraryFolder +{ + public string path; + public Dictionary apps; + + public LibraryFolder() + { + path = string.Empty; + apps = new(); + } +} -- 2.49.0.windows.1 From bcf02f4ecd4f9caad4b1afe2cf364a81db78e160 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Wed, 10 May 2023 16:28:21 -0400 Subject: [PATCH 72/89] Fixed issue #89. One line fix. --- SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs b/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs index a93cbb0..9ebe8e9 100644 --- a/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs +++ b/SrcMod/Shell/ObjectModels/Steam/LibraryFolder.cs @@ -3,7 +3,7 @@ public class LibraryFolder { public string path; - public Dictionary apps; + public Dictionary apps; public LibraryFolder() { -- 2.49.0.windows.1 From eee6306428b0761f1aaa3e026266fd9770ad1f4a Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Wed, 10 May 2023 17:14:05 -0400 Subject: [PATCH 73/89] SrcMod is a windows-only thing now. --- SrcMod/Shell/Shell.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SrcMod/Shell/Shell.csproj b/SrcMod/Shell/Shell.csproj index 253835f..ce8dca2 100644 --- a/SrcMod/Shell/Shell.csproj +++ b/SrcMod/Shell/Shell.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net7.0-windows disable enable srcmod -- 2.49.0.windows.1 From c0afa7dbb4e44dccd400c266fbaf0f2ccd36a386 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 11 May 2023 15:38:41 -0400 Subject: [PATCH 74/89] Automatically detects steam install location now. --- SrcMod/Shell/Miscellaneous/GlobalUsings.cs | 4 +- SrcMod/Shell/ObjectModels/Config.cs | 26 +++++++++-- SrcMod/Shell/Shell.cs | 52 +++++++++++----------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/SrcMod/Shell/Miscellaneous/GlobalUsings.cs b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs index 03f416c..bbee376 100644 --- a/SrcMod/Shell/Miscellaneous/GlobalUsings.cs +++ b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs @@ -1,10 +1,12 @@ -global using Nerd_STF.Mathematics; +global using Microsoft.Win32; +global using Nerd_STF.Mathematics; global using Newtonsoft.Json; global using SharpCompress.Archives.Rar; global using SharpCompress.Archives.SevenZip; global using SharpCompress.Readers; global using SrcMod.Shell.Extensions; global using SrcMod.Shell.Interop; +global using SrcMod.Shell.Modules; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; global using SrcMod.Shell.ObjectModels.Steam; diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index db93907..c213c25 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -22,8 +22,11 @@ public class Config private static Config p_applied; private static Changes? p_changes; + private static string p_steamLocation; + static Config() { + // Generate shared fields between the config class and its changes equivalent. p_applied = Defaults; FieldInfo[] configFields = (from field in typeof(Config).GetFields() @@ -65,8 +68,25 @@ public class Config internal Config() { - // TODO: This won't work if the steam installation is somewhere else. - const string gameDirDataPath = @"C:\Program Files (x86)\Steam\steamapps\libraryfolders.vdf"; + // Locate some steam stuff. + const string steamLocationKey = @"Software\Valve\Steam"; + RegistryKey? key = Registry.CurrentUser.OpenSubKey(steamLocationKey); + if (key is null) + { + Write("[FATAL] Cannot locate Steam installation. Do you have Steam installed?", + ConsoleColor.DarkRed); + Thread.Sleep(1000); + BaseModule.QuitShell(-1); + + // This should never run, and is just here to supress + // a couple compiler warnings. + p_steamLocation = string.Empty; + RunUnsafeCommands = AskMode.Ask; + return; + } + p_steamLocation = (string)key.GetValue("SteamPath")!; + + string gameDirDataPath = Path.Combine(p_steamLocation, @"steamapps\libraryfolders.vdf"); VkvSerializer serializer = new(new() { @@ -78,7 +98,7 @@ public class Config LibraryFolder[]? folders = serializer.Deserialize(gameDirData); if (folders is null) { - Write("[WARNING] Error parsing steam game directories."); + Write("[WARNING] Error parsing Steam game directories.", ConsoleColor.DarkYellow); GameDirectories = Array.Empty(); } else diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index d353fb2..acb78fe 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -16,10 +16,10 @@ public class Shell public List History; public string WorkingDirectory; - private bool lastCancel; - private bool printedCancel; + private bool p_lastCancel; + private bool p_printedCancel; - private BackgroundWorker? activeCommand; + private BackgroundWorker? p_activeCommand; public Shell() { @@ -88,8 +88,8 @@ public class Shell Write(" by ", ConsoleColor.White, false); Write($"{Author}", ConsoleColor.DarkYellow); - lastCancel = false; - activeCommand = null; + p_lastCancel = false; + p_activeCommand = null; Console.CancelKeyPress += HandleCancel; ActiveGame = null; @@ -149,7 +149,7 @@ public class Shell bool printed = false; - if (lastCancel && !printedCancel) + if (p_lastCancel && !p_printedCancel) { // Print the warning. A little bit of mess because execution must // continue without funny printing errors but it's alright I guess. @@ -160,7 +160,7 @@ public class Shell Write("Press ^C again to exit the shell.", ConsoleColor.Red); PlayWarningSound(); - printedCancel = true; + p_printedCancel = true; Console.CursorTop += 2; Console.CursorLeft = originalLeft; @@ -175,8 +175,8 @@ public class Shell if (!printed) { - lastCancel = false; - printedCancel = false; + p_lastCancel = false; + p_printedCancel = false; } return message; @@ -262,18 +262,18 @@ public class Shell } } - activeCommand = new(); - activeCommand.DoWork += runCommand; - activeCommand.RunWorkerAsync(); + p_activeCommand = new(); + p_activeCommand.DoWork += runCommand; + p_activeCommand.RunWorkerAsync(); - activeCommand.WorkerSupportsCancellation = command.CanBeCancelled; + p_activeCommand.WorkerSupportsCancellation = command.CanBeCancelled; - while (activeCommand is not null && activeCommand.IsBusy) Thread.Yield(); + while (p_activeCommand is not null && p_activeCommand.IsBusy) Thread.Yield(); - if (activeCommand is not null) + if (p_activeCommand is not null) { - activeCommand.Dispose(); - activeCommand = null; + p_activeCommand.Dispose(); + p_activeCommand = null; } if (ShellDirectory is null) Write("[WARNING] Could not save config to shell location. Any changes will be ignored."); @@ -310,14 +310,14 @@ public class Shell private void HandleCancel(object? sender, ConsoleCancelEventArgs args) { - if (activeCommand is not null && activeCommand.IsBusy) + if (p_activeCommand is not null && p_activeCommand.IsBusy) { - if (activeCommand.WorkerSupportsCancellation) + if (p_activeCommand.WorkerSupportsCancellation) { // Kill the active command. - activeCommand.CancelAsync(); - activeCommand.Dispose(); - activeCommand = null; + p_activeCommand.CancelAsync(); + p_activeCommand.Dispose(); + p_activeCommand = null; } else { @@ -326,18 +326,18 @@ public class Shell PlayErrorSound(); } - lastCancel = false; - printedCancel = false; + p_lastCancel = false; + p_printedCancel = false; args.Cancel = true; return; } // Due to some funny multithreading issues, we want to make the warning label // single-threaded on the shell. - if (!lastCancel) + if (!p_lastCancel) { // Enable the warning. The "ReadLine" method will do the rest. - lastCancel = true; + p_lastCancel = true; args.Cancel = true; // "Cancel" referring to the cancellation of the cancel operation. return; } -- 2.49.0.windows.1 From 45e23b9924c38250e38d9adc9d7b57459fdce84b Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 11 May 2023 17:11:17 -0400 Subject: [PATCH 75/89] Added some comments. --- SrcMod/Shell/ObjectModels/Config.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index c213c25..fc50b46 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -22,6 +22,7 @@ public class Config private static Config p_applied; private static Changes? p_changes; + // These variables should only exist in the Config class so they aren't marked as shared. private static string p_steamLocation; static Config() @@ -86,6 +87,8 @@ public class Config } p_steamLocation = (string)key.GetValue("SteamPath")!; + // Assign config variables. + string gameDirDataPath = Path.Combine(p_steamLocation, @"steamapps\libraryfolders.vdf"); VkvSerializer serializer = new(new() -- 2.49.0.windows.1 From 92b22d6749b3ffc6523c61d713c947372d536773 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 11 May 2023 17:13:02 -0400 Subject: [PATCH 76/89] One more tiny thing. --- SrcMod/Shell/ObjectModels/Config.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index fc50b46..3494028 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -23,7 +23,7 @@ public class Config private static Changes? p_changes; // These variables should only exist in the Config class so they aren't marked as shared. - private static string p_steamLocation; + private string p_steamLocation; static Config() { @@ -82,6 +82,7 @@ public class Config // This should never run, and is just here to supress // a couple compiler warnings. p_steamLocation = string.Empty; + GameDirectories = Array.Empty(); RunUnsafeCommands = AskMode.Ask; return; } -- 2.49.0.windows.1 From 7854a576a707402846d56c50767d6f045058d403 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 11 May 2023 17:33:11 -0400 Subject: [PATCH 77/89] Reformatted command prompt header and added relative paths. --- SrcMod/Shell/Mod.cs | 5 ++++- SrcMod/Shell/Shell.cs | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/SrcMod/Shell/Mod.cs b/SrcMod/Shell/Mod.cs index b4472d5..d6da543 100644 --- a/SrcMod/Shell/Mod.cs +++ b/SrcMod/Shell/Mod.cs @@ -3,10 +3,12 @@ public class Mod { public string Name { get; set; } + public string RootDirectory { get; set; } private Mod() { Name = string.Empty; + RootDirectory = string.Empty; } public static Mod? ReadDirectory(string dir) @@ -15,7 +17,8 @@ public class Mod Mod mod = new() { - Name = dir.Split("\\").Last() + Name = dir.Split("\\").Last(), + RootDirectory = dir }; return mod; diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index acb78fe..ef5f7b0 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -139,9 +139,18 @@ public class Shell public string ReadLine() { - Write($"\n{WorkingDirectory}", ConsoleColor.DarkGreen, false); - if (ActiveGame is not null) Write($" {ActiveGame}", ConsoleColor.DarkYellow, false); - if (ActiveMod is not null) Write($" {ActiveMod}", ConsoleColor.Magenta, false); + Write("\n", newLine: false); + if (ActiveMod is not null) Write($"{ActiveMod} ", ConsoleColor.Magenta, false); + + if (ActiveMod is not null) + { + string directory = Path.GetRelativePath(ActiveMod.RootDirectory, WorkingDirectory); + if (directory == ".") directory = string.Empty; + Write($"~\\{directory}", ConsoleColor.DarkGreen, false); + } + else Write($"{WorkingDirectory}", ConsoleColor.DarkGreen, false); + + if (ActiveGame is not null) Write($" ({ActiveGame})", ConsoleColor.DarkYellow, false); Write(null); Write($" {Name}", ConsoleColor.DarkCyan, false); -- 2.49.0.windows.1 From 62d3ba6492cbd0c8c6d1f60b6f8c1da00efdeba5 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 11 May 2023 17:43:17 -0400 Subject: [PATCH 78/89] Active mod is now detected in parent directories. --- SrcMod/Shell/Mod.cs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/SrcMod/Shell/Mod.cs b/SrcMod/Shell/Mod.cs index d6da543..148b38b 100644 --- a/SrcMod/Shell/Mod.cs +++ b/SrcMod/Shell/Mod.cs @@ -13,15 +13,28 @@ public class Mod public static Mod? ReadDirectory(string dir) { - if (!File.Exists(dir + "\\GameInfo.txt")) return null; + dir = dir.Trim().Replace('/', '\\'); + string check = dir; - Mod mod = new() + while (!string.IsNullOrEmpty(check)) { - Name = dir.Split("\\").Last(), - RootDirectory = dir - }; + if (File.Exists(Path.Combine(check, "GameInfo.txt"))) + { + // Root mod directory found, go from here. + // TODO: Parse VKV out of GameInfo.txt - return mod; + Mod mod = new() + { + Name = Path.GetFileNameWithoutExtension(check), // TODO: replace with GameInfo: Title + RootDirectory = check + }; + return mod; + } + + check = Path.GetDirectoryName(check) ?? string.Empty; // Go to parent folder. + } + + return null; } public override string ToString() => Name; -- 2.49.0.windows.1 From be6e4a496b8091e3cbdf7d15329be638d002fb59 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Thu, 11 May 2023 21:45:03 -0400 Subject: [PATCH 79/89] Some progress on gameinfo parsing (DOESNT WORK YET) --- SrcMod/Shell/Miscellaneous/GlobalUsings.cs | 1 + SrcMod/Shell/Mod.cs | 10 ++- SrcMod/Shell/ObjectModels/Config.cs | 14 ++-- SrcMod/Shell/ObjectModels/Source/GameInfo.cs | 68 ++++++++++++++++++++ SrcMod/Shell/Tools.cs | 16 ++++- 5 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 SrcMod/Shell/ObjectModels/Source/GameInfo.cs diff --git a/SrcMod/Shell/Miscellaneous/GlobalUsings.cs b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs index bbee376..b5c13b0 100644 --- a/SrcMod/Shell/Miscellaneous/GlobalUsings.cs +++ b/SrcMod/Shell/Miscellaneous/GlobalUsings.cs @@ -9,6 +9,7 @@ global using SrcMod.Shell.Interop; global using SrcMod.Shell.Modules; global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.ObjectModels; +global using SrcMod.Shell.ObjectModels.Source; global using SrcMod.Shell.ObjectModels.Steam; global using System; global using System.Collections; diff --git a/SrcMod/Shell/Mod.cs b/SrcMod/Shell/Mod.cs index 148b38b..c3bfdd3 100644 --- a/SrcMod/Shell/Mod.cs +++ b/SrcMod/Shell/Mod.cs @@ -18,14 +18,18 @@ public class Mod while (!string.IsNullOrEmpty(check)) { - if (File.Exists(Path.Combine(check, "GameInfo.txt"))) + string gameInfoPath = Path.Combine(check, "GameInfo.txt"); + if (File.Exists(gameInfoPath)) { // Root mod directory found, go from here. - // TODO: Parse VKV out of GameInfo.txt + + FileStream fs = new(gameInfoPath, FileMode.Open); + GameInfo? modInfo = SerializeVkv.Deserialize(fs); // TODO: constructor should be public i think + if (modInfo is null) continue; Mod mod = new() { - Name = Path.GetFileNameWithoutExtension(check), // TODO: replace with GameInfo: Title + Name = modInfo.Title, RootDirectory = check }; return mod; diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 3494028..9ef3cdf 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -23,7 +23,7 @@ public class Config private static Changes? p_changes; // These variables should only exist in the Config class so they aren't marked as shared. - private string p_steamLocation; + private readonly string p_steamLocation; static Config() { @@ -92,14 +92,8 @@ public class Config string gameDirDataPath = Path.Combine(p_steamLocation, @"steamapps\libraryfolders.vdf"); - VkvSerializer serializer = new(new() - { - useEscapeCodes = true, - useQuotes = true - }); FileStream gameDirData = new(gameDirDataPath, FileMode.Open); - - LibraryFolder[]? folders = serializer.Deserialize(gameDirData); + LibraryFolder[]? folders = SerializeVkv.Deserialize(gameDirData); if (folders is null) { Write("[WARNING] Error parsing Steam game directories.", ConsoleColor.DarkYellow); @@ -177,7 +171,7 @@ public class Config } StreamReader reader = new(fullPath); JsonTextReader jsonReader = new(reader); - p_changes = Serializer.Deserialize(jsonReader); + p_changes = Tools.SerializerJson.Deserialize(jsonReader); jsonReader.Close(); reader.Close(); @@ -198,7 +192,7 @@ public class Config { Indentation = 4 }; - Serializer.Serialize(jsonWriter, p_changes); + Tools.SerializerJson.Serialize(jsonWriter, p_changes); jsonWriter.Close(); writer.Close(); } diff --git a/SrcMod/Shell/ObjectModels/Source/GameInfo.cs b/SrcMod/Shell/ObjectModels/Source/GameInfo.cs new file mode 100644 index 0000000..039e92f --- /dev/null +++ b/SrcMod/Shell/ObjectModels/Source/GameInfo.cs @@ -0,0 +1,68 @@ +namespace SrcMod.Shell.ObjectModels.Source; + +// Referencing https://developer.valvesoftware.com/wiki/Gameinfo.txt. +public class GameInfo +{ + // Name + public string Game; + public string Title; + public bool GameLogo; + + // Options + public string Type; // TODO: Make this an enum. + public bool NoDifficulty; + public bool HasPortals; + public bool NoCrosshair; + public bool AdvCrosshair; + public bool NoModels; + public bool NoHIModel; + + public Dictionary Hidden_Maps; + public Dictionary CommandLine; + + // Steam games list + public string Developer; + public string Developer_URL; + public string Manual; + public string Icon; + + // Engine and tools + public bool Nodegraph; + public string GameData; + public string InstancePath; + public bool SupportsDX8; + public bool SupportsVR; + public bool SupportsXBox360; + public FileSystemData FileSystem; + + internal GameInfo() + { + Game = string.Empty; + Title = string.Empty; + Type = string.Empty; + Hidden_Maps = new(); + CommandLine = new(); + Developer = string.Empty; + Developer_URL = string.Empty; + Manual = string.Empty; + Icon = string.Empty; + GameData = string.Empty; + FileSystem = new(); + InstancePath = string.Empty; + } + + public class FileSystemData + { + public int SteamAppID; + public int AdditionalContentId; + public int ToolsAppId; + + // Can't make the keys here enums because they can be strung together, + public Dictionary SearchPaths; + + internal FileSystemData() + { + SearchPaths = new(); + } + } +} diff --git a/SrcMod/Shell/Tools.cs b/SrcMod/Shell/Tools.cs index bd1c219..f1e0809 100644 --- a/SrcMod/Shell/Tools.cs +++ b/SrcMod/Shell/Tools.cs @@ -2,15 +2,27 @@ public static class Tools { - public static JsonSerializer Serializer { get; private set; } + public static JsonSerializer SerializerJson { get; private set; } + public static VkvSerializer SerializeVkv { get; private set; } static Tools() { - Serializer = JsonSerializer.Create(new() + SerializerJson = JsonSerializer.Create(new() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore }); + + SerializeVkv = new VkvSerializer(new() + { + closeWhenFinished = true, + indentSize = 4, + resetStreamPosition = false, + serializeProperties = true, + spacing = SpacingMode.DoubleTab, + useEscapeCodes = true, + useQuotes = true + }); } public static void DisplayWithPages(IEnumerable lines, ConsoleColor? color = null) -- 2.49.0.windows.1 From 2abadc40716ca4bf1761506facfe526e86fdc025 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Fri, 12 May 2023 07:41:48 -0400 Subject: [PATCH 80/89] GameInfo doesn't crash anymore, but still needs to be improved. --- SrcMod/Shell/Mod.cs | 2 +- SrcMod/Shell/ObjectModels/Source/GameInfo.cs | 4 ++-- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/SrcMod/Shell/Mod.cs b/SrcMod/Shell/Mod.cs index c3bfdd3..843d51f 100644 --- a/SrcMod/Shell/Mod.cs +++ b/SrcMod/Shell/Mod.cs @@ -24,7 +24,7 @@ public class Mod // Root mod directory found, go from here. FileStream fs = new(gameInfoPath, FileMode.Open); - GameInfo? modInfo = SerializeVkv.Deserialize(fs); // TODO: constructor should be public i think + GameInfo? modInfo = SerializeVkv.Deserialize(fs); if (modInfo is null) continue; Mod mod = new() diff --git a/SrcMod/Shell/ObjectModels/Source/GameInfo.cs b/SrcMod/Shell/ObjectModels/Source/GameInfo.cs index 039e92f..0833a5f 100644 --- a/SrcMod/Shell/ObjectModels/Source/GameInfo.cs +++ b/SrcMod/Shell/ObjectModels/Source/GameInfo.cs @@ -35,7 +35,7 @@ public class GameInfo public bool SupportsXBox360; public FileSystemData FileSystem; - internal GameInfo() + public GameInfo() { Game = string.Empty; Title = string.Empty; @@ -60,7 +60,7 @@ public class GameInfo // Can't make the keys here enums because they can be strung together, public Dictionary SearchPaths; - internal FileSystemData() + public FileSystemData() { SearchPaths = new(); } diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index b5defb5..45f8ff3 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -57,7 +57,6 @@ public static class VkvConvert { if (current == "}") break; VkvNode? output = DeserializeNode(reader, options, out string subName, current); - if (output is null) throw new VkvSerializationException("Error deserializing sub-node."); tree[subName] = output; } if (current is null) throw new VkvSerializationException("Reached end-of-file while deserializing group."); -- 2.49.0.windows.1 From 5b2b0abfa339331916b7d77a2bc4d4519f682cfe Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Fri, 12 May 2023 10:47:13 -0400 Subject: [PATCH 81/89] Added some error handling in the shell. --- SrcMod/Shell/ObjectModels/Config.cs | 38 ++++++++++++++++++++----- SrcMod/Shell/Shell.cs | 41 +++++++++++++++++++++++---- SrcMod/Valve.NET/Vkv/VkvSerializer.cs | 21 ++++++++++---- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index 9ef3cdf..af83ac4 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -4,6 +4,9 @@ public class Config { public const string FilePath = "config.json"; + public static bool HasDisplayableError => false; + public static bool HasDisplayableWarning => p_printedLastSteamWarning; + public static Config Defaults => new(); private static readonly FieldInfo[] p_configSharedFields; @@ -22,6 +25,8 @@ public class Config private static Config p_applied; private static Changes? p_changes; + private static bool p_printedLastSteamWarning; + // These variables should only exist in the Config class so they aren't marked as shared. private readonly string p_steamLocation; @@ -93,16 +98,35 @@ public class Config string gameDirDataPath = Path.Combine(p_steamLocation, @"steamapps\libraryfolders.vdf"); FileStream gameDirData = new(gameDirDataPath, FileMode.Open); - LibraryFolder[]? folders = SerializeVkv.Deserialize(gameDirData); - if (folders is null) + try { - Write("[WARNING] Error parsing Steam game directories.", ConsoleColor.DarkYellow); - GameDirectories = Array.Empty(); + LibraryFolder[]? folders = SerializeVkv.Deserialize(gameDirData); + if (folders is null) + { + if (!p_printedLastSteamWarning) + Write("[WARNING] Error parsing Steam game directories.", ConsoleColor.DarkYellow); + GameDirectories = Array.Empty(); + p_printedLastSteamWarning = true; + } + else + { + GameDirectories = new string[folders.Length]; + for (int i = 0; i < folders.Length; i++) GameDirectories[i] = folders[i].path; + p_printedLastSteamWarning = false; + } } - else + catch (Exception ex) { - GameDirectories = new string[folders.Length]; - for (int i = 0; i < folders.Length; i++) GameDirectories[i] = folders[i].path; + if (!p_printedLastSteamWarning) + { +#if RELEASE + Write("[WARNING] Error parsing Steam game directories.", ConsoleColor.DarkYellow); +#else + Write(ex, ConsoleColor.DarkYellow); +#endif + } + GameDirectories = Array.Empty(); + p_printedLastSteamWarning = true; } RunUnsafeCommands = AskMode.Ask; diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index ef5f7b0..e21cc26 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -6,6 +6,12 @@ public class Shell public const string Name = "SrcMod"; public const string Version = "Beta 0.5.0"; + public bool HasAnyDisplayableError => HasDisplayableError || Config.HasDisplayableError; + public bool HasAnyDisplayableWarning => HasDisplayableWarning || Config.HasDisplayableWarning; + + public bool HasDisplayableError => p_printedLastReloadError; + public bool HasDisplayableWarning => false; + public readonly string? ShellDirectory; public List LoadedCommands; @@ -19,6 +25,8 @@ public class Shell private bool p_lastCancel; private bool p_printedCancel; + private bool p_printedLastReloadError; + private BackgroundWorker? p_activeCommand; public Shell() @@ -140,6 +148,9 @@ public class Shell public string ReadLine() { Write("\n", newLine: false); + if (HasAnyDisplayableError) Write($"(Error) ", ConsoleColor.DarkRed, false); + else if (HasAnyDisplayableWarning) Write($"(Warning) ", ConsoleColor.DarkYellow, false); + if (ActiveMod is not null) Write($"{ActiveMod} ", ConsoleColor.Magenta, false); if (ActiveMod is not null) @@ -309,12 +320,32 @@ public class Shell public void ReloadDirectoryInfo() { - ActiveMod = Mod.ReadDirectory(WorkingDirectory); + try + { + ActiveMod = Mod.ReadDirectory(WorkingDirectory); - // Update title. - string title = "SrcMod"; - if (ActiveMod is not null) title += $" - {ActiveMod.Name}"; - Console.Title = title; + // Update title. + string title = "SrcMod"; + if (ActiveMod is not null) title += $" - {ActiveMod.Name}"; + Console.Title = title; + + p_printedLastReloadError = false; + } + catch (Exception ex) + { + if (!p_printedLastReloadError) + { +#if RELEASE + Write("[ERROR] Error reloading directory information. Some data may not update.", + ConsoleColor.Red); +#else + Write(ex, ConsoleColor.Red); +#endif + } + + p_printedLastReloadError = true; + Console.Title = "SrcMod (Error)"; + } } private void HandleCancel(object? sender, ConsoleCancelEventArgs args) diff --git a/SrcMod/Valve.NET/Vkv/VkvSerializer.cs b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs index 135845b..fe3e8d0 100644 --- a/SrcMod/Valve.NET/Vkv/VkvSerializer.cs +++ b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs @@ -1,4 +1,6 @@ -namespace Valve.Vkv; +using System.Reflection.PortableExecutable; + +namespace Valve.Vkv; public class VkvSerializer { @@ -16,11 +18,18 @@ public class VkvSerializer { long pos = stream.Position; StreamReader reader = new(stream, leaveOpen: !p_options.closeWhenFinished); - VkvNode? result = VkvConvert.DeserializeNode(reader, p_options); - reader.Close(); - - if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); - return result; + try + { + VkvNode? result = VkvConvert.DeserializeNode(reader, p_options); + reader.Close(); + if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); + return result; + } + finally + { + reader.Close(); + if (!p_options.closeWhenFinished && p_options.resetStreamPosition) stream.Seek(pos, SeekOrigin.Begin); + } } public T? Deserialize(Stream stream) { -- 2.49.0.windows.1 From f25b366a4d0fcbca8ce13a2b52075b409a10336c Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Mon, 15 May 2023 10:50:58 -0400 Subject: [PATCH 82/89] Made a bunch of progress parsing mod info, almost done. --- SrcMod/Shell/Game.cs | 46 ++++++- SrcMod/Shell/Mod.cs | 119 ++++++++++++++++++- SrcMod/Shell/ObjectModels/Source/GameInfo.cs | 55 ++++----- 3 files changed, 177 insertions(+), 43 deletions(-) diff --git a/SrcMod/Shell/Game.cs b/SrcMod/Shell/Game.cs index 1a21734..2e0e23c 100644 --- a/SrcMod/Shell/Game.cs +++ b/SrcMod/Shell/Game.cs @@ -1,6 +1,6 @@ namespace SrcMod.Shell; -public class Game +public class Game : IEquatable { public static readonly Game Portal2 = new() { @@ -8,12 +8,48 @@ public class Game NameId = "portal2", SteamId = 620 }; + public static readonly Game Unknown = new() + { + Name = "Unknown Game", + NameId = "unknown", + SteamId = -1, + IsUnknown = true + }; - public required string Name { get; init; } - public required string NameId { get; init; } - public required int SteamId { get; init; } + public string Name { get; private set; } + public string NameId { get; private set; } + public int SteamId { get; private set; } - private Game() { } + public bool IsUnknown { get; private set; } + + private Game() + { + IsUnknown = false; + Name = string.Empty; + NameId = string.Empty; + } + + public static Game FromSteamId(int id) + { + if (id == Portal2.SteamId) return Portal2; + else + { + Game game = (Game)Unknown.MemberwiseClone(); + game.SteamId = id; + return game; + } + } + + public override bool Equals(object? obj) + { + if (obj is Game game) return Equals(game); + return false; + } + public bool Equals(Game? other) => other is not null && SteamId == other.SteamId; + public override int GetHashCode() => base.GetHashCode(); public override string ToString() => Name; + + public static bool operator ==(Game a, Game b) => a.Equals(b); + public static bool operator !=(Game a, Game b) => !a.Equals(b); } diff --git a/SrcMod/Shell/Mod.cs b/SrcMod/Shell/Mod.cs index 843d51f..5386868 100644 --- a/SrcMod/Shell/Mod.cs +++ b/SrcMod/Shell/Mod.cs @@ -2,15 +2,98 @@ public class Mod { + public Game BaseGame { get; set; } + + public string? Developer { get; set; } + public string? DeveloperUrl { get; set; } + public Dictionary SearchPaths { get; set; } // TODO: Replace the keys with a flags enum. + public string? ManualUrl { get; set; } + + public string? FgdDataPath { get; set; } + public string? IconPath { get; set; } + public string? InstancePath { get; set; } + + public PlayerType PlayerMode { get; set; } + + public CrosshairFlags CrosshairMenuFlags { get; set; } + public bool ShowDifficultyMenu { get; set; } + public bool ShowModelMenu { get; set; } + public bool ShowPortalMenu { get; set; } + public SupportFlags SupportingFlags { get; set; } + + public bool HiResModels { get; set; } + + public string[] HiddenMaps { get; set; } + public string Name { get; set; } + public string? Motto { get; set; } + public TitleDisplay TitleDisplayMode { get; set; } + + public bool BuildMapNodegraphs { get; set; } + + public Dictionary? MapbaseLaunchOptions { get; set; } public string RootDirectory { get; set; } private Mod() { + BaseGame = Game.Unknown; + SearchPaths = new(); + HiddenMaps = Array.Empty(); Name = string.Empty; RootDirectory = string.Empty; } + public static Mod FromInfo(string root, GameInfo info) + { + Mod curMod = new() + { + BaseGame = Game.FromSteamId(info.FileSystem.SteamAppID), + BuildMapNodegraphs = info.Nodegraph is not null && info.Nodegraph.Value, + CrosshairMenuFlags = CrosshairFlags.None, + Developer = info.Developer, + DeveloperUrl = info.Developer_URL, + FgdDataPath = info.GameData, + HiddenMaps = info.Hidden_Maps is null ? Array.Empty() : info.Hidden_Maps.Keys.ToArray(), + HiResModels = info.NoHIModel is null || !info.NoHIModel.Value, + IconPath = info.Icon is null ? null : info.Icon.Trim().Replace('/', '\\') + ".tga", + InstancePath = info.InstancePath, + MapbaseLaunchOptions = info.CommandLine, + ManualUrl = info.Manual, + Motto = info.Title2, + Name = string.IsNullOrEmpty(info.Title) ? "Default Mod" : info.Title, + PlayerMode = info.Type is null ? PlayerType.Both : info.Type.Trim().ToLower() switch + { + "singleplayer_only" => PlayerType.Singleplayer, + "multiplayer_only" => PlayerType.Multiplayer, + _ => throw new ArgumentException($"Unknown type \"{info.Type}\"") + }, + RootDirectory = root, + SearchPaths = info.FileSystem.SearchPaths, + ShowDifficultyMenu = info.NoDifficulty is null || !info.NoDifficulty.Value, + ShowModelMenu = info.NoModels is null || !info.NoModels.Value, + ShowPortalMenu = info.HasPortals is not null && info.HasPortals.Value, + SupportingFlags = SupportFlags.None, + TitleDisplayMode = info.GameLogo is null ? TitleDisplay.Title : + (info.GameLogo.Value ? TitleDisplay.Logo : TitleDisplay.Title) + }; + if (curMod.PlayerMode == PlayerType.Multiplayer && info.NoDifficulty is null) + curMod.ShowDifficultyMenu = false; + + if (info.NoCrosshair is null || !info.NoCrosshair.Value) + curMod.CrosshairMenuFlags |= CrosshairFlags.ShowMultiplayer; + if (info.AdvCrosshair is not null && info.AdvCrosshair.Value) + curMod.CrosshairMenuFlags |= CrosshairFlags.AdvancedMenu; + + if (info.SupportsDX8 is not null && info.SupportsDX8.Value) + curMod.SupportingFlags |= SupportFlags.DirectX8; + if (info.SupportsVR is not null && info.SupportsVR.Value) + curMod.SupportingFlags |= SupportFlags.VirtualReality; + if (info.SupportsXBox360 is not null && info.SupportsXBox360.Value) + curMod.SupportingFlags |= SupportFlags.XBox360; + + return curMod; + } + public static Mod? ReadDirectory(string dir) { dir = dir.Trim().Replace('/', '\\'); @@ -27,12 +110,7 @@ public class Mod GameInfo? modInfo = SerializeVkv.Deserialize(fs); if (modInfo is null) continue; - Mod mod = new() - { - Name = modInfo.Title, - RootDirectory = check - }; - return mod; + return FromInfo(check, modInfo); } check = Path.GetDirectoryName(check) ?? string.Empty; // Go to parent folder. @@ -42,4 +120,33 @@ public class Mod } public override string ToString() => Name; + + [Flags] + public enum CrosshairFlags + { + None = 0, + ShowMultiplayer = 1, + AdvancedMenu = 2 + } + + [Flags] + public enum SupportFlags + { + None, + DirectX8 = 1, + VirtualReality = 2, + XBox360 = 4 + } + + public enum PlayerType + { + Singleplayer = 1, + Multiplayer = 2, + Both = Singleplayer | Multiplayer + } + public enum TitleDisplay + { + Title, + Logo + } } diff --git a/SrcMod/Shell/ObjectModels/Source/GameInfo.cs b/SrcMod/Shell/ObjectModels/Source/GameInfo.cs index 0833a5f..c65396e 100644 --- a/SrcMod/Shell/ObjectModels/Source/GameInfo.cs +++ b/SrcMod/Shell/ObjectModels/Source/GameInfo.cs @@ -6,58 +6,49 @@ public class GameInfo // Name public string Game; public string Title; - public bool GameLogo; + public string? Title2; + public bool? GameLogo; // Options - public string Type; // TODO: Make this an enum. - public bool NoDifficulty; - public bool HasPortals; - public bool NoCrosshair; - public bool AdvCrosshair; - public bool NoModels; - public bool NoHIModel; + public string? Type; + public bool? NoDifficulty; + public bool? HasPortals; + public bool? NoCrosshair; + public bool? AdvCrosshair; + public bool? NoModels; + public bool? NoHIModel; - public Dictionary Hidden_Maps; - public Dictionary CommandLine; + public Dictionary? Hidden_Maps; + public Dictionary? CommandLine; // Steam games list - public string Developer; - public string Developer_URL; - public string Manual; - public string Icon; + public string? Developer; + public string? Developer_URL; + public string? Manual; + public string? Icon; // Engine and tools - public bool Nodegraph; - public string GameData; - public string InstancePath; - public bool SupportsDX8; - public bool SupportsVR; - public bool SupportsXBox360; + public bool? Nodegraph; + public string? GameData; + public string? InstancePath; + public bool? SupportsDX8; + public bool? SupportsVR; + public bool? SupportsXBox360; public FileSystemData FileSystem; public GameInfo() { Game = string.Empty; Title = string.Empty; - Type = string.Empty; - Hidden_Maps = new(); - CommandLine = new(); - Developer = string.Empty; - Developer_URL = string.Empty; - Manual = string.Empty; - Icon = string.Empty; - GameData = string.Empty; FileSystem = new(); - InstancePath = string.Empty; } public class FileSystemData { public int SteamAppID; - public int AdditionalContentId; - public int ToolsAppId; + public int? AdditionalContentId; + public int? ToolsAppId; - // Can't make the keys here enums because they can be strung together, public Dictionary SearchPaths; public FileSystemData() -- 2.49.0.windows.1 From dfda870eacb364e4664fd4e5657f2ead080e5e19 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 16 May 2023 08:05:13 -0400 Subject: [PATCH 83/89] Added final tweaks to parsing mod info (for now). --- SrcMod/Shell/Mod.cs | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/SrcMod/Shell/Mod.cs b/SrcMod/Shell/Mod.cs index 5386868..fef57fb 100644 --- a/SrcMod/Shell/Mod.cs +++ b/SrcMod/Shell/Mod.cs @@ -6,7 +6,7 @@ public class Mod public string? Developer { get; set; } public string? DeveloperUrl { get; set; } - public Dictionary SearchPaths { get; set; } // TODO: Replace the keys with a flags enum. + public Dictionary SearchPaths { get; set; } public string? ManualUrl { get; set; } public string? FgdDataPath { get; set; } @@ -68,7 +68,7 @@ public class Mod _ => throw new ArgumentException($"Unknown type \"{info.Type}\"") }, RootDirectory = root, - SearchPaths = info.FileSystem.SearchPaths, + SearchPaths = new(), ShowDifficultyMenu = info.NoDifficulty is null || !info.NoDifficulty.Value, ShowModelMenu = info.NoModels is null || !info.NoModels.Value, ShowPortalMenu = info.HasPortals is not null && info.HasPortals.Value, @@ -91,6 +91,24 @@ public class Mod if (info.SupportsXBox360 is not null && info.SupportsXBox360.Value) curMod.SupportingFlags |= SupportFlags.XBox360; + foreach (KeyValuePair pair in info.FileSystem.SearchPaths) + { + SearchPathType type = SearchPathType.Unknown; + string[] parts = pair.Key.Trim().ToLower().Split('+'); + foreach (string part in parts) type |= part switch + { + "game" => SearchPathType.Game, + "game_write" => SearchPathType.GameWrite, + "gamebin" => SearchPathType.GameBinaries, + "platform" => SearchPathType.Platform, + "mod" => SearchPathType.Mod, + "mod_write" => SearchPathType.ModWrite, + "default_write_path" => SearchPathType.DefaultWritePath, + "vpk" => SearchPathType.Vpk, + _ => SearchPathType.Unknown + }; + } + return curMod; } @@ -138,6 +156,20 @@ public class Mod XBox360 = 4 } + [Flags] + public enum SearchPathType + { + Unknown = 0, + Game = 1, + GameWrite = 2, + GameBinaries = 4, + Platform = 8, + Mod = 16, + ModWrite = 32, + DefaultWritePath = 64, + Vpk = 128 + } + public enum PlayerType { Singleplayer = 1, -- 2.49.0.windows.1 From 858bd580b6f4812691cc208df7b47fc024958b4d Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 16 May 2023 08:31:06 -0400 Subject: [PATCH 84/89] Fixed a config parsing error with booleans. --- .../Shell/Modules/ObjectModels/TypeParsers.cs | 89 +++++++++++++------ SrcMod/Shell/ObjectModels/Config.cs | 3 + 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs b/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs index f2affd8..01d71ff 100644 --- a/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs +++ b/SrcMod/Shell/Modules/ObjectModels/TypeParsers.cs @@ -2,38 +2,73 @@ public static class TypeParsers { - public static bool CanParse(object? obj) => obj is not null && obj is sbyte or byte or short or ushort or int - or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal + public static bool CanParse(object? obj) => obj is not null && obj is bool or sbyte or byte or short or ushort + or int or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal or char or DateOnly or DateTime or DateTimeOffset or Guid or TimeOnly or TimeSpan; public static object ParseAll(string msg) { - if (TryParse(msg, out sbyte int8)) return int8; - if (TryParse(msg, out byte uInt8)) return uInt8; - if (TryParse(msg, out short int16)) return int16; - if (TryParse(msg, out ushort uInt16)) return uInt16; - if (TryParse(msg, out int int32)) return int32; - if (TryParse(msg, out uint uInt32)) return uInt32; - if (TryParse(msg, out long int64)) return int64; - if (TryParse(msg, out ulong uInt64)) return uInt64; - if (TryParse(msg, out Int128 int128)) return int128; - if (TryParse(msg, out UInt128 uInt128)) return uInt128; - if (TryParse(msg, out nint intPtr)) return intPtr; - if (TryParse(msg, out nuint uIntPtr)) return uIntPtr; - if (TryParse(msg, out Half float16)) return float16; - if (TryParse(msg, out float float32)) return float32; - if (TryParse(msg, out double float64)) return float64; - if (TryParse(msg, out decimal float128)) return float128; - if (TryParse(msg, out char resChar)) return resChar; - if (TryParse(msg, out DateOnly dateOnly)) return dateOnly; - if (TryParse(msg, out DateTime dateTime)) return dateTime; - if (TryParse(msg, out DateTimeOffset dateTimeOffset)) return dateTimeOffset; - if (TryParse(msg, out Guid guid)) return guid; - if (TryParse(msg, out TimeOnly timeOnly)) return timeOnly; - if (TryParse(msg, out TimeSpan timeSpan)) return timeSpan; - - return msg; + if (TryParseBool(msg, out bool resBool)) return resBool; + else if (TryParse(msg, out sbyte int8)) return int8; + else if (TryParse(msg, out byte uInt8)) return uInt8; + else if (TryParse(msg, out short int16)) return int16; + else if (TryParse(msg, out ushort uInt16)) return uInt16; + else if (TryParse(msg, out int int32)) return int32; + else if (TryParse(msg, out uint uInt32)) return uInt32; + else if (TryParse(msg, out long int64)) return int64; + else if (TryParse(msg, out ulong uInt64)) return uInt64; + else if (TryParse(msg, out Int128 int128)) return int128; + else if (TryParse(msg, out UInt128 uInt128)) return uInt128; + else if (TryParse(msg, out nint intPtr)) return intPtr; + else if (TryParse(msg, out nuint uIntPtr)) return uIntPtr; + else if (TryParse(msg, out Half float16)) return float16; + else if (TryParse(msg, out float float32)) return float32; + else if (TryParse(msg, out double float64)) return float64; + else if (TryParse(msg, out decimal float128)) return float128; + else if (TryParse(msg, out char resChar)) return resChar; + else if (TryParse(msg, out DateOnly dateOnly)) return dateOnly; + else if (TryParse(msg, out DateTime dateTime)) return dateTime; + else if (TryParse(msg, out DateTimeOffset dateTimeOffset)) return dateTimeOffset; + else if (TryParse(msg, out Guid guid)) return guid; + else if (TryParse(msg, out TimeOnly timeOnly)) return timeOnly; + else if (TryParse(msg, out TimeSpan timeSpan)) return timeSpan; + else return msg; } + public static bool TryParseBool(string msg, out bool result) + { + string trimmed = msg.Trim().ToLower(); + + string[] trues = new string[] + { + "t", + "true", + "1", + "y", + "yes" + }, + falses = new string[] + { + "f", + "false", + "0", + "n", + "no" + }; + + foreach (string t in trues) if (trimmed == t) + { + result = true; + return true; + } + foreach (string f in falses) if (trimmed == f) + { + result = false; + return true; + } + + result = false; + return false; + } public static bool TryParse(string msg, out T? result) where T : IParsable => T.TryParse(msg, null, out result); } diff --git a/SrcMod/Shell/ObjectModels/Config.cs b/SrcMod/Shell/ObjectModels/Config.cs index af83ac4..f7121e2 100644 --- a/SrcMod/Shell/ObjectModels/Config.cs +++ b/SrcMod/Shell/ObjectModels/Config.cs @@ -71,6 +71,7 @@ public class Config public string[] GameDirectories; public AskMode RunUnsafeCommands; + public bool UseLocalModDirectories; internal Config() { @@ -130,6 +131,7 @@ public class Config } RunUnsafeCommands = AskMode.Ask; + UseLocalModDirectories = true; } public Config ApplyChanges(Changes changes) @@ -230,6 +232,7 @@ public class Config { public string[]? GameDirectories; public AskMode? RunUnsafeCommands; + public bool? UseLocalModDirectories; public bool Any() => typeof(Changes).GetFields().Any(x => x.GetValue(this) is not null); } -- 2.49.0.windows.1 From 82afefd3e7b46e97f0f439310d0c1b56623b5691 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Tue, 16 May 2023 09:01:26 -0400 Subject: [PATCH 85/89] Added the VkvKeyName attribute. --- .../Vkv/ObjectModels/VkvKeyNameAttribute.cs | 9 +++++++++ SrcMod/Valve.NET/Vkv/VkvConvert.cs | 14 ++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 SrcMod/Valve.NET/Vkv/ObjectModels/VkvKeyNameAttribute.cs diff --git a/SrcMod/Valve.NET/Vkv/ObjectModels/VkvKeyNameAttribute.cs b/SrcMod/Valve.NET/Vkv/ObjectModels/VkvKeyNameAttribute.cs new file mode 100644 index 0000000..4c54a97 --- /dev/null +++ b/SrcMod/Valve.NET/Vkv/ObjectModels/VkvKeyNameAttribute.cs @@ -0,0 +1,9 @@ +namespace Valve.Vkv.ObjectModels; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] +public class VkvKeyNameAttribute : Attribute +{ + public readonly string name; + + public VkvKeyNameAttribute(string name) => this.name = name; +} diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index 45f8ff3..5458bd9 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -176,9 +176,9 @@ public static class VkvConvert foreach (FieldInfo field in validFields) { - string name = field.Name; + VkvKeyNameAttribute? namingAttribute = field.GetCustomAttribute(); - VkvNode? subNode = node[name]; + VkvNode? subNode = node[namingAttribute?.name ?? field.Name]; if (subNode is null) continue; object? result = FromNodeTree(field.FieldType, subNode, options); @@ -187,9 +187,9 @@ public static class VkvConvert } foreach (PropertyInfo prop in validProperties) { - string name = prop.Name; + VkvKeyNameAttribute? namingAttribute = prop.GetCustomAttribute(); - VkvNode? subNode = node[name]; + VkvNode? subNode = node[namingAttribute?.name ?? prop.Name]; if (subNode is null) continue; object? result = FromNodeTree(prop.PropertyType, subNode, options); @@ -400,11 +400,13 @@ public static class VkvConvert foreach (FieldInfo field in validFields) { - tree[field.Name] = ToNodeTree(field.GetValue(obj), options); + VkvKeyNameAttribute? namingAttribute = field.GetCustomAttribute(); + tree[namingAttribute?.name ?? field.Name] = ToNodeTree(field.GetValue(obj), options); } foreach (PropertyInfo prop in validProperties) { - tree[prop.Name] = ToNodeTree(prop.GetValue(obj), options); + VkvKeyNameAttribute? namingAttribute = prop.GetCustomAttribute(); + tree[namingAttribute?.name ?? prop.Name] = ToNodeTree(prop.GetValue(obj), options); } return tree; -- 2.49.0.windows.1 From 7cad137f3969a13e12a1c581e571015da25efd00 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 16 May 2023 16:10:32 -0400 Subject: [PATCH 86/89] Added a no exception mode for the VKV serializers. --- SrcMod/Valve.NET/Vkv/VkvConvert.cs | 178 +++++++++++++++----------- SrcMod/Valve.NET/Vkv/VkvOptions.cs | 2 + SrcMod/Valve.NET/Vkv/VkvSerializer.cs | 4 +- 3 files changed, 109 insertions(+), 75 deletions(-) diff --git a/SrcMod/Valve.NET/Vkv/VkvConvert.cs b/SrcMod/Valve.NET/Vkv/VkvConvert.cs index 5458bd9..76c6c25 100644 --- a/SrcMod/Valve.NET/Vkv/VkvConvert.cs +++ b/SrcMod/Valve.NET/Vkv/VkvConvert.cs @@ -1,6 +1,4 @@ -using Valve.Vkv.ObjectModels; - -namespace Valve.Vkv; +namespace Valve.Vkv; public static class VkvConvert { @@ -21,9 +19,19 @@ public static class VkvConvert #region DeserializeNode public static VkvNode? DeserializeNode(StreamReader reader) => - DeserializeNode(reader, VkvOptions.Default, out _, null); - public static VkvNode? DeserializeNode(StreamReader reader, VkvOptions options) => - DeserializeNode(reader, options, out _, null); + DeserializeNode(reader, VkvOptions.Default); + public static VkvNode? DeserializeNode(StreamReader reader, VkvOptions options) + { + try + { + return DeserializeNode(reader, options, out _, null); + } + catch + { + if (!options.noExceptions) throw; + return null; + } + } private static VkvNode? DeserializeNode(StreamReader reader, VkvOptions options, out string name, string? first) @@ -114,11 +122,19 @@ public static class VkvConvert public static T? FromNodeTree(VkvNode? node, VkvOptions options) => (T?)FromNodeTree(typeof(T), node, options); public static object? FromNodeTree(Type outputType, VkvNode? node, VkvOptions options) { - if (node is null) return null; + try + { + if (node is null) return null; - if (node is VkvSingleNode single) return FromSingleNode(outputType, single); - else if (node is VkvTreeNode tree) return FromTreeNode(outputType, tree, options); - else throw new VkvSerializationException("Unknown VKV node type."); + if (node is VkvSingleNode single) return FromSingleNode(outputType, single); + else if (node is VkvTreeNode tree) return FromTreeNode(outputType, tree, options); + else throw new VkvSerializationException("Unknown VKV node type."); + } + catch + { + if (!options.noExceptions) throw; + return null; + } } private static object? FromSingleNode(Type outputType, VkvSingleNode node) @@ -267,9 +283,19 @@ public static class VkvConvert #region SerializeNode public static void SerializeNode(StreamWriter writer, VkvNode? node, string name, - VkvOptions options) => SerializeNode(writer, node, name, options, 0); + VkvOptions options) + { + try + { + SerializeNode(writer, node, name, options, 0); + } + catch + { + if (!options.noExceptions) throw; + } + } public static void SerializeNode(StreamWriter writer, VkvNode? node, string name) => - SerializeNode(writer, node, name, VkvOptions.Default, 0); + SerializeNode(writer, node, name, VkvOptions.Default); private static void SerializeNode(StreamWriter writer, VkvNode? node, string name, VkvOptions options, int indentLevel) @@ -343,73 +369,81 @@ public static class VkvConvert public static VkvNode? ToNodeTree(object? obj) => ToNodeTree(obj, VkvOptions.Default); public static VkvNode? ToNodeTree(object? obj, VkvOptions options) { - if (obj is null) return null; - Type type = obj.GetType(); - - if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj); - else if (type.IsPointer) throw new("Cannot serialize a pointer."); - - VkvTreeNode tree = new(); - - if (obj is IVkvConvertible vkv) return vkv.ToNodeTree(); - else if (obj is IDictionary dictionary) + try { - object[] keys = new object[dictionary.Count], - values = new object[dictionary.Count]; - dictionary.Keys.CopyTo(keys, 0); - dictionary.Values.CopyTo(values, 0); - for (int i = 0; i < dictionary.Count; i++) + if (obj is null) return null; + Type type = obj.GetType(); + + if (type.IsPrimitive || TypeParsers.CanParse(obj)) return new VkvSingleNode(obj); + else if (type.IsPointer) throw new("Cannot serialize a pointer."); + + VkvTreeNode tree = new(); + + if (obj is IVkvConvertible vkv) return vkv.ToNodeTree(); + else if (obj is IDictionary dictionary) { - tree[SerializeObject(keys.GetValue(i))!] = ToNodeTree(values.GetValue(i), options); + object[] keys = new object[dictionary.Count], + values = new object[dictionary.Count]; + dictionary.Keys.CopyTo(keys, 0); + dictionary.Values.CopyTo(values, 0); + for (int i = 0; i < dictionary.Count; i++) + { + tree[SerializeObject(keys.GetValue(i))!] = ToNodeTree(values.GetValue(i), options); + } + return tree; } + else if (obj is ICollection enumerable) + { + int index = 0; + foreach (object item in enumerable) + { + tree[SerializeObject(index)!] = ToNodeTree(item, options); + index++; + } + return tree; + } + + IEnumerable validFields = from field in type.GetFields() + let isPublic = field.IsPublic + let isStatic = field.IsStatic + let isIgnored = field.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + let isConst = field.IsLiteral + where isPublic && !isStatic && !isIgnored && !isConst + select field; + + IEnumerable validProperties; + if (options.serializeProperties) + { + validProperties = from prop in type.GetProperties() + let canGet = prop.GetMethod is not null + let isPublic = canGet && prop.GetMethod!.IsPublic + let isStatic = canGet && prop.GetMethod!.IsStatic + let isIgnored = prop.CustomAttributes.Any(x => + x.AttributeType == typeof(VkvIgnoreAttribute)) + where canGet && isPublic && !isStatic && !isIgnored + select prop; + } + else validProperties = Array.Empty(); + + foreach (FieldInfo field in validFields) + { + VkvKeyNameAttribute? namingAttribute = field.GetCustomAttribute(); + tree[namingAttribute?.name ?? field.Name] = ToNodeTree(field.GetValue(obj), options); + } + foreach (PropertyInfo prop in validProperties) + { + VkvKeyNameAttribute? namingAttribute = prop.GetCustomAttribute(); + tree[namingAttribute?.name ?? prop.Name] = ToNodeTree(prop.GetValue(obj), options); + } + return tree; } - else if (obj is ICollection enumerable) + catch { - int index = 0; - foreach (object item in enumerable) - { - tree[SerializeObject(index)!] = ToNodeTree(item, options); - index++; - } - return tree; + if (!options.noExceptions) throw; + return null; } - - IEnumerable validFields = from field in type.GetFields() - let isPublic = field.IsPublic - let isStatic = field.IsStatic - let isIgnored = field.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - let isConst = field.IsLiteral - where isPublic && !isStatic && !isIgnored && !isConst - select field; - - IEnumerable validProperties; - if (options.serializeProperties) - { - validProperties = from prop in type.GetProperties() - let canGet = prop.GetMethod is not null - let isPublic = canGet && prop.GetMethod!.IsPublic - let isStatic = canGet && prop.GetMethod!.IsStatic - let isIgnored = prop.CustomAttributes.Any(x => - x.AttributeType == typeof(VkvIgnoreAttribute)) - where canGet && isPublic && !isStatic && !isIgnored - select prop; - } - else validProperties = Array.Empty(); - - foreach (FieldInfo field in validFields) - { - VkvKeyNameAttribute? namingAttribute = field.GetCustomAttribute(); - tree[namingAttribute?.name ?? field.Name] = ToNodeTree(field.GetValue(obj), options); - } - foreach (PropertyInfo prop in validProperties) - { - VkvKeyNameAttribute? namingAttribute = prop.GetCustomAttribute(); - tree[namingAttribute?.name ?? prop.Name] = ToNodeTree(prop.GetValue(obj), options); - } - - return tree; } #endregion } diff --git a/SrcMod/Valve.NET/Vkv/VkvOptions.cs b/SrcMod/Valve.NET/Vkv/VkvOptions.cs index 4bf92f3..ceb461d 100644 --- a/SrcMod/Valve.NET/Vkv/VkvOptions.cs +++ b/SrcMod/Valve.NET/Vkv/VkvOptions.cs @@ -6,6 +6,7 @@ public record class VkvOptions public bool closeWhenFinished; public int indentSize; + public bool noExceptions; public bool resetStreamPosition; public bool serializeProperties; public SpacingMode spacing; @@ -16,6 +17,7 @@ public record class VkvOptions { closeWhenFinished = true; indentSize = 4; + noExceptions = false; resetStreamPosition = false; serializeProperties = true; spacing = SpacingMode.DoubleTab; diff --git a/SrcMod/Valve.NET/Vkv/VkvSerializer.cs b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs index fe3e8d0..9a18935 100644 --- a/SrcMod/Valve.NET/Vkv/VkvSerializer.cs +++ b/SrcMod/Valve.NET/Vkv/VkvSerializer.cs @@ -1,6 +1,4 @@ -using System.Reflection.PortableExecutable; - -namespace Valve.Vkv; +namespace Valve.Vkv; public class VkvSerializer { -- 2.49.0.windows.1 From 3a961fffbbc278e956374ebb9a3adfcdaa35b482 Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Tue, 16 May 2023 16:18:11 -0400 Subject: [PATCH 87/89] Forgot to actually make the variable do something. --- SrcMod/Shell/Shell.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index e21cc26..ffa2383 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -153,7 +153,7 @@ public class Shell if (ActiveMod is not null) Write($"{ActiveMod} ", ConsoleColor.Magenta, false); - if (ActiveMod is not null) + if (ActiveMod is not null && Config.LoadedConfig.UseLocalModDirectories) { string directory = Path.GetRelativePath(ActiveMod.RootDirectory, WorkingDirectory); if (directory == ".") directory = string.Empty; -- 2.49.0.windows.1 From 287cd26bcb2211ee8defc6d97d043556c7b18066 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 18 May 2023 11:06:28 -0400 Subject: [PATCH 88/89] Shell now syncs its active game with the mod's base game. --- SrcMod/Shell/Shell.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SrcMod/Shell/Shell.cs b/SrcMod/Shell/Shell.cs index ffa2383..766e479 100644 --- a/SrcMod/Shell/Shell.cs +++ b/SrcMod/Shell/Shell.cs @@ -161,7 +161,7 @@ public class Shell } else Write($"{WorkingDirectory}", ConsoleColor.DarkGreen, false); - if (ActiveGame is not null) Write($" ({ActiveGame})", ConsoleColor.DarkYellow, false); + if (ActiveGame is not null) Write($" ({ActiveGame})", ConsoleColor.Blue, false); Write(null); Write($" {Name}", ConsoleColor.DarkCyan, false); @@ -323,6 +323,7 @@ public class Shell try { ActiveMod = Mod.ReadDirectory(WorkingDirectory); + ActiveGame = ActiveMod?.BaseGame; // Update title. string title = "SrcMod"; -- 2.49.0.windows.1 From 8804ac08d9a3a66e71d7cd146e5786ae3d386ec6 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Thu, 18 May 2023 11:12:27 -0400 Subject: [PATCH 89/89] Synced type parsers. --- SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs | 96 ++++++++++++------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs index 0369d68..15a1bbd 100644 --- a/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs +++ b/SrcMod/Valve.NET/Miscellaneous/TypeParsers.cs @@ -2,45 +2,73 @@ public static class TypeParsers { - public static bool CanParse(object? obj) => obj is not null && obj is sbyte or byte or short or ushort or int - or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal + public static bool CanParse(object? obj) => obj is not null && obj is bool or sbyte or byte or short or ushort + or int or uint or long or ulong or Int128 or UInt128 or nint or nuint or Half or float or double or decimal or char or DateOnly or DateTime or DateTimeOffset or Guid or TimeOnly or TimeSpan; - public static bool CanParse(Type type) => type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) - || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) - || type == typeof(ulong) || type == typeof(Int128) || type == typeof(UInt128) || type == typeof(nint) - || type == typeof(nuint) || type == typeof(Half) || type == typeof(float) || type == typeof(double) - || type == typeof(decimal) || type == typeof(char) || type == typeof(DateOnly) || type == typeof(DateTime) - || type == typeof(DateTimeOffset) || type == typeof(Guid) || type == typeof(TimeOnly) - || type == typeof(TimeSpan); public static object ParseAll(string msg) { - if (TryParse(msg, out sbyte int8)) return int8; - if (TryParse(msg, out byte uInt8)) return uInt8; - if (TryParse(msg, out short int16)) return int16; - if (TryParse(msg, out ushort uInt16)) return uInt16; - if (TryParse(msg, out int int32)) return int32; - if (TryParse(msg, out uint uInt32)) return uInt32; - if (TryParse(msg, out long int64)) return int64; - if (TryParse(msg, out ulong uInt64)) return uInt64; - if (TryParse(msg, out Int128 int128)) return int128; - if (TryParse(msg, out UInt128 uInt128)) return uInt128; - if (TryParse(msg, out nint intPtr)) return intPtr; - if (TryParse(msg, out nuint uIntPtr)) return uIntPtr; - if (TryParse(msg, out Half float16)) return float16; - if (TryParse(msg, out float float32)) return float32; - if (TryParse(msg, out double float64)) return float64; - if (TryParse(msg, out decimal float128)) return float128; - if (TryParse(msg, out char resChar)) return resChar; - if (TryParse(msg, out DateOnly dateOnly)) return dateOnly; - if (TryParse(msg, out DateTime dateTime)) return dateTime; - if (TryParse(msg, out DateTimeOffset dateTimeOffset)) return dateTimeOffset; - if (TryParse(msg, out Guid guid)) return guid; - if (TryParse(msg, out TimeOnly timeOnly)) return timeOnly; - if (TryParse(msg, out TimeSpan timeSpan)) return timeSpan; - - return msg; + if (TryParseBool(msg, out bool resBool)) return resBool; + else if (TryParse(msg, out sbyte int8)) return int8; + else if (TryParse(msg, out byte uInt8)) return uInt8; + else if (TryParse(msg, out short int16)) return int16; + else if (TryParse(msg, out ushort uInt16)) return uInt16; + else if (TryParse(msg, out int int32)) return int32; + else if (TryParse(msg, out uint uInt32)) return uInt32; + else if (TryParse(msg, out long int64)) return int64; + else if (TryParse(msg, out ulong uInt64)) return uInt64; + else if (TryParse(msg, out Int128 int128)) return int128; + else if (TryParse(msg, out UInt128 uInt128)) return uInt128; + else if (TryParse(msg, out nint intPtr)) return intPtr; + else if (TryParse(msg, out nuint uIntPtr)) return uIntPtr; + else if (TryParse(msg, out Half float16)) return float16; + else if (TryParse(msg, out float float32)) return float32; + else if (TryParse(msg, out double float64)) return float64; + else if (TryParse(msg, out decimal float128)) return float128; + else if (TryParse(msg, out char resChar)) return resChar; + else if (TryParse(msg, out DateOnly dateOnly)) return dateOnly; + else if (TryParse(msg, out DateTime dateTime)) return dateTime; + else if (TryParse(msg, out DateTimeOffset dateTimeOffset)) return dateTimeOffset; + else if (TryParse(msg, out Guid guid)) return guid; + else if (TryParse(msg, out TimeOnly timeOnly)) return timeOnly; + else if (TryParse(msg, out TimeSpan timeSpan)) return timeSpan; + else return msg; } + public static bool TryParseBool(string msg, out bool result) + { + string trimmed = msg.Trim().ToLower(); + + string[] trues = new string[] + { + "t", + "true", + "1", + "y", + "yes" + }, + falses = new string[] + { + "f", + "false", + "0", + "n", + "no" + }; + + foreach (string t in trues) if (trimmed == t) + { + result = true; + return true; + } + foreach (string f in falses) if (trimmed == f) + { + result = false; + return true; + } + + result = false; + return false; + } public static bool TryParse(string msg, out T? result) where T : IParsable => T.TryParse(msg, null, out result); } -- 2.49.0.windows.1