From c58db54735e047e0c2cdb21046f416549e8629ba Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 03:11:13 +0200 Subject: [PATCH 01/11] [Minor] improves exceptions for MatchX operation, adds information about filename and patchingway later --- ModUtils/CodeUtils.cs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index 8af9f2c..e0c1447 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -470,7 +470,10 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) if (!foundMatch) { - throw new Exception("MatchFrom: No matching lines found. Items to match: " + string.Join(", ", other)); + throw new InvalidOperationException(string.Format( + "MatchFrom: No matching lines found. Items to match:\n{0}", + string.Join("\n", other)) + ); } } @@ -549,7 +552,10 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) if (!encounteredTheBlock) { - throw new Exception("MatchBelow: No matching lines found. Items to match: " + string.Join("\r\n", other)); + throw new InvalidOperationException( + string.Format("MatchBelow: No matching lines found. Items to match:\n{0}", + string.Join("\n", other)) + ); } } /// @@ -653,6 +659,15 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) yield return (Match.After, element); } } + + if (!foundUntil) + { + throw new InvalidOperationException( + string.Format("MatchFromUntil: No matching lines found. Items to match:\nFrom\n{0}\nTo\n{1}", + string.Join("\n", otherfrom), + string.Join("\n", otheruntil)) + ); + } } /// /// Same behaviour as but using .Split('\n') and .Split('\n') for the comparison. @@ -991,8 +1006,10 @@ public static ModSummary Save(this FileEnumerable fe) fe.header.patchingWay ); } - catch + catch (Exception ex) { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay.ToString()); throw; } } From 625fe85bdfc16d764d66322f4de38f8030d41d84 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 16:49:12 +0200 Subject: [PATCH 02/11] [Major] moves checksumchecker and exporter into their respective class, adds the new checksum value and removes older ones, log an error if users load a yyc file and handle gracefully its error, improves stability when loading a file. --- Controls/ModInfos.xaml.cs | 2 +- DataLoader.cs | 191 +++++++++----------------------------- Loader/ChecksumChecker.cs | 34 +++++++ Loader/Exporter.cs | 98 +++++++++++++++++++ Main.xaml.cs | 1 - ModShardLauncher.csproj | 1 + 6 files changed, 178 insertions(+), 149 deletions(-) create mode 100644 Loader/ChecksumChecker.cs create mode 100644 Loader/Exporter.cs diff --git a/Controls/ModInfos.xaml.cs b/Controls/ModInfos.xaml.cs index 7ff1e38..89531ea 100644 --- a/Controls/ModInfos.xaml.cs +++ b/Controls/ModInfos.xaml.cs @@ -62,7 +62,7 @@ private async void Save_Click(object sender, EventArgs e) } // reload the data - await DataLoader.LoadFile(DataLoader.dataPath, true); + await DataLoader.LoadFile(DataLoader.dataPath); Main.Instance.Refresh(); } diff --git a/DataLoader.cs b/DataLoader.cs index 526ee26..9b5f012 100644 --- a/DataLoader.cs +++ b/DataLoader.cs @@ -1,17 +1,13 @@ using UndertaleModLib; -using UndertaleModLib.Models; using System.Threading.Tasks; using System.IO; using System; -using System.Windows; using UndertaleModLib.Util; using System.Linq; using Microsoft.Win32; using System.Collections.Generic; -using Newtonsoft.Json; using Serilog; -using UndertaleModLib.Decompiler; -using System.Security.Cryptography; +using ModShardLauncher.Loader; namespace ModShardLauncher { @@ -20,15 +16,19 @@ public class DataLoader public static UndertaleData data = new(); internal static string dataPath = ""; internal static string savedDataPath = ""; - public delegate void FileMessageEventHandler(string message); - public static event FileMessageEventHandler FileMessageEvent; - public static void ShowWarning(string warning, string title) + public static void LogUTMTWarnings(string warning) { - Console.WriteLine(title + ":" + warning); + Log.Warning("[UTMT WARNING]: {0}", warning); } - public static void ShowError(string error, string title) + public static void LogUTMTMessages(string message) { - Console.WriteLine(title + ":" + error); + return; //Log.Information("[UTMT MESSAGE]: {0}", message); + } + public static void Reset() + { + data = new(); + dataPath = ""; + savedDataPath = ""; } public static async Task DoOpenDialog() { @@ -42,129 +42,31 @@ public static async Task DoOpenDialog() // load if (dlg.ShowDialog() == true) { - await LoadFile(dlg.FileName); - return true; - } - - // nothing was load - return false; - } - private static void ExportData() - { - File.WriteAllText("json_dump_code.json", JsonConvert.SerializeObject(data.Code.Select(t => t.Name.Content))); - File.WriteAllText("json_dump_variables.json", JsonConvert.SerializeObject(data.Variables.Select(t => t.Name.Content))); - File.WriteAllText("json_dump_rooms.json", JsonConvert.SerializeObject(data.Rooms.Select(t => t.Name.Content))); - Msl.GenerateNRandomLinesFromCode(data.Code, new GlobalDecompileContext(data, false), 100, 1, 0); - } - /// - /// Export all items, weapons and armors in csv files. - /// - private static void ExportItems() - { - try - { - DirectoryInfo dir = new("export"); - if (dir.Exists) dir.Delete(true); - dir.Create(); - - List? weapons = ModLoader.GetTable("gml_GlobalScript_table_weapons"); - List? armor = ModLoader.GetTable("gml_GlobalScript_table_armor"); - - File.WriteAllLines( - Path.Join(dir.FullName, Path.DirectorySeparatorChar.ToString(), "_all_items.csv"), - data.GameObjects.Select(t => t.Name.Content).Where(x => x.Contains("o_inv_")).Select(x => x.Replace("o_inv_", "")) - ); - - if (weapons != null) + try { - File.WriteAllLines( - Path.Join(dir.FullName, Path.DirectorySeparatorChar.ToString(), "_all_weapons.csv"), - weapons.Select(x => string.Join(';', x.Split(';').Take(4))) - ); + await LoadFile(dlg.FileName); + return true; } - - if (armor != null) + catch (Exception ex) { - File.WriteAllLines( - Path.Join(dir.FullName, Path.DirectorySeparatorChar.ToString(), "_all_armors.csv"), - armor.Select(x => string.Join(';', x.Split(';').Take(6))) - ); + Log.Error(ex, "Something went wrong while loading {0}.", dlg.FileName); + Reset(); } } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } - } - private static void ExportPreset() - { - GlobalDecompileContext context = new(ModLoader.Data, false); - File.WriteAllText("json_preset_bastion.json", Decompiler.Decompile(data.Code.First(t => t.Name.Content.Contains("scr_preset_bastion_1")), context)); - File.WriteAllText("json_preset_catacombs.json", Decompiler.Decompile(data.Code.First(t => t.Name.Content.Contains("scr_preset_catacombs")), context)); - File.WriteAllText("json_preset_crypt.json", Decompiler.Decompile(data.Code.First(t => t.Name.Content.Contains("scr_preset_crypt_1")), context)); - } - /// - /// Compute the MD5 checksum of a file located in a FileStream. - /// - /// - /// - private static string ComputeChecksum(FileStream stream) - { - using var md5 = MD5.Create(); - return Convert.ToHexString(md5.ComputeHash(stream)); - } - /// - /// Return True if the MD5 checksum of a file is equal either to the MD5 checksum of the GOG data.win of Stoneshard or to the MD5 checksum of the STEAM data.win of Stoneshard. - /// - /// - /// - private static bool CompareChecksum(FileStream stream) - { - string hash = ComputeChecksum(stream); - // Log.Information(hash); // uncomment to log the checksum of new versions and add to the array - string[] checksums = - { - "6E37E076EDFDC25468195EC1FFA937A5", // GOG 0.8.2.10 - "392EE0E8C6A09A16DED58C5737ECF1B5", // Steam 0.8.2.10 - "5F91989CA7E2A2B1234B2CD2A6AF9821", // Steam 0.9.1.16-vm - "2BD331F728428746FA337D6C7B67040A", // Steam 0.9.1.17-vm - "6F9F1E29275EEF60E3A725ECA1033DF8" // Steam 0.9.1.18-vm - }; - return checksums.Contains(hash); + + // nothing was load + return false; } - private static bool LoadUmt(string filename) + private static void LoadUmt(string filename) { - bool hadWarnings = false; - using (FileStream stream = new(filename, FileMode.Open, FileAccess.Read)) + using FileStream stream = new(filename, FileMode.Open, FileAccess.Read); + if (!ChecksumChecker.CompareChecksum(stream)) { - if(!CompareChecksum(stream)) - { - Log.Warning("Checksum inconsistency, {{{0}}} may not be vanilla or is a new version.", filename); - } - data = UndertaleIO.Read( - stream, warning => - { - ShowWarning(warning, "Loading warning"); - - if (warning.Contains("unserializeCountError.txt") || warning.Contains("object pool size")) - return; - - hadWarnings = true; - }, - delegate (string message) - { - FileMessageEvent?.Invoke(message); - } - ); + Log.Warning("Checksum inconsistency, {{{0}}} may not be steam vanilla from the modbranch beta branch or is a new version.", filename); } - - //UndertaleEmbeddedTexture.TexData.ClearSharedStream(); - Log.Information(string.Format("Successfully load: {0}.", filename)); - - return hadWarnings; + data = UndertaleIO.Read(stream, LogUTMTWarnings, LogUTMTMessages); } - public static async Task LoadFile(string filename, bool re = false) + public static async Task LoadFile(string filename) { // save the filename for later dataPath = filename; @@ -176,16 +78,7 @@ public static async Task LoadFile(string filename, bool re = false) // task load a data.win with umt Task taskLoadDataWinWithUmt = Task.Run(() => { - bool hadWarnings = false; - try - { - hadWarnings = LoadUmt(filename); - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + LoadUmt(filename); Main.Instance.Dispatcher.Invoke(() => { dialog.Hide(); @@ -194,10 +87,21 @@ public static async Task LoadFile(string filename, bool re = false) // run dialog.ShowDialog(); await taskLoadDataWinWithUmt; + + if (data.IsYYC()) + { + throw new InvalidDataException(string.Format( + "{{{0}}} was made with YYC (YoYo Compiler) which is unmodable currently. You should move to the beta branch called modbranch instead.", + filename + )); + } + + Log.Information(string.Format("Successfully load: {0}.", filename)); + ModLoader.Initalize(); // cleaning loot table LootUtils.ResetLootTables(); - ExportItems(); + data.Export(DataType.Items); } public static async Task DoSaveDialog() { @@ -221,10 +125,7 @@ private static void SaveTempWithUmt(string filename) { using (FileStream stream = new(filename + "temp", FileMode.Create, FileAccess.Write)) { - UndertaleIO.Write(stream, data, message => - { - FileMessageEvent?.Invoke(message); - }); + UndertaleIO.Write(stream, data, LogUTMTMessages); } //UndertaleEmbeddedTexture.TexData.ClearSharedStream(); @@ -236,12 +137,8 @@ private static void HandleFailedSave(Exception exception) { try { - IEnumerable enumerableChunks = data.FORM.Chunks.Values.Where(x => x is not null).Select((UndertaleChunk x) => x as IUndertaleListChunk); - Parallel.ForEach(enumerableChunks, (chunk) => - { - chunk.ClearIndexDict(); - }); - + IEnumerable enumerableChunks = data.FORM.Chunks.Values.Where(x => x is not null).Select(x => (IUndertaleListChunk)x); + Parallel.ForEach(enumerableChunks, (chunk) => chunk.ClearIndexDict()); UndertaleIO.IsDictionaryCleared = true; } catch { } @@ -249,7 +146,7 @@ private static void HandleFailedSave(Exception exception) Main.Instance.Dispatcher.Invoke(() => { - ShowError("An error occured while trying to save:\n" + exception.Message, "Save error"); + Log.Error("An error occured while trying to save:\n" + exception.Message, "Save error"); }); } public static async Task SaveFile(string filename) @@ -291,7 +188,7 @@ public static async Task SaveFile(string filename) { Main.Instance.Dispatcher.Invoke(() => { - ShowError("An error occured while trying to save:\n" + exc.Message, "Save error"); + Log.Error("An error occured while trying to save:\n" + exc.Message, "Save error"); }); SaveSucceeded = false; diff --git a/Loader/ChecksumChecker.cs b/Loader/ChecksumChecker.cs new file mode 100644 index 0000000..e11fc76 --- /dev/null +++ b/Loader/ChecksumChecker.cs @@ -0,0 +1,34 @@ +using System.IO; +using System; +using System.Linq; +using System.Security.Cryptography; + +namespace ModShardLauncher.Loader +{ + static public class ChecksumChecker + { + private static string ComputeChecksum(FileStream stream) + { + using MD5 md5 = MD5.Create(); + return Convert.ToHexString(md5.ComputeHash(stream)); + } + /// + /// Return True if the MD5 checksum of a file is equal a valid precomputed checksum. + /// + /// + /// + public static bool CompareChecksum(FileStream stream) + { + string hash = ComputeChecksum(stream); + + string[] checksums = + { + "5F91989CA7E2A2B1234B2CD2A6AF9821", // Steam 0.9.1.16-vm + "2BD331F728428746FA337D6C7B67040A", // Steam 0.9.1.17-vm + "6F9F1E29275EEF60E3A725ECA1033DF8", // Steam 0.9.1.18-vm + "47282D0C650216D88AE25FA99615F9CB", // Steam 0.9.3.9-vm + }; + return checksums.Contains(hash); + } + } +} \ No newline at end of file diff --git a/Loader/Exporter.cs b/Loader/Exporter.cs new file mode 100644 index 0000000..2c214a6 --- /dev/null +++ b/Loader/Exporter.cs @@ -0,0 +1,98 @@ +using UndertaleModLib; +using System.IO; +using System; +using System.Linq; +using System.Collections.Generic; +using Newtonsoft.Json; +using Serilog; +using UndertaleModLib.Decompiler; + +namespace ModShardLauncher.Loader +{ + public enum DataType + { + Codes, + Items, + DungeonPresets, + } + static public class ExporterExtensions + { + /// + /// Export all code, variables and rooms name in json. + /// + private static void ExportCodes(UndertaleData data) + { + File.WriteAllText("json_dump_code.json", JsonConvert.SerializeObject(data.Code.Select(t => t.Name.Content))); + File.WriteAllText("json_dump_variables.json", JsonConvert.SerializeObject(data.Variables.Select(t => t.Name.Content))); + File.WriteAllText("json_dump_rooms.json", JsonConvert.SerializeObject(data.Rooms.Select(t => t.Name.Content))); + } + /// + /// Export all items, weapons and armors in csv. + /// + private static void ExportItems(UndertaleData data) + { + DirectoryInfo dir = new("export"); + if (dir.Exists) dir.Delete(true); + dir.Create(); + + List? weapons = ModLoader.GetTable("gml_GlobalScript_table_weapons"); + List? armor = ModLoader.GetTable("gml_GlobalScript_table_armor"); + + File.WriteAllLines( + Path.Join(dir.FullName, Path.DirectorySeparatorChar.ToString(), "_all_items.csv"), + data.GameObjects.Select(t => t.Name.Content).Where(x => x.Contains("o_inv_")).Select(x => x.Replace("o_inv_", "")) + ); + + if (weapons != null) + { + File.WriteAllLines( + Path.Join(dir.FullName, Path.DirectorySeparatorChar.ToString(), "_all_weapons.csv"), + weapons.Select(x => string.Join(';', x.Split(';').Take(4))) + ); + } + + if (armor != null) + { + File.WriteAllLines( + Path.Join(dir.FullName, Path.DirectorySeparatorChar.ToString(), "_all_armors.csv"), + armor.Select(x => string.Join(';', x.Split(';').Take(6))) + ); + } + } + /// + /// Export all preset data for all dungeons in json. + /// + private static void ExportPresets(UndertaleData data) + { + GlobalDecompileContext context = new(ModLoader.Data, false); + File.WriteAllText("json_preset_bastion.json", Decompiler.Decompile(data.Code.First(t => t.Name.Content.Contains("scr_preset_bastion_1")), context)); + File.WriteAllText("json_preset_catacombs.json", Decompiler.Decompile(data.Code.First(t => t.Name.Content.Contains("scr_preset_catacombs")), context)); + File.WriteAllText("json_preset_crypt.json", Decompiler.Decompile(data.Code.First(t => t.Name.Content.Contains("scr_preset_crypt_1")), context)); + } + /// + /// Export data for code exploration in json or csv. + /// + public static void Export(this UndertaleData data, DataType dataType) + { + try + { + switch (dataType) + { + case DataType.Codes: + ExportCodes(data); + break; + case DataType.Items: + ExportItems(data); + break; + case DataType.DungeonPresets: + ExportPresets(data); + break; + } + } + catch (Exception ex) + { + Log.Error(ex, "Something went wrong while exporting {{{0}}}", dataType); + } + } + } +} \ No newline at end of file diff --git a/Main.xaml.cs b/Main.xaml.cs index 6382b3d..ab9470a 100644 --- a/Main.xaml.cs +++ b/Main.xaml.cs @@ -38,7 +38,6 @@ public partial class Main : Window public static IntPtr handle; public string mslVersion; public string utmtlibVersion; - // private const double DefaultWidth = 960; // Исходная ширина private const double DefaultHeight = 800; // Исходная высота private const double AspectRatio = DefaultWidth / DefaultHeight; // Соотношение сторон diff --git a/ModShardLauncher.csproj b/ModShardLauncher.csproj index dc1d6a8..e740f76 100644 --- a/ModShardLauncher.csproj +++ b/ModShardLauncher.csproj @@ -30,6 +30,7 @@ + From 20a5c68298c5767f38fca65d76a0547079cb0904 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 19:56:08 +0200 Subject: [PATCH 03/11] [Minor] fixes crash if saving is cancelled --- Controls/ModInfos.xaml.cs | 18 +++++++--- DataLoader.cs | 69 +++++++++++++++++++++++---------------- ModUtils/LootUtils.cs | 19 +++++++---- 3 files changed, 67 insertions(+), 39 deletions(-) diff --git a/Controls/ModInfos.xaml.cs b/Controls/ModInfos.xaml.cs index 89531ea..adaa58b 100644 --- a/Controls/ModInfos.xaml.cs +++ b/Controls/ModInfos.xaml.cs @@ -35,15 +35,16 @@ private async void Save_Click(object sender, EventArgs e) } bool patchSucess = false; + bool saveSucess = false; - try + try { ModLoader.PatchFile(); Log.Information("Successfully patch vanilla"); patchSucess = true; Main.Instance.LogModList(); } - catch(Exception ex) + catch (Exception ex) { Main.Instance.LogModList(); Log.Error(ex, "Something went wrong"); @@ -52,14 +53,21 @@ private async void Save_Click(object sender, EventArgs e) } // attempt to save the patched data - if (patchSucess) + if (patchSucess) { Task save = DataLoader.DoSaveDialog(); await save; - if (!save.Result) Log.Information("Saved cancelled."); - // copy the dataloot.json in the stoneshard directory + saveSucess = save.Result; + } + + if (saveSucess) + { LootUtils.SaveLootTables(Msl.ThrowIfNull(Path.GetDirectoryName(DataLoader.savedDataPath))); } + else + { + Log.Information("Saved cancelled."); + } // reload the data await DataLoader.LoadFile(DataLoader.dataPath); diff --git a/DataLoader.cs b/DataLoader.cs index 9b5f012..5abc94e 100644 --- a/DataLoader.cs +++ b/DataLoader.cs @@ -44,6 +44,8 @@ public static async Task DoOpenDialog() { try { + // save the filename for later + dataPath = dlg.FileName; await LoadFile(dlg.FileName); return true; } @@ -68,8 +70,6 @@ private static void LoadUmt(string filename) } public static async Task LoadFile(string filename) { - // save the filename for later - dataPath = filename; // create a new dialog box LoadingDialog dialog = new() { @@ -115,8 +115,23 @@ public static async Task DoSaveDialog() if (dlg.ShowDialog() == true) { savedDataPath = dlg.FileName; - await SaveFile(dlg.FileName); - return true; + try + { + await SaveFile(dlg.FileName); + return true; + } + catch (AggregateException exs) + { + Log.Error("Multiple exceptions occurred during save operation for {{{0}}:", dlg.FileName); + foreach (Exception ex in exs.InnerExceptions) + { + Log.Error(ex, "Exception: {Message}", ex.Message); + } + } + catch (Exception ex) + { + Log.Error(ex, "An exception occurred during save operation for {{{0}}:", dlg.FileName); + } } return false; @@ -131,23 +146,14 @@ private static void SaveTempWithUmt(string filename) //UndertaleEmbeddedTexture.TexData.ClearSharedStream(); QoiConverter.ClearSharedBuffer(); } - private static void HandleFailedSave(Exception exception) + private static void HandleFailedSave() { if (!UndertaleIO.IsDictionaryCleared) { - try - { - IEnumerable enumerableChunks = data.FORM.Chunks.Values.Where(x => x is not null).Select(x => (IUndertaleListChunk)x); - Parallel.ForEach(enumerableChunks, (chunk) => chunk.ClearIndexDict()); - UndertaleIO.IsDictionaryCleared = true; - } - catch { } + IEnumerable enumerableChunks = data.FORM.Chunks.Values.Where(x => x is not null).Select(x => (IUndertaleListChunk)x); + Parallel.ForEach(enumerableChunks, (chunk) => chunk.ClearIndexDict()); + UndertaleIO.IsDictionaryCleared = true; } - - Main.Instance.Dispatcher.Invoke(() => - { - Log.Error("An error occured while trying to save:\n" + exception.Message, "Save error"); - }); } public static async Task SaveFile(string filename) { @@ -157,21 +163,30 @@ public static async Task SaveFile(string filename) Owner = Main.Instance }; - Task t = Task.Run(() => + Task taskSaveDataWinWithUmt = Task.Run(() => { + List exceptions = new(); bool SaveSucceeded = true; // try temp save first try { SaveTempWithUmt(filename); } - catch (Exception e) + catch (Exception savedException) { - HandleFailedSave(e); + exceptions.Add(savedException); + try + { + HandleFailedSave(); + } + catch (Exception handledException) + { + exceptions.Add(handledException); + } SaveSucceeded = false; } - // move save + // clean after saving try { if (SaveSucceeded) @@ -184,13 +199,9 @@ public static async Task SaveFile(string filename) if (File.Exists(filename + "temp")) File.Delete(filename + "temp"); } } - catch (Exception exc) + catch (Exception cleanUpException) { - Main.Instance.Dispatcher.Invoke(() => - { - Log.Error("An error occured while trying to save:\n" + exc.Message, "Save error"); - }); - + exceptions.Add(cleanUpException); SaveSucceeded = false; } @@ -198,11 +209,13 @@ public static async Task SaveFile(string filename) { dialog.Hide(); }); + + if (!SaveSucceeded) throw new AggregateException(exceptions); }); //run dialog.ShowDialog(); - await t; + await taskSaveDataWinWithUmt; } } } \ No newline at end of file diff --git a/ModUtils/LootUtils.cs b/ModUtils/LootUtils.cs index 308db2e..ee5ca48 100644 --- a/ModUtils/LootUtils.cs +++ b/ModUtils/LootUtils.cs @@ -82,15 +82,22 @@ public static void ResetLootTables() } public static void SaveLootTables(string DirPath) { - if (LootTables.Count > 0) + try { - File.WriteAllText(Path.Combine(DirPath, "loot_table.json"), JsonConvert.SerializeObject(LootTables)); - Log.Information("Successfully saving the loot table json."); + if (LootTables.Count > 0) + { + File.WriteAllText(Path.Combine(DirPath, "loot_table.json"), JsonConvert.SerializeObject(LootTables)); + Log.Information("Successfully saving the loot table json."); + } + if (ReferenceTables.Count > 0) + { + File.WriteAllText(Path.Combine(DirPath, "reference_table.json"), JsonConvert.SerializeObject(ReferenceTables)); + Log.Information("Successfully saving the reference table json."); + } } - if (ReferenceTables.Count > 0) + catch (Exception ex) { - File.WriteAllText(Path.Combine(DirPath, "reference_table.json"), JsonConvert.SerializeObject(ReferenceTables)); - Log.Information("Successfully saving the reference table json."); + Log.Error(ex, "Saving Loot table failed for {0}", DirPath); } } public static void InjectLootScripts() From ec7cb9e425731b89f5a617d9fe779517121566aa Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 22:45:48 +0200 Subject: [PATCH 04/11] [Major] removes string interpolation for logging --- DataLoader.cs | 2 +- FileReader.cs | 8 ++--- Main.xaml.cs | 2 +- ModLoader.cs | 6 ++-- ModUtils/AsmUtils.cs | 33 ++++++++++--------- ModUtils/CodeUtils.cs | 24 +++++++------- ModUtils/EventUtils.cs | 4 +-- ModUtils/GeneralUtils.cs | 47 +++++++++++++-------------- ModUtils/HookUtils.cs | 2 +- ModUtils/ModMenuUtils.cs | 6 ++-- ModUtils/ObjectUtils.cs | 8 ++--- ModUtils/RoomUtils.cs | 38 +++++++++++----------- ModUtils/TableUtils/Backers.cs | 2 +- ModUtils/TableUtils/ContractsStats.cs | 4 +-- ModUtils/TableUtils/Drops.cs | 4 +-- ModUtils/TableUtils/DungeonsSpawn.cs | 4 +-- ModUtils/TableUtils/MobsStats.cs | 2 +- ModUtils/TableUtils/PotionsStats.cs | 2 +- ModUtils/TableUtils/RecipesCook.cs | 4 +-- ModUtils/TableUtils/RecipesCraft.cs | 4 +-- ModUtils/TableUtils/SkillsStats.cs | 4 +-- ModUtils/TableUtils/SurfaceSpawn.cs | 2 +- ModUtils/TableUtils/TableArmor.cs | 4 +-- ModUtils/TableUtils/TableWeapons.cs | 2 +- ModUtils/TextureUtils.cs | 10 +++--- ModUtils/VariableUtils.cs | 4 +-- ModUtils/WeaponUtils.cs | 4 +-- TextureLoader.cs | 2 +- 28 files changed, 120 insertions(+), 118 deletions(-) diff --git a/DataLoader.cs b/DataLoader.cs index 5abc94e..b97cc43 100644 --- a/DataLoader.cs +++ b/DataLoader.cs @@ -96,7 +96,7 @@ public static async Task LoadFile(string filename) )); } - Log.Information(string.Format("Successfully load: {0}.", filename)); + Log.Information("Successfully load: {0}.", filename); ModLoader.Initalize(); // cleaning loot table diff --git a/FileReader.cs b/FileReader.cs index 67bd534..fe61f23 100644 --- a/FileReader.cs +++ b/FileReader.cs @@ -84,7 +84,7 @@ public string GetCode(string fileName) byte[] data = GetFile(fileName); if (data.Length == 0) { - Log.Warning($"{fileName} is empty."); + Log.Warning("{0} is empty.", fileName); return ""; } // if a BOM is found aka: 0xEF 0xBB 0xBF at the beginning of the file, remove it since UTMT will not understand these characters. @@ -165,7 +165,7 @@ public static class FileReader byte[] versionbytes = Read(fs, size); file.Version = reg.Replace(Encoding.UTF8.GetString(versionbytes), "$1"); - Log.Information(string.Format("Reading {{{0}}} built with version {{{1}}}", nameMod, file.Version)); + Log.Information("Reading {{{0}}} built with version {{{1}}}", nameMod, file.Version); // read textures int count = BitConverter.ToInt32(Read(fs, 4), 0); @@ -250,7 +250,7 @@ public static class FileReader } catch { - Log.Information(string.Format("Cannot find the icon.png associated to {0}", fs.Name.Split("\\")[^1])); + Log.Information("Cannot find the icon.png associated to {0}", fs.Name.Split("\\")[^1]); } fs.Close(); @@ -263,7 +263,7 @@ public static byte[] Read(FileStream fs, int length) if(fs.Length - fs.Position < length) { fs.Close(); - throw new Exception(string.Format("In FileReader.Read cannot read {0} bytes in the mod {1} ", length, fs.Name.Split("\\")[^1])); + throw new Exception($"In FileReader.Read cannot read {length} bytes in the mod {fs.Name.Split("\\")[^1]}"); } fs.Read(bytes, 0, length); return bytes; diff --git a/Main.xaml.cs b/Main.xaml.cs index ab9470a..8fe12e5 100644 --- a/Main.xaml.cs +++ b/Main.xaml.cs @@ -241,7 +241,7 @@ public static void LoadSettings() if (modFile != null) listModFile[indexMod].isEnabled = true; else - Log.Warning($"Mod {i} not found"); + Log.Warning("Mod {0} not found", i); } } } diff --git a/ModLoader.cs b/ModLoader.cs index 519d4cc..78b181b 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -60,7 +60,7 @@ public static void AddMenu(string name, params UIComponent[] components) string matchedText = Regex.Match(text, "return (\\[.*\\])").Groups[1].Value; List? tableAsList = JsonConvert.DeserializeObject>(matchedText); - Log.Information(string.Format("Get table: {0}", name.ToString())); + Log.Information("Get table: {0}", name.ToString()); return tableAsList; } catch(Exception ex) @@ -80,7 +80,7 @@ public static void SetTable(List table, string name) text = Regex.Replace(text, "\\[.*\\]", ret); target.ReplaceGML(text, Data); - Log.Information(string.Format("Successfully set table: {0}", name.ToString())); + Log.Information("Successfully set table: {0}", name); } catch(Exception ex) { @@ -131,7 +131,7 @@ public static void LoadFiles() } catch(Exception ex) { - Log.Information(ex, string.Format("Cannot read the mod {0}", file)); + Log.Information(ex, "Cannot read the mod {0}", file); } if (f == null) continue; try diff --git a/ModUtils/AsmUtils.cs b/ModUtils/AsmUtils.cs index ca0276c..29140a9 100644 --- a/ModUtils/AsmUtils.cs +++ b/ModUtils/AsmUtils.cs @@ -39,7 +39,10 @@ public static void CheckInstructionsVariables(UndertaleCode originalCode, string } else { - Log.Warning($"Cannot infer the instance type of {instruction}. There is a risk it will lead to an undefined variable."); + Log.Warning( + "Cannot infer the instance type of {0}. There is a risk it will lead to an undefined variable.", + instruction + ); } } } @@ -74,13 +77,13 @@ public static void InsertAssemblyString(string codeAsString, string fileName, in { try { - Log.Information(string.Format("Trying insert assembly in: {0}", fileName.ToString())); + Log.Information("Trying insert assembly in: {0}", fileName); List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); originalCode.Insert(position, codeAsString); SetAssemblyString(string.Join("\n", originalCode), fileName); - Log.Information(string.Format("Patched function with InsertAssemblyString: {0}", fileName.ToString())); + Log.Information("Patched function with InsertAssemblyString: {0}", fileName); } catch(Exception ex) { @@ -92,13 +95,13 @@ public static void ReplaceAssemblyString(string codeAsString, string fileName, i { try { - Log.Information(string.Format("Trying replace assembly in: {0}", fileName.ToString())); + Log.Information("Trying replace assembly in: {0}", fileName); List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); originalCode[position] = codeAsString; SetAssemblyString(string.Join("\n", originalCode), fileName); - Log.Information(string.Format("Patched function with ReplaceAssemblyString: {0}", fileName.ToString())); + Log.Information("Patched function with ReplaceAssemblyString: {0}", fileName); } catch(Exception ex) { @@ -110,7 +113,7 @@ public static void ReplaceAssemblyString(string codeAsString, string fileName, i { try { - Log.Information(string.Format("Trying replace assembly in: {0}", fileName.ToString())); + Log.Information("Trying replace assembly in: {0}", fileName); List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); originalCode[start] = codeAsString; @@ -120,7 +123,7 @@ public static void ReplaceAssemblyString(string codeAsString, string fileName, i SetAssemblyString(string.Join("\n", originalCode), fileName); - Log.Information(string.Format("Patched function with ReplaceAssemblyString: {0}", fileName.ToString())); + Log.Information("Patched function with ReplaceAssemblyString: {0}", fileName); } catch(Exception ex) { @@ -132,12 +135,12 @@ public static void InjectAssemblyInstruction(string name, Func CreateRefVariabl NameStringID = id }; ModLoader.Data.Variables.Add(variable); - Log.Information($"Created {variable.InstanceType} variable: {variable.Name.Content} {variable.VarID}"); + Log.Information("Created {0} variable: {1} {2}", variable.InstanceType, variable.Name.Content, variable.VarID); return new UndertaleInstruction.Reference(variable, UndertaleInstruction.VariableType.Normal); } @@ -218,7 +221,7 @@ public static void CheckRefLocalVariableOrCreate(UndertaleCode code, string name } else { - Log.Information($"Found local variable: {localvar.Name.Content}"); + Log.Information("Found local variable: {0}", localvar.Name.Content); } } public static void CheckRefVariableOrCreate(string name, UndertaleInstruction.InstanceType instanceType) @@ -241,7 +244,7 @@ public static void CheckRefVariableOrCreate(string name, UndertaleInstruction.In } else { - Log.Information($"Found variable: {variable.Name.Content} of type {variable.InstanceType}"); + Log.Information("Found variable: {0} of type {1}", variable.Name.Content, variable.InstanceType); } } catch @@ -261,7 +264,7 @@ public static UndertaleInstruction.Reference GetRefVariableOr else refVariable = new UndertaleInstruction.Reference(variable, UndertaleInstruction.VariableType.Normal); - Log.Information(string.Format("Found variable: {0}", refVariable.ToString())); + Log.Information("Found variable: {0}", refVariable); return refVariable; } @@ -295,7 +298,7 @@ public static string CreateLocalVarAssemblyAsString(UndertaleCode code) public static UndertaleResourceById CreateString(string name) { UndertaleString str = ModLoader.Data.Strings.MakeString(name, out int ind); - Log.Information(string.Format("Created string: {0}", str.ToString())); + Log.Information("Created string: {0}", str); return new UndertaleResourceById(str, ind); } public static UndertaleResourceById GetStringOrCreate(string name) @@ -309,7 +312,7 @@ public static UndertaleResourceById GetStri else stringById = new UndertaleResourceById(str, ind); - Log.Information(string.Format("Find string: {0}", stringById.ToString())); + Log.Information("Find string: {0}", stringById); return stringById; } diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index e0c1447..a97525e 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -92,7 +92,7 @@ public static UndertaleCode GetUMTCodeFromFile(string fileName) try { UndertaleCode code = ModLoader.Data.Code.First(t => t.Name?.Content == fileName); - Log.Information(string.Format("Found function: {0}", code.ToString())); + Log.Information("Found function: {0}", code); return code; } @@ -177,7 +177,7 @@ internal static string GetCodeRes(string name) var data = CodeResources.ResourceManager.GetObject(name, CodeResources.Culture) as byte[]; if (data == null) { - Log.Information($"Code resource not found :{name}"); + Log.Information("Code resource not found :{0}", name); return ""; } return Encoding.UTF8.GetString(data); @@ -198,13 +198,13 @@ public static UndertaleCode AddFunction(string codeAsString, string name) { try { - Log.Information(string.Format("Trying to add the function : {0}", name.ToString())); + Log.Information("Trying to add the function : {0}", name); UndertaleCode scriptCode = AddCode(codeAsString, name); ModLoader.Data.Code.Add(ModLoader.Data.Code[0]); ModLoader.Data.Code.RemoveAt(0); - Log.Information(string.Format("Successfully added the function : {0}", name.ToString())); + Log.Information("Successfully added the function : {0}", name); return scriptCode; } catch @@ -270,13 +270,13 @@ public static void InsertGMLString(string codeAsString, string fileName, int pos { try { - Log.Information(string.Format("Trying insert code in: {0}", fileName.ToString())); + Log.Information("Trying insert code in: {0}", fileName); List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); originalCode.Insert(position, codeAsString); SetStringGMLInFile(string.Join("\n", originalCode), fileName); - Log.Information(string.Format("Patched function with InsertGMLString: {0}", fileName.ToString())); + Log.Information("Patched function with InsertGMLString: {0}", fileName); } catch (Exception ex) { @@ -302,13 +302,13 @@ public static void ReplaceGMLString(string codeAsString, string fileName, int po { try { - Log.Information(string.Format("Trying replace code in: {0}", fileName.ToString())); + Log.Information("Trying replace code in: {0}", fileName); List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); originalCode[position] = codeAsString; SetStringGMLInFile(string.Join("\n", originalCode), fileName); - Log.Information(string.Format("Patched function with ReplaceGMLString: {0}", fileName.ToString())); + Log.Information("Patched function with ReplaceGMLString: {0}", fileName); } catch (Exception ex) { @@ -336,7 +336,7 @@ public static void ReplaceGMLString(string codeAsString, string fileName, int st { try { - Log.Information(string.Format("Trying replace code in: {0}", fileName.ToString())); + Log.Information("Trying replace code in: {0}", fileName); List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); originalCode[start] = codeAsString; @@ -347,7 +347,7 @@ public static void ReplaceGMLString(string codeAsString, string fileName, int st SetStringGMLInFile(string.Join("\n", originalCode), fileName); - Log.Information(string.Format("Patched function with ReplaceGMLString: {0}", fileName.ToString())); + Log.Information("Patched function with ReplaceGMLString: {0}", fileName); } catch (Exception ex) { @@ -999,7 +999,7 @@ public static ModSummary Save(this FileEnumerable fe) default: break; } - Log.Information("Successfully patched function {{{0}}} with {{{1}}}", fe.header.fileName, fe.header.patchingWay.ToString()); + Log.Information("Successfully patched function {{{0}}} with {{{1}}}", fe.header.fileName, fe.header.patchingWay); return new( fe.header.fileName, newCode, @@ -1009,7 +1009,7 @@ public static ModSummary Save(this FileEnumerable fe) catch (Exception ex) { ex.Data.Add("fileName", fe.header.fileName); - ex.Data.Add("patchingWay", fe.header.patchingWay.ToString()); + ex.Data.Add("patchingWay", fe.header.patchingWay); throw; } } diff --git a/ModUtils/EventUtils.cs b/ModUtils/EventUtils.cs index cf6b8bd..921b42d 100644 --- a/ModUtils/EventUtils.cs +++ b/ModUtils/EventUtils.cs @@ -167,7 +167,7 @@ public static void AddNewEvent(string objectName, string eventCode, EventType ev }); gameObject.Events[(int)eventType].Add(newEvent); - Log.Information(string.Format("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, objectName)); + Log.Information("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, objectName); } catch(Exception ex) { @@ -233,7 +233,7 @@ public static void AddNewEvent(UndertaleGameObject gameObject, string eventCode, }); gameObject.Events[(int)eventType].Add(newEvent); - Log.Information(string.Format("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, gameObject.Name.Content)); + Log.Information("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, gameObject.Name.Content); } catch(Exception ex) { diff --git a/ModUtils/GeneralUtils.cs b/ModUtils/GeneralUtils.cs index 7a11ee9..cffb0bd 100644 --- a/ModUtils/GeneralUtils.cs +++ b/ModUtils/GeneralUtils.cs @@ -106,10 +106,10 @@ public static FileEnumerable LoadAssemblyAsString(string fileName) public static void LogInstruction(UndertaleInstruction instruction) { try { - Log.Information(string.Format(@"{{{0}}}: - ( - .Address = {10}, - .JumpOffset = {11}, + Log.Information(@"{{{0}}}: + ( + .Address = {10}, + .JumpOffset = {11}, .Kind = {1}, .ComparisonKind = {8}, .Type1 = {2}, @@ -121,12 +121,12 @@ public static void LogInstruction(UndertaleInstruction instruction) .ArgumentsCount = {9}, ) ", - instruction.ToString(), - instruction.Kind.ToString(), - instruction.Type1.ToString(), - instruction.Type2.ToString(), - instruction.TypeInst.ToString(), - (instruction.Destination != null) ? + instruction, + instruction.Kind, + instruction.Type1, + instruction.Type2, + instruction.TypeInst, + (instruction.Destination != null) ? string.Format(@"( .Type = {0}, .Target = ( .Name = {1}, .InstanceType = {2}, ), @@ -135,7 +135,7 @@ public static void LogInstruction(UndertaleInstruction instruction) instruction.Destination?.Target.Name.ToString(), instruction.Destination?.Target.InstanceType.ToString()) : "", - (instruction.Value is UndertaleInstruction.Reference) ? + (instruction.Value is UndertaleInstruction.Reference) ? string.Format(@"( .Type = {0}, .Target = ( .Name = {1}, .InstanceType = {2}, ), @@ -144,8 +144,7 @@ public static void LogInstruction(UndertaleInstruction instruction) (instruction.Value as UndertaleInstruction.Reference)?.Target.Name.ToString(), (instruction.Value as UndertaleInstruction.Reference)?.Target.InstanceType.ToString()) : instruction.Value?.ToString() ?? "", - - (instruction.Function != null) ? + (instruction.Function != null) ? string.Format(@"( .Type = {0}, .Target = ( .Name = {1}, .Classification = {2}, ), @@ -154,14 +153,14 @@ public static void LogInstruction(UndertaleInstruction instruction) instruction.Function?.Target.Name.ToString(), instruction.Function?.Target.Classification.ToString()) : "", - instruction.ComparisonKind.ToString(), - instruction.ArgumentsCount.ToString(), - instruction.Address.ToString(), - instruction.JumpOffset.ToString() - )); + instruction.ComparisonKind, + instruction.ArgumentsCount, + instruction.Address, + instruction.JumpOffset + ); } catch(Exception ex) { - Log.Error(ex, string.Format("Cannot log {0}", instruction.ToString())); + Log.Error(ex, "Cannot log {0}", instruction); throw; } @@ -175,7 +174,7 @@ public static T ThrowIfNull( { if (argument is null) { - Log.Error(string.Format("{0} is null.", argument)); + Log.Error("{0} is null.", argument); throw new ArgumentNullException(paramName, message); } else @@ -191,7 +190,7 @@ public static T ThrowIfNull( { if (argument is null) { - Log.Error(string.Format("{0} is null.", argument)); + Log.Error("{0} is null.", argument); throw new ArgumentNullException(paramName, message); } else @@ -215,20 +214,20 @@ public static void GenerateNRandomLinesFromCode(IList code, Globa { try { - Log.Information(invalid.ToString()); + Log.Information("{0}", invalid); // we encounter an error since we can't decompile a nested function // the error message indicates where to look instead // but you need to parse the message to retrieve the needed code // "This code block represents a function nested inside " + code.ParentEntry.Name + " - decompile that instead" string name = invalid.Message.Split('\"')[1]; - Log.Information(string.Format("Looking for {{{0}}} instead", name)); + Log.Information("Looking for {{{0}}} instead", name); s.AddRange(Decompiler.Decompile(code.First(x => x.Name.Content == name), context).Split('\n').SelectionSamplingTechnique(numberLinesByCode)); } // not all code can be decompiled sadly catch { string name = invalid.Message.Split('\"')[1]; - Log.Information(string.Format("Cannot decompile {{{0}}}, skipping that file", name)); + Log.Information("Cannot decompile {{{0}}}, skipping that file", name); continue; } diff --git a/ModUtils/HookUtils.cs b/ModUtils/HookUtils.cs index 90b14c7..f1ddc79 100644 --- a/ModUtils/HookUtils.cs +++ b/ModUtils/HookUtils.cs @@ -20,7 +20,7 @@ public static void HookFunction(string functionName, string hookName, params str { try { - Log.Information(string.Format("Trying add hook in: {0}", functionName)); + Log.Information("Trying add hook in: {0}", functionName); List? originalCode = GetStringGMLFromFile(functionName).Split("\n").ToList(); originalCode.Append($"var {hookName} = createHookObj({paramNames.Length}, {string.Join(", ", paramNames)})"); diff --git a/ModUtils/ModMenuUtils.cs b/ModUtils/ModMenuUtils.cs index ae5f6ab..146b2fb 100644 --- a/ModUtils/ModMenuUtils.cs +++ b/ModUtils/ModMenuUtils.cs @@ -34,7 +34,7 @@ public UIComponent(string name, string associatedGlobal, UIComponentType compome { case UIComponentType.ComboBox: case UIComponentType.Slider: - Log.Error($"Incorrect use of UIComponent, you cannot define a {compomentType} using these parameters."); + Log.Error("Incorrect use of UIComponent, you cannot define a {0} using these parameters.", compomentType); throw new ValueUnavailableException(); default: @@ -52,7 +52,7 @@ public UIComponent(string name, string associatedGlobal, UIComponentType compome { case UIComponentType.CheckBox: case UIComponentType.Slider: - Log.Error($"Incorrect use of UIComponent, you cannot define a {compomentType} using these parameters."); + Log.Error("Incorrect use of UIComponent, you cannot define a {0} using these parameters.", compomentType); throw new ValueUnavailableException(); default: @@ -71,7 +71,7 @@ public UIComponent(string name, string associatedGlobal, UIComponentType compome { case UIComponentType.CheckBox: case UIComponentType.ComboBox: - Log.Error($"Incorrect use of UIComponent, you cannot define a {compomentType} using these parameters."); + Log.Error("Incorrect use of UIComponent, you cannot define a {0} using these parameters.", compomentType); throw new ValueUnavailableException(); default: diff --git a/ModUtils/ObjectUtils.cs b/ModUtils/ObjectUtils.cs index 57197ea..912245f 100644 --- a/ModUtils/ObjectUtils.cs +++ b/ModUtils/ObjectUtils.cs @@ -101,7 +101,7 @@ public static UndertaleGameObject AddObject( UndertaleGameObject? existingObj = ModLoader.Data.GameObjects.FirstOrDefault(t => t.Name.Content == name); if(existingObj != null) { - Log.Information(string.Format("Cannot create the GameObject since it already exists: {0}", name.ToString())); + Log.Information("Cannot create the GameObject since it already exists: {0}", name); return existingObj; } @@ -123,7 +123,7 @@ public static UndertaleGameObject AddObject( Awake = isAwake, }; ModLoader.Data.GameObjects.Add(obj); - Log.Information(string.Format("Successfully created gameObject: {0}", name.ToString())); + Log.Information("Successfully created gameObject: {0}", name); return obj; } catch @@ -141,7 +141,7 @@ public static UndertaleGameObject GetObject(string name) try { UndertaleGameObject gameObject = ModLoader.Data.GameObjects.First(t => t.Name.Content == name); - Log.Information(string.Format("Found gameObject: {0}", name.ToString())); + Log.Information("Found gameObject: {0}", name); return gameObject; } catch @@ -161,7 +161,7 @@ public static void SetObject(string name, UndertaleGameObject o) { (int indexObj, _) = ModLoader.Data.GameObjects.Enumerate().First(t => t.Item2.Name.Content == name); ModLoader.Data.GameObjects[indexObj] = o; - Log.Information(string.Format("Successfully replaced gameObject: {0}", name.ToString())); + Log.Information("Successfully replaced gameObject: {0}", name); } catch(Exception ex) { diff --git a/ModUtils/RoomUtils.cs b/ModUtils/RoomUtils.cs index 148b4e7..3072984 100644 --- a/ModUtils/RoomUtils.cs +++ b/ModUtils/RoomUtils.cs @@ -25,7 +25,7 @@ public static void AddRoomJson(string jsonString) { UndertaleRoom newRoom = new UndertaleRoom(); - Log.Information($"A room is being added or edited"); + Log.Information("A room is being added or edited"); byte[] jsonUtf8Bytes = Encoding.UTF8.GetBytes(jsonString); JsonReaderOptions options = new JsonReaderOptions @@ -52,7 +52,7 @@ public static void AddRoomJson(string jsonString) if (ModLoader.Data.Rooms.ByName(newRoom.Name.Content) == null) ModLoader.Data.Rooms.Add(newRoom); - Log.Information($"Successfully created room {newRoom.Name}."); + Log.Information("Successfully created room {0}.", newRoom.Name); } #region AddRoomJson @@ -742,12 +742,12 @@ public static UndertaleRoom GetRoom(string name) try { UndertaleRoom room = ModLoader.Data.Rooms.First(t => t.Name.Content == name); - Log.Information($"Found room {name}"); + Log.Information("Found room {0}", name); return room; } catch { - Log.Error($"Cannot find room {name}."); + Log.Error("Cannot find room {0}.", name); throw; } } @@ -762,12 +762,12 @@ public static UndertaleRoom AddRoom(string name) Flags = UndertaleRoom.RoomEntryFlags.IsGMS2 ^ UndertaleRoom.RoomEntryFlags.EnableViews, }; ModLoader.Data.Rooms.Add(room); - Log.Information($"Successfully created room {name}."); + Log.Information("Successfully created room {0}.", name); return room; } catch { - Log.Error($"Cannot add Room {name} since it already exists."); + Log.Error("Cannot add Room {0} since it already exists.", name); throw; } } @@ -858,7 +858,7 @@ public static UndertaleRoom AddRoom(string name, uint width, uint height) } newLayer.ParentRoom = room; - Log.Information($"Successfully created layer {name} of type {type} in room {room.Name}."); + Log.Information("Successfully created layer {0} of type {1} in room {2}.", name, type, room.Name); return newLayer; } public static UndertaleRoom.Layer AddLayer(this UndertaleRoom room, UndertaleRoom.LayerType type, string name) where T : UndertaleRoom.Layer.LayerData, new() @@ -878,12 +878,12 @@ public static UndertaleRoom.Layer GetLayer(this UndertaleRoom room, UndertaleRoo try { UndertaleRoom.Layer layer = room.Layers.First(t => t.LayerName.Content == name && t.LayerType == type); - Log.Information($"Found layer {name} of type {type} in room {room.Name}."); + Log.Information("Found layer {0} of type {1} in room {2}.", name, type, room.Name); return layer; } catch { - Log.Error($"Cannot find layer {name} of type {type} in room {room.Name}."); + Log.Error("Cannot find layer {0} of type {1} in room {2}.", name, type, room.Name); throw; } } @@ -904,12 +904,12 @@ public static UndertaleRoom.GameObject AddGameObject(this UndertaleRoom room, st room.GameObjects.Add(gameObject); room.GetLayer(UndertaleRoom.LayerType.Instances, layerName).InstancesData.Instances.Add(gameObject); - Log.Information($"Successfully created gameobject {obName} in layer {layerName} in room {room.Name}"); + Log.Information("Successfully created gameobject {0} in layer {1} in room {2}", obName, layerName, room.Name); return gameObject; } catch { - Log.Error($"Cannot add the gameobject {obName} in layer {layerName} in room {room.Name}."); + Log.Error("Cannot add the gameobject {0} in layer {1} in room {2}.", obName, layerName, room.Name); throw; } } @@ -930,12 +930,12 @@ public static UndertaleRoom.GameObject AddGameObject(this UndertaleRoom room, Un room.GameObjects.Add(gameObject); layer.InstancesData.Instances.Add(gameObject); - Log.Information($"Successfully created gameobject {obName} in layer {layer.LayerName} in room {room.Name}"); + Log.Information("Successfully created gameobject {0} in layer {1} in room {2}", obName, layer.LayerName, room.Name); return gameObject; } catch { - Log.Error($"Cannot add the gameobject {obName} in layer {layer.LayerName} in room {room.Name}."); + Log.Error("Cannot add the gameobject {0} in layer {1} in room {2}.", obName, layer.LayerName, room.Name); throw; } } @@ -955,12 +955,12 @@ public static UndertaleRoom.GameObject AddGameObject(this UndertaleRoom room, st room.GameObjects.Add(gameObject); room.GetLayer(UndertaleRoom.LayerType.Instances, layerName).InstancesData.Instances.Add(gameObject); - Log.Information($"Successfully created gameobject {ob.Name} in layer {layerName} in room {room.Name}"); + Log.Information("Successfully created gameobject {0} in layer {1} in room {2}", ob.Name, layerName, room.Name); return gameObject; } catch { - Log.Error($"Cannot add the gameobject {ob.Name} in layer {layerName} in room {room.Name}."); + Log.Error("Cannot add the gameobject {0} in layer {1} in room {2}.", ob.Name, layerName, room.Name); throw; } } @@ -980,12 +980,12 @@ public static UndertaleRoom.GameObject AddGameObject(this UndertaleRoom room, Un room.GameObjects.Add(gameObject); layer.InstancesData.Instances.Add(gameObject); - Log.Information($"Successfully created gameobject {ob.Name} in layer {layer.LayerName} in room {room.Name}"); + Log.Information("Successfully created gameobject {0} in layer {1} in room {2}", ob.Name, layer.LayerName, room.Name); return gameObject; } catch { - Log.Error($"Cannot add the gameobject {ob.Name} in layer {layer.LayerName} in room {room.Name}."); + Log.Error("Cannot add the gameobject {0} in layer {1} in room {2}.", ob.Name, layer.LayerName, room.Name); throw; } } @@ -994,12 +994,12 @@ public static UndertaleRoom.GameObject GetGameObject(this UndertaleRoom room, st try { UndertaleRoom.GameObject go = room.GetLayer(UndertaleRoom.LayerType.Instances, layerName).InstancesData.Instances.First(t => t.ObjectDefinition.Name.Content == obName); - Log.Information($"Found GameObject {obName} in layer {layerName} in room {room.Name}"); + Log.Information("Found GameObject {0} in layer {1} in room {2}", obName, layerName, room.Name); return go; } catch { - Log.Error($"Cannot find instance of gameobject {obName} in layer {layerName} in room {room.Name}."); + Log.Error("Cannot find instance of gameobject {0} in layer {1} in room {2}.", obName, layerName, room.Name); throw; } } diff --git a/ModUtils/TableUtils/Backers.cs b/ModUtils/TableUtils/Backers.cs index 1c90c36..8ad027c 100644 --- a/ModUtils/TableUtils/Backers.cs +++ b/ModUtils/TableUtils/Backers.cs @@ -19,6 +19,6 @@ public static void InjectTableBackers(string? name = null, string? nickname = nu // Add line to table table.Add(newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected {name}:{nickname} into {tableName} table."); + Log.Information("Injected {0}:{1} into {2} table.", name, nickname, tableName); } } \ No newline at end of file diff --git a/ModUtils/TableUtils/ContractsStats.cs b/ModUtils/TableUtils/ContractsStats.cs index ff378e8..18a9fa7 100644 --- a/ModUtils/TableUtils/ContractsStats.cs +++ b/ModUtils/TableUtils/ContractsStats.cs @@ -66,11 +66,11 @@ float k { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected contract {id} into {tableName}"); + Log.Information("Injected contract {0} into {1}", id, tableName); } else { - Log.Error($"Hook not found in {tableName}. {id} was not injected."); + Log.Error("Hook not found in {0}. {1} was not injected.", tableName, id); throw new Exception($"Hook not found in {tableName}. {id} was not injected."); } } diff --git a/ModUtils/TableUtils/Drops.cs b/ModUtils/TableUtils/Drops.cs index 0506d62..b97bef0 100644 --- a/ModUtils/TableUtils/Drops.cs +++ b/ModUtils/TableUtils/Drops.cs @@ -137,11 +137,11 @@ public static void InjectTableDrops( { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Drop {id} into table {tableName} under {hook}"); + Log.Information("Injected Drop {0} into table {1} under {2}", id, tableName, hook); } else { - Log.Error($"Cannot find hook {hook} in table {tableName}"); + Log.Error("Cannot find hook {0} in table {1}", hook, tableName); throw new Exception($"Cannot find hook {hook} in table {tableName}"); } } diff --git a/ModUtils/TableUtils/DungeonsSpawn.cs b/ModUtils/TableUtils/DungeonsSpawn.cs index ee1715c..1cad658 100644 --- a/ModUtils/TableUtils/DungeonsSpawn.cs +++ b/ModUtils/TableUtils/DungeonsSpawn.cs @@ -83,11 +83,11 @@ public static void InjectTableDungeonsSpawn( { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Dungeon Spawn {id} into {tableName} under {hook}"); + Log.Information("Injected Dungeon Spawn {0} into {1} under {2}", id, tableName, hook); } else { - Log.Error($"Cannot find Hook {hook} in table {tableName}"); + Log.Error("Cannot find Hook {0} in table {1}", hook, tableName); throw new Exception($"Hook {hook} not found in table {tableName}"); } } diff --git a/ModUtils/TableUtils/MobsStats.cs b/ModUtils/TableUtils/MobsStats.cs index 725a6be..2566900 100644 --- a/ModUtils/TableUtils/MobsStats.cs +++ b/ModUtils/TableUtils/MobsStats.cs @@ -251,6 +251,6 @@ public static void InjectTableMobsStats( // Add line to table table.Add(newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Mob Stat {name} into table"); + Log.Information("Injected Mob Stat {0} into table", name); } } \ No newline at end of file diff --git a/ModUtils/TableUtils/PotionsStats.cs b/ModUtils/TableUtils/PotionsStats.cs index eb10733..9230e9d 100644 --- a/ModUtils/TableUtils/PotionsStats.cs +++ b/ModUtils/TableUtils/PotionsStats.cs @@ -33,6 +33,6 @@ public static void InjectTablePotionsStats(string name, string effectScript, par // Add line to end of table table.Add(newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected {name} into {tableName} table."); + Log.Information("Injected {0} into {1} table.", name, tableName); } } \ No newline at end of file diff --git a/ModUtils/TableUtils/RecipesCook.cs b/ModUtils/TableUtils/RecipesCook.cs index 50761b6..b36ae52 100644 --- a/ModUtils/TableUtils/RecipesCook.cs +++ b/ModUtils/TableUtils/RecipesCook.cs @@ -86,11 +86,11 @@ public static void InjectTableRecipesCook( { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Armor {NAME} into table {tableName} under {hook}"); + Log.Information("Injected Armor {0} into table {1} under {2}", NAME, tableName, hook); } else { - Log.Error($"Cannot find hook {hook} in table {tableName}"); + Log.Error("Cannot find hook {0} in table {1}", hook, tableName); throw new Exception($"Cannot find hook {hook} in table {tableName}"); } } diff --git a/ModUtils/TableUtils/RecipesCraft.cs b/ModUtils/TableUtils/RecipesCraft.cs index 6b6c48c..dd5964a 100644 --- a/ModUtils/TableUtils/RecipesCraft.cs +++ b/ModUtils/TableUtils/RecipesCraft.cs @@ -66,11 +66,11 @@ public static void InjectTableRecipesCraft( { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected craft recipe {NAME} into {tableName} under {hook}"); + Log.Information("Injected craft recipe {0} into {1} under {2}", NAME, tableName, hook); } else { - Log.Error($"Cannot find hook {hook} in table {tableName}"); + Log.Error("Cannot find hook {0} in table {1}", hook, tableName); throw new Exception($"Hook {hook} not found in table {tableName}"); } } diff --git a/ModUtils/TableUtils/SkillsStats.cs b/ModUtils/TableUtils/SkillsStats.cs index c64e83f..93ca3f4 100644 --- a/ModUtils/TableUtils/SkillsStats.cs +++ b/ModUtils/TableUtils/SkillsStats.cs @@ -177,11 +177,11 @@ public static void InjectTableSkillsStats( { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Skill Stat {id} into {tableName} under {hook}"); + Log.Information("Injected Skill Stat {0} into {1} under {2}", id, tableName, hook); } else { - Log.Error($"Cannot find Hook {hook} in table {tableName}"); + Log.Error("Cannot find Hook {0} in table {1}", hook, tableName); throw new Exception($"Hook {hook} not found in table {tableName}"); } } diff --git a/ModUtils/TableUtils/SurfaceSpawn.cs b/ModUtils/TableUtils/SurfaceSpawn.cs index 02b4904..edf6a86 100644 --- a/ModUtils/TableUtils/SurfaceSpawn.cs +++ b/ModUtils/TableUtils/SurfaceSpawn.cs @@ -89,6 +89,6 @@ public static void InjectTableSurfaceSpawn( // Add line to table table.Add(newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected a Spawn into table {tableName}"); + Log.Information("Injected a Spawn into table {0}", tableName); } } \ No newline at end of file diff --git a/ModUtils/TableUtils/TableArmor.cs b/ModUtils/TableUtils/TableArmor.cs index c36ab27..80ff875 100644 --- a/ModUtils/TableUtils/TableArmor.cs +++ b/ModUtils/TableUtils/TableArmor.cs @@ -208,11 +208,11 @@ public static void InjectTableArmor( { table.Insert(ind + 1, newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Armor {id} into table {tableName} under {hook}"); + Log.Information("Injected Armor {0} into table {1} under {2}", id, tableName, hook); } else { - Log.Error($"Cannot find hook {hook} in table {tableName}"); + Log.Error("Cannot find hook {0} in table {1}", hook, tableName); throw new Exception($"Cannot find hook {hook} in table {tableName}"); } } diff --git a/ModUtils/TableUtils/TableWeapons.cs b/ModUtils/TableUtils/TableWeapons.cs index 17eeba7..7c6432a 100644 --- a/ModUtils/TableUtils/TableWeapons.cs +++ b/ModUtils/TableUtils/TableWeapons.cs @@ -192,6 +192,6 @@ public static void InjectTableWeapons( // Add line to table table.Add(newline); ModLoader.SetTable(table, tableName); - Log.Information($"Injected Weapon {id} into table {tableName}"); + Log.Information("Injected Weapon {0} into table {1}", id, tableName); } } \ No newline at end of file diff --git a/ModUtils/TextureUtils.cs b/ModUtils/TextureUtils.cs index 589045a..c7d0b47 100644 --- a/ModUtils/TextureUtils.cs +++ b/ModUtils/TextureUtils.cs @@ -104,7 +104,7 @@ public static UndertaleSprite GetSprite(string name) try { UndertaleSprite sprite = ModLoader.Data.Sprites.First(t => t.Name.Content == name); - Log.Information(string.Format("Found sprite: {0}", name.ToString())); + Log.Information("Found sprite: {0}", name); return sprite; } catch(Exception ex) @@ -118,7 +118,7 @@ public static UndertaleEmbeddedTexture GetEmbeddedTexture(string name) try { UndertaleEmbeddedTexture embeddedTexture = ModLoader.Data.EmbeddedTextures.First(t => t.Name.Content == name); - Log.Information(string.Format("Found embedded texture: {0}", name.ToString())); + Log.Information("Found embedded texture: {0}", name); return embeddedTexture; } catch(Exception ex) @@ -132,7 +132,7 @@ public static UndertaleTexturePageItem GetTexturePageItem(string name) try { UndertaleTexturePageItem texturePageItem = ModLoader.Data.TexturePageItems.First(t => t.Name.Content == name); - Log.Information(string.Format("Found texture page item: {0}", name.ToString())); + Log.Information("Found texture page item: {0}", name); return texturePageItem; } catch(Exception ex) @@ -154,7 +154,7 @@ public static string AddNewTexturePageItem(string embeddedTextureName, RectTextu bounding ); ModLoader.Data.TexturePageItems.Add(texturePageItem); - Log.Information(string.Format("Successfully added a new texture from: {0}", embeddedTextureName.ToString())); + Log.Information("Successfully added a new texture from: {0}", embeddedTextureName); return texturePageItem.Name.Content; } @@ -186,7 +186,7 @@ public static string AddNewSprite(string spriteName, List texturePageIte ModLoader.Data.Sprites.Add(newSprite); - Log.Information(string.Format("Successfully added new sprite: {0}", newSprite.Name.Content)); + Log.Information("Successfully added new sprite: {0}", newSprite.Name.Content); return newSprite.Name.Content; } diff --git a/ModUtils/VariableUtils.cs b/ModUtils/VariableUtils.cs index 85df9d1..2279c18 100644 --- a/ModUtils/VariableUtils.cs +++ b/ModUtils/VariableUtils.cs @@ -12,7 +12,7 @@ public static UndertaleVariable GetVariable(string name) try { UndertaleVariable variable = ModLoader.Data.Variables.First(t => t.Name?.Content == name); - Log.Information(string.Format("Found variable: {0}", variable.ToString())); + Log.Information("Found variable: {0}", variable); return variable; } @@ -26,7 +26,7 @@ public static UndertaleString GetString(string name) try { UndertaleString variable = ModLoader.Data.Strings.First(t => t.Content == name); - Log.Information(string.Format("Found string: {0}", variable.ToString())); + Log.Information("Found string: {0}", variable); return variable; } diff --git a/ModUtils/WeaponUtils.cs b/ModUtils/WeaponUtils.cs index 99a9947..4f2929c 100644 --- a/ModUtils/WeaponUtils.cs +++ b/ModUtils/WeaponUtils.cs @@ -29,7 +29,7 @@ public static Weapon GetWeapon(string id) weaponDescription.Remove(""); weaponDescription.RemoveAt(0); - Log.Information(string.Format("Found weapon: {0}", weaponsName.ToString())); + Log.Information("Found weapon: {0}", weaponsName); return new(weaponsName, weaponDescription, localizationNames); } catch(Exception ex) @@ -61,7 +61,7 @@ public static void SetWeapon(string id, Weapon weapon) ModLoader.WeaponDescriptions[indexDescription] = w2s.Item2; ModLoader.WeaponDescriptions[indexLocalizationName] = w2s.Item3; - Log.Information(string.Format("Successfully set weapon: {0}", targetName.ToString())); + Log.Information("Successfully set weapon: {0}", targetName); } catch(Exception ex) { diff --git a/TextureLoader.cs b/TextureLoader.cs index 2c2f86b..a0763c2 100644 --- a/TextureLoader.cs +++ b/TextureLoader.cs @@ -329,7 +329,7 @@ private static void ScanForTextures(ModFile modFile) Source = fileChunk.name.Split("\\")[^1], Data = byteFile }; - Log.Information(string.Format("Successfully load texture {0}", fileChunk.name)); + Log.Information("Successfully load texture {0}", fileChunk.name); SourceTextures.Add(textureInfo); } else From cc2f89bf7ce7c15f2a4209341b423b29e4691a99 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 23:22:29 +0200 Subject: [PATCH 05/11] [Major] removes useless catch/rethrow --- Controls/SourceBar.xaml.cs | 2 +- FilePacker.cs | 37 ++----- FileReader.cs | 42 +++----- ModLoader.cs | 86 ++++++---------- ModUtils/AsmUtils.cs | 183 +++++++++++----------------------- ModUtils/CodeUtils.cs | 199 ++++++++++++------------------------- ModUtils/EventUtils.cs | 153 ++++++++++------------------ ModUtils/GeneralUtils.cs | 54 ++++------ ModUtils/HookUtils.cs | 18 +--- ModUtils/ObjectUtils.cs | 27 ++--- ModUtils/TextureUtils.cs | 112 +++++++-------------- ModUtils/VariableUtils.cs | 26 ++--- ModUtils/WeaponUtils.cs | 76 ++++++-------- 13 files changed, 330 insertions(+), 685 deletions(-) diff --git a/Controls/SourceBar.xaml.cs b/Controls/SourceBar.xaml.cs index ccbd698..e5d1a1a 100644 --- a/Controls/SourceBar.xaml.cs +++ b/Controls/SourceBar.xaml.cs @@ -38,7 +38,7 @@ private void CompileButton_Click(object sender, RoutedEventArgs e) Log.Error(ex, "Something went wrong"); } - Msl.ThrowIfNull(Main.Instance.Viewer.Content as UserControl).UpdateLayout(); + Msl.ThrowIfNull((UserControl)Main.Instance.Viewer.Content).UpdateLayout(); Main.Instance.Refresh(); } diff --git a/FilePacker.cs b/FilePacker.cs index 260e302..39bc43a 100644 --- a/FilePacker.cs +++ b/FilePacker.cs @@ -13,35 +13,16 @@ public static class UtilsPacker /// /// /// - public static bool Pack(string path) + public static void Pack(string path) { - bool resultPacking = false; - - try - { - resultPacking = FilePacker.Pack( - null, - path, - ModLoader.ModPath, - path, - Main.Instance.mslVersion, - new Type[2] {typeof(ModShardLauncher.Mods.Mod), typeof(UndertaleModLib.Models.UndertaleCode)} - ); - } - catch(Exception ex) - { - if (ex is ArgumentNullException || ex is ArgumentException || ex is IOException || ex is DirectoryNotFoundException) - { - Log.Error(ex.ToString()); - } - else - { - Log.Error(ex, "Unexpected error"); - } - Console.WriteLine(ex.Message); - } - - return resultPacking; + FilePacker.Pack( + null, + path, + ModLoader.ModPath, + path, + Main.Instance.mslVersion, + new Type[2] {typeof(ModShardLauncher.Mods.Mod), typeof(UndertaleModLib.Models.UndertaleCode)} + ); } } } diff --git a/FileReader.cs b/FileReader.cs index fe61f23..2e99cce 100644 --- a/FileReader.cs +++ b/FileReader.cs @@ -79,41 +79,27 @@ public byte[] GetFile(string fileName) } public string GetCode(string fileName) { - try + byte[] data = GetFile(fileName); + if (data.Length == 0) { - byte[] data = GetFile(fileName); - if (data.Length == 0) - { - Log.Warning("{0} is empty.", fileName); - return ""; - } - // if a BOM is found aka: 0xEF 0xBB 0xBF at the beginning of the file, remove it since UTMT will not understand these characters. - // BOM are produced if a script is made through Visual Studio - if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) data = data.Skip(3).ToArray(); - - string text = Encoding.UTF8.GetString(data); - if(text.Length == 0) - { - MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + fileName); - throw new ArgumentException("String cannot be of length zero"); - } - return text; + Log.Warning("{0} is empty.", fileName); + return ""; } - catch + // if a BOM is found aka: 0xEF 0xBB 0xBF at the beginning of the file, remove it since UTMT will not understand these characters. + // BOM are produced if a script is made through Visual Studio + if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) data = data.Skip(3).ToArray(); + + string text = Encoding.UTF8.GetString(data); + if(text.Length == 0) { - throw; + MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + fileName); + throw new ArgumentException("String cannot be of length zero"); } + return text; } public bool FileExist(string fileName) { - try - { - return GetFile(fileName).Length > 0; - } - catch - { - throw; - } + return GetFile(fileName).Length > 0; } } public static class FileReader diff --git a/ModLoader.cs b/ModLoader.cs index 78b181b..490ab69 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -52,41 +52,25 @@ public static void AddMenu(string name, params UIComponent[] components) } public static List? GetTable(string name) { - try - { - UndertaleCode table = Data.Code.First(t => t.Name.Content == name); - GlobalDecompileContext context = new(Data, false); - string text = Decompiler.Decompile(table, context); - string matchedText = Regex.Match(text, "return (\\[.*\\])").Groups[1].Value; - List? tableAsList = JsonConvert.DeserializeObject>(matchedText); + UndertaleCode table = Data.Code.First(t => t.Name.Content == name); + GlobalDecompileContext context = new(Data, false); + string text = Decompiler.Decompile(table, context); + string matchedText = Regex.Match(text, "return (\\[.*\\])").Groups[1].Value; + List? tableAsList = JsonConvert.DeserializeObject>(matchedText); - Log.Information("Get table: {0}", name.ToString()); - return tableAsList; - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Get table: {0}", name.ToString()); + return tableAsList; } public static void SetTable(List table, string name) { - try - { - string ret = JsonConvert.SerializeObject(table).Replace("\n", ""); - UndertaleCode target = Data.Code.First(t => t.Name.Content == name); - GlobalDecompileContext context = new(Data, false); - string text = Decompiler.Decompile(target, context); - text = Regex.Replace(text, "\\[.*\\]", ret); - target.ReplaceGML(text, Data); + string ret = JsonConvert.SerializeObject(table).Replace("\n", ""); + UndertaleCode target = Data.Code.First(t => t.Name.Content == name); + GlobalDecompileContext context = new(Data, false); + string text = Decompiler.Decompile(target, context); + text = Regex.Replace(text, "\\[.*\\]", ret); + target.ReplaceGML(text, Data); - Log.Information("Successfully set table: {0}", name); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Successfully set table: {0}", name); } public static void LoadFiles() { @@ -134,34 +118,28 @@ public static void LoadFiles() Log.Information(ex, "Cannot read the mod {0}", file); } if (f == null) continue; - try - { - Assembly assembly = f.Assembly; - // for array or list, use the available search method instead of Linq one - // use the Linq ones for IEnumerable - Type? modType = Array.Find(assembly.GetTypes(), t => t.IsSubclassOf(typeof(Mod))); - if (modType == null) - { - MessageBox.Show("加载错误: " + assembly.GetName().Name + " 此Mod需要一个Mod类"); - continue; - } - else - { - if (Activator.CreateInstance(modType) is not Mod mod) continue; - mod.LoadAssembly(); - mod.ModFiles = f; - f.instance = mod; + Assembly assembly = f.Assembly; + // for array or list, use the available search method instead of Linq one + // use the Linq ones for IEnumerable + Type? modType = Array.Find(assembly.GetTypes(), t => t.IsSubclassOf(typeof(Mod))); - ModFile? old = mods.Find(t => t.Name == f.Name); - if (old != null) f.isEnabled = old.isEnabled; - - modCaches.Add(f); - } + if (modType == null) + { + MessageBox.Show("加载错误: " + assembly.GetName().Name + " 此Mod需要一个Mod类"); + continue; } - catch + else { - throw; + if (Activator.CreateInstance(modType) is not Mod mod) continue; + mod.LoadAssembly(); + mod.ModFiles = f; + f.instance = mod; + + ModFile? old = mods.Find(t => t.Name == f.Name); + if (old != null) f.isEnabled = old.isEnabled; + + modCaches.Add(f); } } mods.Clear(); diff --git a/ModUtils/AsmUtils.cs b/ModUtils/AsmUtils.cs index 29140a9..8236250 100644 --- a/ModUtils/AsmUtils.cs +++ b/ModUtils/AsmUtils.cs @@ -49,104 +49,55 @@ public static void CheckInstructionsVariables(UndertaleCode originalCode, string } public static string GetAssemblyString(string fileName) { - try - { - UndertaleCode originalCode = GetUMTCodeFromFile(fileName); - return originalCode.Disassemble(ModLoader.Data.Variables, ModLoader.Data.CodeLocals.For(originalCode)); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleCode originalCode = GetUMTCodeFromFile(fileName); + return originalCode.Disassemble(ModLoader.Data.Variables, ModLoader.Data.CodeLocals.For(originalCode)); } public static void SetAssemblyString(string codeAsString, string fileName) { - try - { - UndertaleCode originalCode = GetUMTCodeFromFile(fileName); - originalCode.Replace(Assembler.Assemble(codeAsString, ModLoader.Data)); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleCode originalCode = GetUMTCodeFromFile(fileName); + originalCode.Replace(Assembler.Assemble(codeAsString, ModLoader.Data)); } public static void InsertAssemblyString(string codeAsString, string fileName, int position) { - try - { - Log.Information("Trying insert assembly in: {0}", fileName); + Log.Information("Trying insert assembly in: {0}", fileName); - List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); - originalCode.Insert(position, codeAsString); - SetAssemblyString(string.Join("\n", originalCode), fileName); + List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); + originalCode.Insert(position, codeAsString); + SetAssemblyString(string.Join("\n", originalCode), fileName); - Log.Information("Patched function with InsertAssemblyString: {0}", fileName); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Patched function with InsertAssemblyString: {0}", fileName); } public static void ReplaceAssemblyString(string codeAsString, string fileName, int position) { - try - { - Log.Information("Trying replace assembly in: {0}", fileName); + Log.Information("Trying replace assembly in: {0}", fileName); - List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); - originalCode[position] = codeAsString; - SetAssemblyString(string.Join("\n", originalCode), fileName); + List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); + originalCode[position] = codeAsString; + SetAssemblyString(string.Join("\n", originalCode), fileName); - Log.Information("Patched function with ReplaceAssemblyString: {0}", fileName); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Patched function with ReplaceAssemblyString: {0}", fileName); } public static void ReplaceAssemblyString(string codeAsString, string fileName, int start, int len) { - try - { - Log.Information("Trying replace assembly in: {0}", fileName); + Log.Information("Trying replace assembly in: {0}", fileName); - List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); - originalCode[start] = codeAsString; - for (int i = 1; i < Math.Min(len, originalCode.Count - start); i++) { - originalCode[start + i] = ""; - } - - SetAssemblyString(string.Join("\n", originalCode), fileName); - - Log.Information("Patched function with ReplaceAssemblyString: {0}", fileName); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; + List? originalCode = GetAssemblyString(fileName).Split("\n").ToList(); + originalCode[start] = codeAsString; + for (int i = 1; i < Math.Min(len, originalCode.Count - start); i++) { + originalCode[start + i] = ""; } + SetAssemblyString(string.Join("\n", originalCode), fileName); + + Log.Information("Patched function with ReplaceAssemblyString: {0}", fileName); } public static void InjectAssemblyInstruction(string name, Func, IEnumerable> patch) { - try - { - Log.Information("Trying inject assembly in: {0}", name); + Log.Information("Trying inject assembly in: {0}", name); - UndertaleCode originalCode = GetUMTCodeFromFile(name); - originalCode.Replace(patch(originalCode.Instructions).ToList()); + UndertaleCode originalCode = GetUMTCodeFromFile(name); + originalCode.Replace(patch(originalCode.Instructions).ToList()); - Log.Information("Patched function with InjectAssemblyInstruction: {0}", name); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Patched function with InjectAssemblyInstruction: {0}", name); } } public static class AssemblyWrapper @@ -226,52 +177,38 @@ public static void CheckRefLocalVariableOrCreate(UndertaleCode code, string name } public static void CheckRefVariableOrCreate(string name, UndertaleInstruction.InstanceType instanceType) { - try + UndertaleVariable? variable = null; + if (instanceType == UndertaleInstruction.InstanceType.Local) { - UndertaleVariable? variable = null; - if (instanceType == UndertaleInstruction.InstanceType.Local) - { - throw new ArgumentException("Wrong method used for checking Local Variables"); - } - else - { - variable = ModLoader.Data.Variables.FirstOrDefault(t => t.Name?.Content == name && t.InstanceType == instanceType); - } + throw new ArgumentException("Wrong method used for checking Local Variables"); + } + else + { + variable = ModLoader.Data.Variables.FirstOrDefault(t => t.Name?.Content == name && t.InstanceType == instanceType); + } - if (variable == null) - { - CreateRefVariable(name, instanceType); - } - else - { - Log.Information("Found variable: {0} of type {1}", variable.Name.Content, variable.InstanceType); - } + if (variable == null) + { + CreateRefVariable(name, instanceType); } - catch + else { - throw; + Log.Information("Found variable: {0} of type {1}", variable.Name.Content, variable.InstanceType); } } public static UndertaleInstruction.Reference GetRefVariableOrCreate(string name, UndertaleInstruction.InstanceType instanceType) { - try - { - UndertaleInstruction.Reference refVariable; - UndertaleVariable? variable = ModLoader.Data.Variables.FirstOrDefault(t => t.Name?.Content == name); - - if (variable == null) - refVariable = CreateRefVariable(name, instanceType); - else - refVariable = new UndertaleInstruction.Reference(variable, UndertaleInstruction.VariableType.Normal); + UndertaleInstruction.Reference refVariable; + UndertaleVariable? variable = ModLoader.Data.Variables.FirstOrDefault(t => t.Name?.Content == name); + + if (variable == null) + refVariable = CreateRefVariable(name, instanceType); + else + refVariable = new UndertaleInstruction.Reference(variable, UndertaleInstruction.VariableType.Normal); - Log.Information("Found variable: {0}", refVariable); + Log.Information("Found variable: {0}", refVariable); - return refVariable; - } - catch - { - throw; - } + return refVariable; } public static string CreateLocalVarAssemblyAsString(UndertaleCode code) { @@ -303,23 +240,17 @@ public static UndertaleResourceById CreateS } public static UndertaleResourceById GetStringOrCreate(string name) { - try { - UndertaleResourceById stringById; - (int ind, UndertaleString str) = ModLoader.Data.Strings.Enumerate().FirstOrDefault(x => x.Item2.Content == name); - - if (str == null) - stringById = CreateString(name); - else - stringById = new UndertaleResourceById(str, ind); + UndertaleResourceById stringById; + (int ind, UndertaleString str) = ModLoader.Data.Strings.Enumerate().FirstOrDefault(x => x.Item2.Content == name); + + if (str == null) + stringById = CreateString(name); + else + stringById = new UndertaleResourceById(str, ind); - Log.Information("Find string: {0}", stringById); + Log.Information("Find string: {0}", stringById); - return stringById; - } - catch(Exception ex) { - Log.Error(ex, "Something went wrong"); - throw; - } + return stringById; } public static UndertaleInstruction PushShort(short val) { diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index a97525e..5883913 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -89,18 +89,10 @@ public static partial class Msl /// public static UndertaleCode GetUMTCodeFromFile(string fileName) { - try - { - UndertaleCode code = ModLoader.Data.Code.First(t => t.Name?.Content == fileName); - Log.Information("Found function: {0}", code); + UndertaleCode code = ModLoader.Data.Code.First(t => t.Name?.Content == fileName); + Log.Information("Found function: {0}", code); - return code; - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + return code; } /// /// Add a new UndertaleCode named using the code . It is expected to be written in GML. @@ -110,28 +102,21 @@ public static UndertaleCode GetUMTCodeFromFile(string fileName) /// public static UndertaleCode AddCode(string codeAsString, string name) { - try + UndertaleCode code = new(); + UndertaleCodeLocals locals = new(); + code.Name = ModLoader.Data.Strings.MakeString(name); + locals.Name = code.Name; + UndertaleCodeLocals.LocalVar argsLocal = new() { - UndertaleCode code = new(); - UndertaleCodeLocals locals = new(); - code.Name = ModLoader.Data.Strings.MakeString(name); - locals.Name = code.Name; - UndertaleCodeLocals.LocalVar argsLocal = new() - { - Name = ModLoader.Data.Strings.MakeString("arguments"), - Index = 0 - }; - locals.Locals.Add(argsLocal); - code.LocalsCount = 1; - ModLoader.Data.CodeLocals.Add(locals); - code.ReplaceGML(codeAsString, ModLoader.Data); - ModLoader.Data.Code.Add(code); - return code; - } - catch - { - throw; - } + Name = ModLoader.Data.Strings.MakeString("arguments"), + Index = 0 + }; + locals.Locals.Add(argsLocal); + code.LocalsCount = 1; + ModLoader.Data.CodeLocals.Add(locals); + code.ReplaceGML(codeAsString, ModLoader.Data); + ModLoader.Data.Code.Add(code); + return code; } /// /// Add a new UndertaleCode named using the code . It is expected to be written in ASM abstraction. @@ -141,31 +126,24 @@ public static UndertaleCode AddCode(string codeAsString, string name) /// public static UndertaleCode AddCodeAsm(string codeAsString, string name) { - try - { - UndertaleCode code = new(); - UndertaleCodeLocals locals = new(); - code.Name = ModLoader.Data.Strings.MakeString(name); - locals.Name = code.Name; - UndertaleCodeLocals.LocalVar argsLocal = new() - { - Name = ModLoader.Data.Strings.MakeString("arguments"), - Index = 0 - }; - locals.Locals.Add(argsLocal); - code.LocalsCount = 1; - ModLoader.Data.CodeLocals.Add(locals); - CheckInstructionsVariables(code, codeAsString); - string newLocalVarsAsString = AssemblyWrapper.CreateLocalVarAssemblyAsString(code); - codeAsString = codeAsString.Insert(codeAsString.IndexOf('\n') + 1, newLocalVarsAsString); - code.Replace(Assembler.Assemble(codeAsString, ModLoader.Data)); - ModLoader.Data.Code.Add(code); - return code; - } - catch - { - throw; - } + UndertaleCode code = new(); + UndertaleCodeLocals locals = new(); + code.Name = ModLoader.Data.Strings.MakeString(name); + locals.Name = code.Name; + UndertaleCodeLocals.LocalVar argsLocal = new() + { + Name = ModLoader.Data.Strings.MakeString("arguments"), + Index = 0 + }; + locals.Locals.Add(argsLocal); + code.LocalsCount = 1; + ModLoader.Data.CodeLocals.Add(locals); + CheckInstructionsVariables(code, codeAsString); + string newLocalVarsAsString = AssemblyWrapper.CreateLocalVarAssemblyAsString(code); + codeAsString = codeAsString.Insert(codeAsString.IndexOf('\n') + 1, newLocalVarsAsString); + code.Replace(Assembler.Assemble(codeAsString, ModLoader.Data)); + ModLoader.Data.Code.Add(code); + return code; } /// /// Get code from file in this tool. @@ -196,21 +174,14 @@ internal static string GetCodeRes(string name) /// public static UndertaleCode AddFunction(string codeAsString, string name) { - try - { - Log.Information("Trying to add the function : {0}", name); + Log.Information("Trying to add the function : {0}", name); - UndertaleCode scriptCode = AddCode(codeAsString, name); - ModLoader.Data.Code.Add(ModLoader.Data.Code[0]); - ModLoader.Data.Code.RemoveAt(0); + UndertaleCode scriptCode = AddCode(codeAsString, name); + ModLoader.Data.Code.Add(ModLoader.Data.Code[0]); + ModLoader.Data.Code.RemoveAt(0); - Log.Information("Successfully added the function : {0}", name); - return scriptCode; - } - catch - { - throw; - } + Log.Information("Successfully added the function : {0}", name); + return scriptCode; } /// /// Add a new function from the code in this tool. @@ -223,34 +194,18 @@ public static UndertaleCode AddFunction(string codeAsString, string name) /// public static string GetStringGMLFromFile(string fileName) { - try - { - UndertaleCode code = GetUMTCodeFromFile(fileName); - GlobalDecompileContext context = new(ModLoader.Data, false); + UndertaleCode code = GetUMTCodeFromFile(fileName); + GlobalDecompileContext context = new(ModLoader.Data, false); - return Decompiler.Decompile(code, context); - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + return Decompiler.Decompile(code, context); } /// /// Set the UndertaleCode in as . /// public static void SetStringGMLInFile(string codeAsString, string fileName) { - try - { - UndertaleCode code = GetUMTCodeFromFile(fileName); - code.ReplaceGML(codeAsString, ModLoader.Data); - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleCode code = GetUMTCodeFromFile(fileName); + code.ReplaceGML(codeAsString, ModLoader.Data); } /// /// Insert GML from a string in at a given . @@ -268,21 +223,13 @@ public static void SetStringGMLInFile(string codeAsString, string fileName) /// The exact position to insert. public static void InsertGMLString(string codeAsString, string fileName, int position) { - try - { - Log.Information("Trying insert code in: {0}", fileName); + Log.Information("Trying insert code in: {0}", fileName); - List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); - originalCode.Insert(position, codeAsString); - SetStringGMLInFile(string.Join("\n", originalCode), fileName); + List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); + originalCode.Insert(position, codeAsString); + SetStringGMLInFile(string.Join("\n", originalCode), fileName); - Log.Information("Patched function with InsertGMLString: {0}", fileName); - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Patched function with InsertGMLString: {0}", fileName); } /// /// Replace an existing GML code by another from a string in at a given . @@ -300,21 +247,13 @@ public static void InsertGMLString(string codeAsString, string fileName, int pos /// The exact position to insert. public static void ReplaceGMLString(string codeAsString, string fileName, int position) { - try - { - Log.Information("Trying replace code in: {0}", fileName); + Log.Information("Trying replace code in: {0}", fileName); - List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); - originalCode[position] = codeAsString; - SetStringGMLInFile(string.Join("\n", originalCode), fileName); + List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); + originalCode[position] = codeAsString; + SetStringGMLInFile(string.Join("\n", originalCode), fileName); - Log.Information("Patched function with ReplaceGMLString: {0}", fileName); - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Patched function with ReplaceGMLString: {0}", fileName); } /// /// Replace an existing GML code by another from a string in at a given @@ -334,26 +273,18 @@ public static void ReplaceGMLString(string codeAsString, string fileName, int po /// The exact position to insert. public static void ReplaceGMLString(string codeAsString, string fileName, int start, int len) { - try - { - Log.Information("Trying replace code in: {0}", fileName); - - List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); - originalCode[start] = codeAsString; - for (int i = 1; i < Math.Min(len, originalCode.Count - start); i++) - { - originalCode[start + i] = ""; - } + Log.Information("Trying replace code in: {0}", fileName); - SetStringGMLInFile(string.Join("\n", originalCode), fileName); - - Log.Information("Patched function with ReplaceGMLString: {0}", fileName); - } - catch (Exception ex) + List? originalCode = GetStringGMLFromFile(fileName).Split("\n").ToList(); + originalCode[start] = codeAsString; + for (int i = 1; i < Math.Min(len, originalCode.Count - start); i++) { - Log.Error(ex, "Something went wrong"); - throw; + originalCode[start + i] = ""; } + + SetStringGMLInFile(string.Join("\n", originalCode), fileName); + + Log.Information("Patched function with ReplaceGMLString: {0}", fileName); } /// /// Convert a (Match, string) IEnumerable into a string IEnumerable by selecting for all elements only the string part. diff --git a/ModUtils/EventUtils.cs b/ModUtils/EventUtils.cs index 921b42d..ab241f7 100644 --- a/ModUtils/EventUtils.cs +++ b/ModUtils/EventUtils.cs @@ -42,14 +42,7 @@ public MslEvent(string code, EventType eventType, uint subtype) /// public void Apply(string objectName, ModFile modFile) { - try - { - Msl.AddNewEvent(objectName, modFile.GetCode(Code), EventType, Subtype); - } - catch - { - throw; - } + Msl.AddNewEvent(objectName, modFile.GetCode(Code), EventType, Subtype); } /// /// Given a , load the source code of the event and add it in the data.win through the function. @@ -58,14 +51,7 @@ public void Apply(string objectName, ModFile modFile) /// public void Apply(UndertaleGameObject gameObject, ModFile modFile) { - try - { - Msl.AddNewEvent(gameObject, modFile.GetCode(Code), EventType, Subtype); - } - catch - { - throw; - } + Msl.AddNewEvent(gameObject, modFile.GetCode(Code), EventType, Subtype); } /// /// Given an named , load the source code of the event and add it in the data.win through the function. @@ -74,14 +60,7 @@ public void Apply(UndertaleGameObject gameObject, ModFile modFile) /// public void Apply(string objectName) { - try - { - Msl.AddNewEvent(objectName, Code, EventType, Subtype); - } - catch - { - throw; - } + Msl.AddNewEvent(objectName, Code, EventType, Subtype); } /// /// Given a , load the source code of the event and add it in the data.win through the function. @@ -90,14 +69,7 @@ public void Apply(string objectName) /// public void Apply(UndertaleGameObject objectName) { - try - { - Msl.AddNewEvent(objectName, Code, EventType, Subtype); - } - catch - { - throw; - } + Msl.AddNewEvent(objectName, Code, EventType, Subtype); } } public static partial class Msl @@ -137,43 +109,35 @@ public static void AddNewEvent(string objectName, string eventCode, EventType ev /// public static void AddNewEvent(string objectName, string eventCode, EventType eventType, uint subtype, bool asAsm = false) { - try + CheckSubEvent(eventType, subtype); + // find the object + UndertaleGameObject gameObject = GetObject(objectName); + // check if the subEvent already exists + Event? subtypeObj = gameObject.Events[(int)eventType].FirstOrDefault(x => x.EventSubtype == subtype); + if (subtypeObj != null) { - CheckSubEvent(eventType, subtype); - // find the object - UndertaleGameObject gameObject = GetObject(objectName); - // check if the subEvent already exists - Event? subtypeObj = gameObject.Events[(int)eventType].FirstOrDefault(x => x.EventSubtype == subtype); - if (subtypeObj != null) - { - throw new ArgumentException(string.Format("Cannot add the event {0}_{1} in {2} since it already exists", eventType, subtype, objectName)); - } + throw new ArgumentException(string.Format("Cannot add the event {0}_{1} in {2} since it already exists", eventType, subtype, objectName)); + } - // create a new code - string newEventName = EventName(objectName, eventType, subtype); - if (asAsm) - { - AddCodeAsm(eventCode, newEventName); - } - else - { - AddCode(eventCode, newEventName); - } - // add the previous code to the event - Event newEvent = new() { EventSubtype = subtype }; - newEvent.Actions.Add(new EventAction() - { - CodeId = GetUMTCodeFromFile(newEventName), - }); - - gameObject.Events[(int)eventType].Add(newEvent); - Log.Information("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, objectName); + // create a new code + string newEventName = EventName(objectName, eventType, subtype); + if (asAsm) + { + AddCodeAsm(eventCode, newEventName); } - catch(Exception ex) + else { - Log.Error(ex, "Something went wrong"); - throw; + AddCode(eventCode, newEventName); } + // add the previous code to the event + Event newEvent = new() { EventSubtype = subtype }; + newEvent.Actions.Add(new EventAction() + { + CodeId = GetUMTCodeFromFile(newEventName), + }); + + gameObject.Events[(int)eventType].Add(newEvent); + Log.Information("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, objectName); } /// /// Add a new event (, ) associated to a . @@ -185,14 +149,7 @@ public static void AddNewEvent(string objectName, string eventCode, EventType ev /// public static void AddNewEvent(UndertaleGameObject objectName, string eventCode, EventType eventType, uint subtype) { - try - { - AddNewEvent(objectName, eventCode, eventType, subtype, false); - } - catch - { - throw; - } + AddNewEvent(objectName, eventCode, eventType, subtype, false); } /// /// Add a new event (, ) associated to a . @@ -204,42 +161,34 @@ public static void AddNewEvent(UndertaleGameObject objectName, string eventCode, /// public static void AddNewEvent(UndertaleGameObject gameObject, string eventCode, EventType eventType, uint subtype, bool asAsm = false) { - try + CheckSubEvent(eventType, subtype); + // check if the subEvent already exists + Event? subtypeObj = gameObject.Events[(int)eventType].FirstOrDefault(x => x.EventSubtype == subtype); + if (subtypeObj != null) { - CheckSubEvent(eventType, subtype); - // check if the subEvent already exists - Event? subtypeObj = gameObject.Events[(int)eventType].FirstOrDefault(x => x.EventSubtype == subtype); - if (subtypeObj != null) - { - throw new ArgumentException(string.Format("Cannot add the event {0}_{1} in {2} since it already exists", eventType, subtype, gameObject.Name.Content)); - } + throw new ArgumentException(string.Format("Cannot add the event {0}_{1} in {2} since it already exists", eventType, subtype, gameObject.Name.Content)); + } - // create a new code - string newEventName = EventName(gameObject.Name.Content, eventType, subtype); + // create a new code + string newEventName = EventName(gameObject.Name.Content, eventType, subtype); - if (asAsm) - { - AddCodeAsm(eventCode, newEventName); - } - else - { - AddCode(eventCode, newEventName); - } - // add the previous code to the event - Event newEvent = new() { EventSubtype = subtype }; - newEvent.Actions.Add(new EventAction() - { - CodeId = GetUMTCodeFromFile(newEventName), - }); - - gameObject.Events[(int)eventType].Add(newEvent); - Log.Information("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, gameObject.Name.Content); + if (asAsm) + { + AddCodeAsm(eventCode, newEventName); } - catch(Exception ex) + else { - Log.Error(ex, "Something went wrong"); - throw; + AddCode(eventCode, newEventName); } + // add the previous code to the event + Event newEvent = new() { EventSubtype = subtype }; + newEvent.Actions.Add(new EventAction() + { + CodeId = GetUMTCodeFromFile(newEventName), + }); + + gameObject.Events[(int)eventType].Add(newEvent); + Log.Information("Successfully added event {{{0}_{1}}} in object {{{2}}}", eventType, subtype, gameObject.Name.Content); } /// /// Check if the combination and are correct. Raise an exception if not. diff --git a/ModUtils/GeneralUtils.cs b/ModUtils/GeneralUtils.cs index cffb0bd..981f9f6 100644 --- a/ModUtils/GeneralUtils.cs +++ b/ModUtils/GeneralUtils.cs @@ -17,46 +17,30 @@ public static partial class Msl { public static FileEnumerable LoadGML(string fileName) { - try - { - UndertaleCode code = GetUMTCodeFromFile(fileName); - GlobalDecompileContext context = new(ModLoader.Data, false); + UndertaleCode code = GetUMTCodeFromFile(fileName); + GlobalDecompileContext context = new(ModLoader.Data, false); - return new( - new( - fileName, - code, - PatchingWay.GML - ), - Decompiler.Decompile(code, context).Split("\n") - ); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + return new( + new( + fileName, + code, + PatchingWay.GML + ), + Decompiler.Decompile(code, context).Split("\n") + ); } public static FileEnumerable LoadAssemblyAsString(string fileName) { - try - { - UndertaleCode code = GetUMTCodeFromFile(fileName); + UndertaleCode code = GetUMTCodeFromFile(fileName); - return new( - new( - fileName, - code, - PatchingWay.AssemblyAsString - ), - code.Disassemble(ModLoader.Data.Variables, ModLoader.Data.CodeLocals.For(code)).Split("\n") - ); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + return new( + new( + fileName, + code, + PatchingWay.AssemblyAsString + ), + code.Disassemble(ModLoader.Data.Variables, ModLoader.Data.CodeLocals.For(code)).Split("\n") + ); } /// /// Equivalent of enumerate found in Python but for C# IEnumerable. diff --git a/ModUtils/HookUtils.cs b/ModUtils/HookUtils.cs index f1ddc79..79d9214 100644 --- a/ModUtils/HookUtils.cs +++ b/ModUtils/HookUtils.cs @@ -18,20 +18,12 @@ public static partial class Msl /// All the things you want to get. public static void HookFunction(string functionName, string hookName, params string[] paramNames) { - try - { - Log.Information("Trying add hook in: {0}", functionName); + Log.Information("Trying add hook in: {0}", functionName); - List? originalCode = GetStringGMLFromFile(functionName).Split("\n").ToList(); - originalCode.Append($"var {hookName} = createHookObj({paramNames.Length}, {string.Join(", ", paramNames)})"); - originalCode.Append($"SendMsg(\"HOK\", \"{hookName}\" + {hookName}, false)"); - SetStringGMLInFile(string.Join("\n", originalCode), functionName); - } - catch (Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + List? originalCode = GetStringGMLFromFile(functionName).Split("\n").ToList(); + originalCode.Append($"var {hookName} = createHookObj({paramNames.Length}, {string.Join(", ", paramNames)})"); + originalCode.Append($"SendMsg(\"HOK\", \"{hookName}\" + {hookName}, false)"); + SetStringGMLInFile(string.Join("\n", originalCode), functionName); } } } diff --git a/ModUtils/ObjectUtils.cs b/ModUtils/ObjectUtils.cs index 912245f..bb34005 100644 --- a/ModUtils/ObjectUtils.cs +++ b/ModUtils/ObjectUtils.cs @@ -138,16 +138,9 @@ public static UndertaleGameObject AddObject( /// public static UndertaleGameObject GetObject(string name) { - try - { - UndertaleGameObject gameObject = ModLoader.Data.GameObjects.First(t => t.Name.Content == name); - Log.Information("Found gameObject: {0}", name); - return gameObject; - } - catch - { - throw; - } + UndertaleGameObject gameObject = ModLoader.Data.GameObjects.First(t => t.Name.Content == name); + Log.Information("Found gameObject: {0}", name); + return gameObject; } /// /// Replace the named by . @@ -157,17 +150,9 @@ public static UndertaleGameObject GetObject(string name) /// public static void SetObject(string name, UndertaleGameObject o) { - try - { - (int indexObj, _) = ModLoader.Data.GameObjects.Enumerate().First(t => t.Item2.Name.Content == name); - ModLoader.Data.GameObjects[indexObj] = o; - Log.Information("Successfully replaced gameObject: {0}", name); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + (int indexObj, _) = ModLoader.Data.GameObjects.Enumerate().First(t => t.Item2.Name.Content == name); + ModLoader.Data.GameObjects[indexObj] = o; + Log.Information("Successfully replaced gameObject: {0}", name); } } } \ No newline at end of file diff --git a/ModUtils/TextureUtils.cs b/ModUtils/TextureUtils.cs index c7d0b47..76987f2 100644 --- a/ModUtils/TextureUtils.cs +++ b/ModUtils/TextureUtils.cs @@ -101,100 +101,58 @@ public static UndertaleSprite CreateSpriteNoCollisionMasks(string spriteName, Ma } public static UndertaleSprite GetSprite(string name) { - try - { - UndertaleSprite sprite = ModLoader.Data.Sprites.First(t => t.Name.Content == name); - Log.Information("Found sprite: {0}", name); - return sprite; - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleSprite sprite = ModLoader.Data.Sprites.First(t => t.Name.Content == name); + Log.Information("Found sprite: {0}", name); + return sprite; } public static UndertaleEmbeddedTexture GetEmbeddedTexture(string name) { - try - { - UndertaleEmbeddedTexture embeddedTexture = ModLoader.Data.EmbeddedTextures.First(t => t.Name.Content == name); - Log.Information("Found embedded texture: {0}", name); - return embeddedTexture; - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleEmbeddedTexture embeddedTexture = ModLoader.Data.EmbeddedTextures.First(t => t.Name.Content == name); + Log.Information("Found embedded texture: {0}", name); + return embeddedTexture; } public static UndertaleTexturePageItem GetTexturePageItem(string name) { - try - { - UndertaleTexturePageItem texturePageItem = ModLoader.Data.TexturePageItems.First(t => t.Name.Content == name); - Log.Information("Found texture page item: {0}", name); - return texturePageItem; - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleTexturePageItem texturePageItem = ModLoader.Data.TexturePageItems.First(t => t.Name.Content == name); + Log.Information("Found texture page item: {0}", name); + return texturePageItem; } public static string AddNewTexturePageItem(string embeddedTextureName, RectTexture source, RectTexture target, BoundingData bounding) { - try - { - UndertaleEmbeddedTexture embeddedTexture = GetEmbeddedTexture(embeddedTextureName); - - UndertaleTexturePageItem texturePageItem = CreateTexureItem( - embeddedTexture, - source, - target, - bounding - ); - ModLoader.Data.TexturePageItems.Add(texturePageItem); - Log.Information("Successfully added a new texture from: {0}", embeddedTextureName); - return texturePageItem.Name.Content; + UndertaleEmbeddedTexture embeddedTexture = GetEmbeddedTexture(embeddedTextureName); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + UndertaleTexturePageItem texturePageItem = CreateTexureItem( + embeddedTexture, + source, + target, + bounding + ); + ModLoader.Data.TexturePageItems.Add(texturePageItem); + Log.Information("Successfully added a new texture from: {0}", embeddedTextureName); + return texturePageItem.Name.Content; } public static string AddNewSprite(string spriteName, List texturePageItemNames, MarginData margin, OriginData origin, BoundingData bounding) { - try - { - UndertaleSprite newSprite = CreateSpriteNoCollisionMasks( - spriteName, - margin, - origin, - bounding - ); + UndertaleSprite newSprite = CreateSpriteNoCollisionMasks( + spriteName, + margin, + origin, + bounding + ); - IEnumerable texturePageItems = texturePageItemNames - .Select(x => GetTexturePageItem(x)) - .Select(x => new UndertaleSprite.TextureEntry(){ Texture = x }); + IEnumerable texturePageItems = texturePageItemNames + .Select(x => GetTexturePageItem(x)) + .Select(x => new UndertaleSprite.TextureEntry(){ Texture = x }); - foreach(UndertaleSprite.TextureEntry texturePageItem in texturePageItems) - { - newSprite.Textures.Add(texturePageItem); - } - - ModLoader.Data.Sprites.Add(newSprite); - - Log.Information("Successfully added new sprite: {0}", newSprite.Name.Content); - return newSprite.Name.Content; - - } - catch(Exception ex) + foreach(UndertaleSprite.TextureEntry texturePageItem in texturePageItems) { - Log.Error(ex, "Something went wrong"); - throw; + newSprite.Textures.Add(texturePageItem); } + + ModLoader.Data.Sprites.Add(newSprite); + + Log.Information("Successfully added new sprite: {0}", newSprite.Name.Content); + return newSprite.Name.Content; } } } \ No newline at end of file diff --git a/ModUtils/VariableUtils.cs b/ModUtils/VariableUtils.cs index 2279c18..5eb2828 100644 --- a/ModUtils/VariableUtils.cs +++ b/ModUtils/VariableUtils.cs @@ -9,31 +9,17 @@ public static partial class Msl { public static UndertaleVariable GetVariable(string name) { - try - { - UndertaleVariable variable = ModLoader.Data.Variables.First(t => t.Name?.Content == name); - Log.Information("Found variable: {0}", variable); + UndertaleVariable variable = ModLoader.Data.Variables.First(t => t.Name?.Content == name); + Log.Information("Found variable: {0}", variable); - return variable; - } - catch(Exception ex) { - Log.Error(ex, "Something went wrong"); - throw; - } + return variable; } public static UndertaleString GetString(string name) { - try - { - UndertaleString variable = ModLoader.Data.Strings.First(t => t.Content == name); - Log.Information("Found string: {0}", variable); + UndertaleString variable = ModLoader.Data.Strings.First(t => t.Content == name); + Log.Information("Found string: {0}", variable); - return variable; - } - catch(Exception ex) { - Log.Error(ex, "Something went wrong"); - throw; - } + return variable; } } } \ No newline at end of file diff --git a/ModUtils/WeaponUtils.cs b/ModUtils/WeaponUtils.cs index 4f2929c..de08d73 100644 --- a/ModUtils/WeaponUtils.cs +++ b/ModUtils/WeaponUtils.cs @@ -10,64 +10,48 @@ public static partial class Msl { public static Weapon GetWeapon(string id) { - try - { - string weaponsName = ModLoader.Weapons.First(t => t.StartsWith(id)); + string weaponsName = ModLoader.Weapons.First(t => t.StartsWith(id)); - // for a lazy evaluation to avoid going through all the WeaponDescriptions list - IEnumerator weaponDescriptionEnumerator = ModLoader.WeaponDescriptions.Where(t => t.StartsWith(id)).GetEnumerator(); + // for a lazy evaluation to avoid going through all the WeaponDescriptions list + IEnumerator weaponDescriptionEnumerator = ModLoader.WeaponDescriptions.Where(t => t.StartsWith(id)).GetEnumerator(); - // getting the first element - the localization name - weaponDescriptionEnumerator.MoveNext(); - List localizationNames = weaponDescriptionEnumerator.Current.Split(";").ToList(); - localizationNames.Remove(""); - localizationNames.RemoveAt(0); + // getting the first element - the localization name + weaponDescriptionEnumerator.MoveNext(); + List localizationNames = weaponDescriptionEnumerator.Current.Split(";").ToList(); + localizationNames.Remove(""); + localizationNames.RemoveAt(0); - // getting the second element - the description - weaponDescriptionEnumerator.MoveNext(); - List weaponDescription = weaponDescriptionEnumerator.Current.Split(";").ToList(); - weaponDescription.Remove(""); - weaponDescription.RemoveAt(0); + // getting the second element - the description + weaponDescriptionEnumerator.MoveNext(); + List weaponDescription = weaponDescriptionEnumerator.Current.Split(";").ToList(); + weaponDescription.Remove(""); + weaponDescription.RemoveAt(0); - Log.Information("Found weapon: {0}", weaponsName); - return new(weaponsName, weaponDescription, localizationNames); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Found weapon: {0}", weaponsName); + return new(weaponsName, weaponDescription, localizationNames); } public static void SetWeapon(string id, Weapon weapon) { - try - { - string targetName = ModLoader.Weapons.First(t => t.StartsWith(id)); - int indexTargetName = ModLoader.Weapons.IndexOf(targetName); + string targetName = ModLoader.Weapons.First(t => t.StartsWith(id)); + int indexTargetName = ModLoader.Weapons.IndexOf(targetName); - // for a lazy evaluation to avoid going through all the WeaponDescriptions list - IEnumerator<(int, string)> weaponDescriptionEnumerator = ModLoader.WeaponDescriptions.Where(t => t.StartsWith(id)).Enumerate().GetEnumerator(); + // for a lazy evaluation to avoid going through all the WeaponDescriptions list + IEnumerator<(int, string)> weaponDescriptionEnumerator = ModLoader.WeaponDescriptions.Where(t => t.StartsWith(id)).Enumerate().GetEnumerator(); - // getting the first element - the localization name - weaponDescriptionEnumerator.MoveNext(); - (int indexLocalizationName, _) = weaponDescriptionEnumerator.Current; + // getting the first element - the localization name + weaponDescriptionEnumerator.MoveNext(); + (int indexLocalizationName, _) = weaponDescriptionEnumerator.Current; - // getting the first element - the description - weaponDescriptionEnumerator.MoveNext(); - (int indexDescription, _) = weaponDescriptionEnumerator.Current; + // getting the first element - the description + weaponDescriptionEnumerator.MoveNext(); + (int indexDescription, _) = weaponDescriptionEnumerator.Current; - (string, string, string) w2s = Weapon.Weapon2String(weapon); - ModLoader.Weapons[indexTargetName] = w2s.Item1; - ModLoader.WeaponDescriptions[indexDescription] = w2s.Item2; - ModLoader.WeaponDescriptions[indexLocalizationName] = w2s.Item3; + (string, string, string) w2s = Weapon.Weapon2String(weapon); + ModLoader.Weapons[indexTargetName] = w2s.Item1; + ModLoader.WeaponDescriptions[indexDescription] = w2s.Item2; + ModLoader.WeaponDescriptions[indexLocalizationName] = w2s.Item3; - Log.Information("Successfully set weapon: {0}", targetName); - } - catch(Exception ex) - { - Log.Error(ex, "Something went wrong"); - throw; - } + Log.Information("Successfully set weapon: {0}", targetName); } } } \ No newline at end of file From a10ca48de932a18a715e322b2945a8e2f24b493f Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 23:50:03 +0200 Subject: [PATCH 06/11] [Minor] using Log instead of messagebox for missing files --- FileReader.cs | 8 ++++---- ModLoader.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/FileReader.cs b/FileReader.cs index 2e99cce..b0e43f0 100644 --- a/FileReader.cs +++ b/FileReader.cs @@ -14,9 +14,9 @@ namespace ModShardLauncher { - public class FileChunk + public class FileChunk { - public string name; + public string name = string.Empty; public int offset; public int length; } @@ -58,7 +58,7 @@ public byte[] GetFile(string fileName) { if(!isExisted) { - MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + Name); + Log.Error("The mod {0} which was located at {1} does not exist anymore.", Name, Path); ModLoader.LoadFiles(); return Array.Empty(); } @@ -92,7 +92,7 @@ public string GetCode(string fileName) string text = Encoding.UTF8.GetString(data); if(text.Length == 0) { - MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + fileName); + Log.Error("The mod {0} which was located at {1} does not exist anymore.", Name, Path); throw new ArgumentException("String cannot be of length zero"); } return text; diff --git a/ModLoader.cs b/ModLoader.cs index 490ab69..4b1c286 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -160,7 +160,7 @@ public static void PatchMods() if (!mod.isEnabled) continue; if (!mod.isExisted) { - MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + mod.Name); + Log.Warning("The mod {0} which was located at {1} does not exist anymore.", mod.Name, mod.Path); continue; } Main.Settings.EnableMods.Add(mod.Name); From bff59dc0ac42cb303b04d04c9fffb50adb7a0ae4 Mon Sep 17 00:00:00 2001 From: remyCases Date: Mon, 8 Sep 2025 00:44:59 +0200 Subject: [PATCH 07/11] [Minor] better logging errors if loading an external .gml or .asm file failed, no more uses of try/catch in async button related functions and a better something went wrong error message --- Controls/ModInfos.xaml.cs | 38 ++++++++-------------- ModLoader.cs | 37 +++++++++++++++++----- ModUtils/CodeUtils.cs | 66 +++++++++++++++++++++++++++++++++++---- 3 files changed, 103 insertions(+), 38 deletions(-) diff --git a/Controls/ModInfos.xaml.cs b/Controls/ModInfos.xaml.cs index adaa58b..904b9af 100644 --- a/Controls/ModInfos.xaml.cs +++ b/Controls/ModInfos.xaml.cs @@ -34,39 +34,27 @@ private async void Save_Click(object sender, EventArgs e) return; } - bool patchSucess = false; - bool saveSucess = false; - - try + if (ModLoader.PatchFile()) { - ModLoader.PatchFile(); - Log.Information("Successfully patch vanilla"); - patchSucess = true; Main.Instance.LogModList(); - } - catch (Exception ex) - { - Main.Instance.LogModList(); - Log.Error(ex, "Something went wrong"); - Log.Information("Failed patching vanilla"); - MessageBox.Show(ex.ToString(), Application.Current.FindResource("SaveDataWarning").ToString()); - } + Log.Information("Successfully patch vanilla"); - // attempt to save the patched data - if (patchSucess) - { Task save = DataLoader.DoSaveDialog(); await save; - saveSucess = save.Result; - } - - if (saveSucess) - { - LootUtils.SaveLootTables(Msl.ThrowIfNull(Path.GetDirectoryName(DataLoader.savedDataPath))); + if (save.Result) + { + LootUtils.SaveLootTables(Msl.ThrowIfNull(Path.GetDirectoryName(DataLoader.savedDataPath))); + } + else + { + Log.Information("Saved cancelled."); + } } else { - Log.Information("Saved cancelled."); + Main.Instance.LogModList(); + Log.Information("Failed patching vanilla"); + MessageBox.Show("Patching failed, more information can be found in the logs.", Application.Current.FindResource("SaveDataWarning").ToString()); } // reload the data diff --git a/ModLoader.cs b/ModLoader.cs index 4b1c286..516c296 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -199,14 +199,37 @@ public static void LoadWeapon(Type type) WeaponDescriptions.Insert(WeaponDescriptions.IndexOf(";weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;") + 1, weapon.Name + ";He;;;It;She;She;She;She;He;;;;"); } - public static void PatchFile() + public static bool PatchFile() { - // add new msl log function - LogUtils.InjectLog(); - PatchInnerFile(); - PatchMods(); - // add the new loot related functions if there is any - LootUtils.InjectLootScripts(); + try + { + // add new msl log function + LogUtils.InjectLog(); + PatchInnerFile(); + PatchMods(); + // add the new loot related functions if there is any + LootUtils.InjectLootScripts(); + return true; + } + catch (Exception ex) + { + string extraInformation = ""; + object? fileName = null; + object? patchingWay = null; + if (ex.Data.Contains("fileName")) + { + fileName = ex.Data["fileName"]; + extraInformation += " in file {{{0}}}"; + } + if (ex.Data.Contains("patchingWay")) + { + patchingWay = ex.Data["patchingWay"]; + extraInformation += " while patching by {{{1}}}"; + } + + Log.Error(ex, "Something went wrong" + extraInformation, fileName, patchingWay); + return false; + } } internal static void PatchInnerFile() { diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index 5883913..f874891 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -427,7 +427,16 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) /// public static FileEnumerable<(Match, string)> MatchFrom(this FileEnumerable fe, ModFile modFile, string fileName) { - return new(fe.header, fe.ienumerable.MatchFrom(modFile.GetCode(fileName).Split("\n"))); + try + { + return new(fe.header, fe.ienumerable.MatchFrom(modFile.GetCode(fileName).Split("\n"))); + } + catch (Exception ex) + { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay); + throw; + } } /// /// A selector that tags the -th lines of code below a given list of string. @@ -508,7 +517,16 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) /// public static FileEnumerable<(Match, string)> MatchBelow(this FileEnumerable fe, ModFile modFile, string fileName, int len) { - return new(fe.header, fe.ienumerable.MatchBelow(modFile.GetCode(fileName).Split("\n"), len)); + try + { + return new(fe.header, fe.ienumerable.MatchBelow(modFile.GetCode(fileName).Split("\n"), len)); + } + catch (Exception ex) + { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay); + throw; + } } /// /// A selector that tags the all lines of the input. @@ -619,7 +637,16 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) /// public static FileEnumerable<(Match, string)> MatchFromUntil(this FileEnumerable fe, ModFile modFile, string filenameOther, string filenameUntil) { - return new(fe.header, fe.ienumerable.MatchFromUntil(modFile.GetCode(filenameOther).Split("\n"), modFile.GetCode(filenameUntil).Split("\n"))); + try + { + return new(fe.header, fe.ienumerable.MatchFromUntil(modFile.GetCode(filenameOther).Split("\n"), modFile.GetCode(filenameUntil).Split("\n"))); + } + catch (Exception ex) + { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay); + throw; + } } /// /// An action on an IEnumerable that prints each line on the log console but does not alter the data flow. @@ -782,7 +809,16 @@ public static FileEnumerable InsertBelow(this FileEnumerable<(Match, str /// public static FileEnumerable InsertBelow(this FileEnumerable<(Match, string)> fe, ModFile modFile, string fileName) { - return new(fe.header, fe.ienumerable.InsertBelow(modFile.GetCode(fileName).Split("\n"))); + try + { + return new(fe.header, fe.ienumerable.InsertBelow(modFile.GetCode(fileName).Split("\n"))); + } + catch (Exception ex) + { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay); + throw; + } } /// /// An action on an IEnumerable that inserts lines of code above the Matching block. @@ -830,7 +866,16 @@ public static FileEnumerable InsertAbove(this FileEnumerable<(Match, str /// public static FileEnumerable InsertAbove(this FileEnumerable<(Match, string)> fe, ModFile modFile, string fileName) { - return new(fe.header, fe.ienumerable.InsertAbove(modFile.GetCode(fileName).Split("\n"))); + try + { + return new(fe.header, fe.ienumerable.InsertAbove(modFile.GetCode(fileName).Split("\n"))); + } + catch (Exception ex) + { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay); + throw; + } } /// /// An action on an IEnumerable that replace the Matching block with the lines given. @@ -884,7 +929,16 @@ public static FileEnumerable ReplaceBy(this FileEnumerable<(Match, strin /// public static FileEnumerable ReplaceBy(this FileEnumerable<(Match, string)> fe, ModFile modFile, string fileName) { - return new(fe.header, fe.ienumerable.ReplaceBy(modFile.GetCode(fileName).Split("\n"))); + try + { + return new(fe.header, fe.ienumerable.ReplaceBy(modFile.GetCode(fileName).Split("\n"))); + } + catch (Exception ex) + { + ex.Data.Add("fileName", fe.header.fileName); + ex.Data.Add("patchingWay", fe.header.patchingWay); + throw; + } } /// /// Apply an to an . From 3c75d48f3853c53005a6c881156126a06b0c28c3 Mon Sep 17 00:00:00 2001 From: remyCases Date: Mon, 8 Sep 2025 01:07:40 +0200 Subject: [PATCH 08/11] [Minor] fixes unit tests --- ModShardLauncherTest/CodeUtilsTest.cs | 27 ++++++++++++--------------- ModUtils/CodeUtils.cs | 10 +--------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/ModShardLauncherTest/CodeUtilsTest.cs b/ModShardLauncherTest/CodeUtilsTest.cs index 52464a8..052cbac 100644 --- a/ModShardLauncherTest/CodeUtilsTest.cs +++ b/ModShardLauncherTest/CodeUtilsTest.cs @@ -263,10 +263,10 @@ public void MatchFrom_EmptyString_WithNonEmptyString(string input) IEnumerable stringList = "".Split('\n'); // Act - Exception ex = Assert.Throws(() => stringList.MatchFrom(input).ToList()); + InvalidOperationException ex = Assert.Throws(() => stringList.MatchFrom(input).ToList()); // Assert - Assert.Contains("MatchFrom: No matching lines found", ex.Message); + Assert.Equal($"MatchFrom: No matching lines found. Items to match:\n{input}", ex.Message); } [Theory] @@ -327,11 +327,10 @@ public void MatchFrom_NonEmptyString_NoMatch(string input, string stringToMatch) IEnumerable stringList = input.Split('\n'); // Act - Exception ex = Assert.Throws(() => stringList.MatchFrom(stringToMatch).ToList()); + InvalidOperationException ex = Assert.Throws(() => stringList.MatchFrom(stringToMatch).ToList()); // Assert - Assert.Contains("MatchFrom: No matching lines found", ex.Message); - Assert.Contains(stringToMatch, ex.Message); + Assert.Equal($"MatchFrom: No matching lines found. Items to match:\n{stringToMatch}", ex.Message); } [Theory] @@ -422,10 +421,10 @@ public void MatchBelow_EmptyString_WithNonEmptyString(string input) IEnumerable stringList = "".Split('\n'); // Act - Exception ex = Assert.Throws(() => stringList.MatchBelow(input, 0).ToList()); + InvalidOperationException ex = Assert.Throws(() => stringList.MatchBelow(input, 0).ToList()); // Assert - Assert.Contains("MatchBelow: No matching lines found", ex.Message); + Assert.Equal($"MatchBelow: No matching lines found. Items to match:\n{input}", ex.Message); } [Theory] @@ -502,11 +501,10 @@ public void MatchBelow_NonEmptyString_NoMatch(string input, string stringToMatch IEnumerable stringList = input.Split('\n'); // Act - Exception ex = Assert.Throws(() => stringList.MatchBelow(stringToMatch, len).ToList()); + InvalidOperationException ex = Assert.Throws(() => stringList.MatchBelow(stringToMatch, len).ToList()); // Assert - Assert.Contains("MatchBelow: No matching lines found", ex.Message); - Assert.Contains(stringToMatch, ex.Message); + Assert.Equal($"MatchBelow: No matching lines found. Items to match:\n{stringToMatch}", ex.Message); } [Theory] @@ -596,10 +594,10 @@ public void MatchFromUntil_EmptyString_FromNonEmptyStringUntilEmptyString(string IEnumerable stringList = "".Split('\n'); // Act - Exception ex = Assert.Throws(() => stringList.MatchFromUntil(input, "").ToList()); + InvalidOperationException ex = Assert.Throws(() => stringList.MatchFromUntil(input, "").ToList()); // Assert - Assert.Contains("MatchFrom: No matching lines found", ex.Message); + Assert.Equal($"MatchFrom: No matching lines found. Items to match:\n{input}", ex.Message); } [Theory] @@ -619,11 +617,10 @@ public void MatchFromUntil_FromNoMatch_UntilEmptyString(string input, string fro IEnumerable stringList = input.Split('\n'); // Act - Exception ex = Assert.Throws(() => stringList.MatchFromUntil(from, "").ToList()); + InvalidOperationException ex = Assert.Throws(() => stringList.MatchFromUntil(from, "").ToList()); // Assert - Assert.Contains("MatchFrom: No matching lines found", ex.Message); - Assert.Contains(from, ex.Message); + Assert.Equal($"MatchFrom: No matching lines found. Items to match:\n{from}", ex.Message); } [Theory] diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index f874891..5147385 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -576,6 +576,7 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) if (otherUntilEnumerator.MoveNext()) otherUntilString = otherUntilEnumerator.Current; + foreach ((Match m, string element) in ienumerable.MatchFrom(otherfrom)) { if (m == Match.Before || m == Match.Matching) @@ -608,15 +609,6 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) yield return (Match.After, element); } } - - if (!foundUntil) - { - throw new InvalidOperationException( - string.Format("MatchFromUntil: No matching lines found. Items to match:\nFrom\n{0}\nTo\n{1}", - string.Join("\n", otherfrom), - string.Join("\n", otheruntil)) - ); - } } /// /// Same behaviour as but using .Split('\n') and .Split('\n') for the comparison. From 97869fbf2357e7fc66a05dfef5c6809e4c99f114 Mon Sep 17 00:00:00 2001 From: remyCases Date: Thu, 11 Sep 2025 14:04:33 +0200 Subject: [PATCH 09/11] [Minor] adding diagnostic class to sum up code behaviour upon failing, first rework of the error windowbox --- Controls/ModInfos.xaml.cs | 9 ++++++-- Core/Errors/MSLDiagnostic.cs | 45 ++++++++++++++++++++++++++++++++++++ Main.xaml.cs | 4 ++++ ModLoader.cs | 24 +++++-------------- ModShardLauncher.csproj | 2 +- 5 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 Core/Errors/MSLDiagnostic.cs diff --git a/Controls/ModInfos.xaml.cs b/Controls/ModInfos.xaml.cs index 2595b42..2dfca67 100644 --- a/Controls/ModInfos.xaml.cs +++ b/Controls/ModInfos.xaml.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using ModShardLauncher.Core.Errors; using ModShardLauncher.Mods; using Serilog; @@ -36,7 +37,9 @@ private async void Save_Click(object sender, EventArgs e) return; } - if (ModLoader.PatchFile()) + MSLDiagnostic? diag = ModLoader.PatchFile(); + + if (diag is null) { Main.Instance.LogModListStatus(); Log.Information("Successfully patch vanilla"); @@ -56,7 +59,9 @@ private async void Save_Click(object sender, EventArgs e) { Main.Instance.LogModListStatus(); Log.Information("Failed patching vanilla"); - MessageBox.Show("Patching failed, more information can be found in the logs.", Application.Current.FindResource("SaveDataWarning").ToString()); + string messageBoxText = "Do you want to save changes?"; + string caption = diag.Title(); + MessageBox.Show(messageBoxText, caption); } // reload the data diff --git a/Core/Errors/MSLDiagnostic.cs b/Core/Errors/MSLDiagnostic.cs new file mode 100644 index 0000000..87f1435 --- /dev/null +++ b/Core/Errors/MSLDiagnostic.cs @@ -0,0 +1,45 @@ +using System; +using Serilog; + +namespace ModShardLauncher.Core.Errors +{ + public class MSLDiagnostic + { + public string ModName; + public string? FileName; + public string? PatchingMethod; + public Exception exception; + public MSLDiagnostic(Exception ex, ModFile modFile) + { + if (ex.Data.Contains("fileName")) + { + object? fileName = ex.Data["fileName"]; + FileName = $"{fileName}"; + } + if (ex.Data.Contains("patchingWay")) + { + object? patchingWay = ex.Data["patchingWay"]; + PatchingMethod = $"{patchingWay}"; + } + ModName = modFile.Name; + exception = ex; + } + public void ToLog() + { + string extraInformation = " for {{{0}}}"; + if (FileName is not null) + { + extraInformation += " in file {{{1}}}"; + } + if (PatchingMethod is not null) + { + extraInformation += " while patching by {{{2}}}"; + } + Log.Error(exception, "Something went wrong" + extraInformation, ModName, FileName, PatchingMethod); + } + public string Title() + { + return $"{ModName} failed"; + } + } +} \ No newline at end of file diff --git a/Main.xaml.cs b/Main.xaml.cs index a5b3b9c..c424bdd 100644 --- a/Main.xaml.cs +++ b/Main.xaml.cs @@ -156,6 +156,10 @@ public static void LogModStatus(ModFile modFile) } Log.Warning("Patching {{{2}}} for {{{0}}} {{{1}}}", modFile.Name, modFile.Version, statusMessage); } + public ModFile GetFailingMod() + { + return ModPage.Mods.Where(x => x.Enabled).First(x => x.PatchStatus == PatchStatus.Patching); ; + } private void MyToggleButton_Checked(object sender, EventArgs e) { foreach (var i in stackPanel.Children) diff --git a/ModLoader.cs b/ModLoader.cs index 17e1dd2..c29c3b0 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -13,6 +13,7 @@ using UndertaleModLib.Models; using ModShardLauncher.Controls; using Serilog; +using ModShardLauncher.Core.Errors; namespace ModShardLauncher { @@ -183,7 +184,7 @@ public static void PatchMods() Msl.ChainDisclaimerRooms(Disclaimers); Msl.CreateMenu(Menus); } - public static bool PatchFile() + public static MSLDiagnostic? PatchFile() { try { @@ -192,26 +193,13 @@ public static bool PatchFile() PatchMods(); // add the new loot related functions if there is any LootUtils.InjectLootScripts(); - return true; + return null; } catch (Exception ex) { - string extraInformation = ""; - object? fileName = null; - object? patchingWay = null; - if (ex.Data.Contains("fileName")) - { - fileName = ex.Data["fileName"]; - extraInformation += " in file {{{0}}}"; - } - if (ex.Data.Contains("patchingWay")) - { - patchingWay = ex.Data["patchingWay"]; - extraInformation += " while patching by {{{1}}}"; - } - - Log.Error(ex, "Something went wrong" + extraInformation, fileName, patchingWay); - return false; + MSLDiagnostic diag = new(ex, Main.Instance.GetFailingMod()); + diag.ToLog(); + return diag; } } } diff --git a/ModShardLauncher.csproj b/ModShardLauncher.csproj index 6601e14..7c7930d 100644 --- a/ModShardLauncher.csproj +++ b/ModShardLauncher.csproj @@ -21,7 +21,7 @@ - + From 53f2e1eb62f07805c1e7f5ce3316021a97d59e0a Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 21 Sep 2025 21:38:03 +0200 Subject: [PATCH 10/11] [Major] improves the error dialog window --- Controls/ModInfos.xaml.cs | 5 +- Core/Errors/MSLDiagnostic.cs | 38 ++++++++- Core/UI/ErrorMessageDialog.cs | 145 ++++++++++++++++++++++++++++++++++ Main.xaml.cs | 3 +- ModShardLauncher.csproj | 1 + 5 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 Core/UI/ErrorMessageDialog.cs diff --git a/Controls/ModInfos.xaml.cs b/Controls/ModInfos.xaml.cs index 2dfca67..b3213bb 100644 --- a/Controls/ModInfos.xaml.cs +++ b/Controls/ModInfos.xaml.cs @@ -7,6 +7,7 @@ using System.Windows; using System.Windows.Controls; using ModShardLauncher.Core.Errors; +using ModShardLauncher.Core.UI; using ModShardLauncher.Mods; using Serilog; @@ -59,9 +60,7 @@ private async void Save_Click(object sender, EventArgs e) { Main.Instance.LogModListStatus(); Log.Information("Failed patching vanilla"); - string messageBoxText = "Do you want to save changes?"; - string caption = diag.Title(); - MessageBox.Show(messageBoxText, caption); + ErrorMessageDialog.Show(diag.Title(), diag.MessageDialog(), Main.Instance.logPath); } // reload the data diff --git a/Core/Errors/MSLDiagnostic.cs b/Core/Errors/MSLDiagnostic.cs index 87f1435..388584e 100644 --- a/Core/Errors/MSLDiagnostic.cs +++ b/Core/Errors/MSLDiagnostic.cs @@ -1,4 +1,6 @@ using System; +using System.Drawing; +using System.Windows.Forms; using Serilog; namespace ModShardLauncher.Core.Errors @@ -39,7 +41,41 @@ public void ToLog() } public string Title() { - return $"{ModName} failed"; + return $"Patching {ModName} failed"; + } + public string MessageDialog() + { + RichTextBox message = new(); + + message.SelectionColor = Color.Black; + message.AppendText("An error was encountered while patching the mod "); + message.SelectionColor = Color.Blue; + message.AppendText(ModName); + message.SelectionColor = Color.Black; + message.AppendText(":\n"); + + if (FileName is not null) + { + message.SelectionColor = Color.Black; + message.AppendText("In file "); + message.SelectionColor = Color.Blue; + message.AppendText(FileName); + } + if (PatchingMethod is not null) + { + message.SelectionColor = Color.Black; + message.AppendText(" by "); + message.SelectionColor = Color.Blue; + message.AppendText(PatchingMethod); + message.SelectionColor = Color.Black; + message.AppendText(":\n"); + } + + message.SelectionColor = Color.Black; + message.AppendText("\n"); + message.SelectionFont = new Font(message.Font, FontStyle.Bold); + message.AppendText(exception.ToString()); + return message.Rtf; } } } \ No newline at end of file diff --git a/Core/UI/ErrorMessageDialog.cs b/Core/UI/ErrorMessageDialog.cs new file mode 100644 index 0000000..e437b37 --- /dev/null +++ b/Core/UI/ErrorMessageDialog.cs @@ -0,0 +1,145 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using Serilog; + +namespace ModShardLauncher.Core.UI +{ + public class ErrorMessageDialog : Form + { + private readonly RichTextBox messageTextBox; + public DialogResult Result { get; private set; } + private readonly TableLayoutPanel panel; + private readonly Button okButton; + private readonly Button cpyButton; + private readonly Button logButton; + public ErrorMessageDialog(string title, string message, string? logPath = null) + { + panel = new(); + messageTextBox = new RichTextBox(); + okButton = new Button(); + cpyButton = new Button(); + logButton = new Button(); + + InitializeComponent(); + SetupDialog(title, message, logPath); + } + private void InitializeComponent() + { + SuspendLayout(); + + Text = string.Empty; + Size = new Size(450, 200); + StartPosition = FormStartPosition.CenterParent; + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + ShowIcon = false; + ShowInTaskbar = false; + Dock = DockStyle.Fill; + + // panel + panel.Anchor = AnchorStyles.Top; + panel.Size = new Size(300, 150); + panel.BorderStyle = BorderStyle.None; + panel.ColumnCount = 3; + panel.RowCount = 2; + panel.RowStyles.Add(new RowStyle(SizeType.AutoSize)); + panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 44)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.Dock = DockStyle.Fill; + + // Message TextBox + messageTextBox.ReadOnly = true; + messageTextBox.BorderStyle = BorderStyle.None; + messageTextBox.BackColor = BackColor; + messageTextBox.ScrollBars = RichTextBoxScrollBars.Vertical; + messageTextBox.TabStop = false; + + // ok button + okButton.Text = "OK"; + okButton.Size = new Size(75, 23); + okButton.DialogResult = DialogResult.OK; + okButton.Click += (s, e) => { Result = DialogResult.OK; Close(); }; + + // copy button + cpyButton.Text = "Copy error"; + cpyButton.Size = new Size(100, 23); + cpyButton.Click += CopyButton_Click; + + // log button + logButton.Text = "Open Log Folder"; + logButton.Size = new Size(120, 23); + logButton.Click += LogButton_Click; + + panel.Controls.Add(messageTextBox, 0, 0); + panel.SetColumnSpan(messageTextBox, 3); + panel.Controls.Add(okButton, 0, 1); + panel.Controls.Add(cpyButton, 1, 1); + panel.Controls.Add(logButton, 2, 1); + + Controls.Add(panel); + + // Set default button and cancel button + AcceptButton = okButton; + CancelButton = okButton; + + ResumeLayout(); + } + private void SetupDialog(string title, string message, string? logPath = null) + { + Text = title; + messageTextBox.Rtf = message; + messageTextBox.AutoSize = true; + + Size size = messageTextBox.GetPreferredSize(new Size(800, 0)) + new Size(0, 50); + int newHeight = size.Height + 100; + int newWidth = Math.Max(450, size.Width + 50); + + messageTextBox.Size = new Size(size.Width, size.Height); + Size = new Size(newWidth, newHeight); + + // Hide log button if no path provided + if (string.IsNullOrEmpty(logPath)) + { + logButton.Visible = false; + okButton.Location = new Point(340, 125); // Center the OK button + } + else + { + logButton.Tag = logPath; // Store the log path + } + } + private void LogButton_Click(object? sender, EventArgs e) + { + try + { + string? logPath = logButton.Tag?.ToString(); + if (!string.IsNullOrEmpty(logPath)) + { + System.Diagnostics.Process.Start("explorer.exe", logPath); + } + } + catch (Exception ex) + { + MessageBox.Show($"Could not open log folder: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + // nifty trick: use Retry to indicate log button was clicked + Result = DialogResult.Retry; + Close(); + } + private void CopyButton_Click(object? sender, EventArgs e) + { + Clipboard.SetText(messageTextBox.Text); + } + public static DialogResult Show(string title, string message, string? logPath = null) + { + using var dialog = new ErrorMessageDialog(title, message, logPath); + dialog.ShowDialog(); + return dialog.Result; + } + } +} \ No newline at end of file diff --git a/Main.xaml.cs b/Main.xaml.cs index c424bdd..6b4360e 100644 --- a/Main.xaml.cs +++ b/Main.xaml.cs @@ -38,6 +38,7 @@ public partial class Main : Window public static IntPtr handle; public string mslVersion; public string utmtlibVersion; + public readonly string logPath = "logs"; private const double DefaultWidth = 960; // Исходная ширина private const double DefaultHeight = 800; // Исходная высота private const double AspectRatio = DefaultWidth / DefaultHeight; // Соотношение сторон @@ -61,7 +62,7 @@ public Main() // create File and Console (controlledby a switch) sinks LoggerConfiguration logger = new LoggerConfiguration() .MinimumLevel.Debug() - .WriteTo.File(string.Format("logs/log_{0}.txt", DateTime.Now.ToString("yyyyMMdd_HHmm"))) + .WriteTo.File(string.Format("{0}/log_{1}.txt", logPath, DateTime.Now.ToString("yyyyMMdd_HHmm"))) .WriteTo.Logger(log => log .MinimumLevel.ControlledBy(lls) .WriteTo.Console() diff --git a/ModShardLauncher.csproj b/ModShardLauncher.csproj index 7c7930d..df3a24c 100644 --- a/ModShardLauncher.csproj +++ b/ModShardLauncher.csproj @@ -40,6 +40,7 @@ + From 5225364c4a7e3af5cf6e6abdf58bc9d21429dcef Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 21 Sep 2025 22:18:30 +0200 Subject: [PATCH 11/11] [Minor] adding english translation --- ModLoader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ModLoader.cs b/ModLoader.cs index c29c3b0..c79d6eb 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -131,6 +131,7 @@ public static void LoadFiles() if (modType == null) { + // MessageBox.Show("Loading error: " + assembly.GetName().Name + " This Mod need a Mod class"); MessageBox.Show("加载错误: " + assembly.GetName().Name + " 此Mod需要一个Mod类"); continue; }