diff --git a/UndertaleModLib/Decompiler/Decompiler.cs b/UndertaleModLib/Decompiler/Decompiler.cs index 6453f6bb0..0322d96be 100644 --- a/UndertaleModLib/Decompiler/Decompiler.cs +++ b/UndertaleModLib/Decompiler/Decompiler.cs @@ -75,21 +75,32 @@ public DecompileContext(GlobalDecompileContext globalContext, UndertaleCode code if (code.ParentEntry != null) throw new InvalidOperationException("This code block represents a function nested inside " + code.ParentEntry.Name + " - decompile that instead"); - if (computeObject && globalContext.Data != null) + if (computeObject && globalContext.Data is not null) { // TODO: This is expensive, move it somewhere else as a dictionary // and have it update when events/objects are modified. - foreach (var obj in globalContext.Data.GameObjects) - foreach (var event_list in obj.Events) - foreach (var subevent in event_list) - foreach (var ev in subevent.Actions) - if (ev.CodeId == code) - { - Object = obj; - goto LoopEnd; - } + + // Currently using for loops on purpose, as foreach has memory issues due to IEnumerable + for (int i = 0; i < globalContext.Data.GameObjects.Count; i++) + { + UndertaleGameObject obj = globalContext.Data.GameObjects[i]; + for (int j = 0; j < obj.Events.Count; j++) + { + var eventList = obj.Events[j]; + for (int k = 0; k < eventList.Count; k++) + { + UndertaleGameObject.Event subEvent = eventList[k]; + for (int l = 0; l < subEvent.Actions.Count; l++) + { + UndertaleGameObject.EventAction ev = subEvent.Actions[l]; + if (ev.CodeId != code) continue; + Object = obj; + return; + } + } + } + } } - LoopEnd: return; } #region Struct management @@ -3464,7 +3475,7 @@ public static Dictionary> ComputeReverseDominators(Dictionary Block b = blockList[i]; - IEnumerable e; + Block[] e; if (b.conditionalExit) { reverseUse2[0] = b.nextBlockTrue; @@ -4043,7 +4054,7 @@ public static void BuildSubFunctionCache(UndertaleData data) { throw new TimeoutException("The building cache process hung.\n" + "The function code entries that didn't manage to decompile:\n" + - String.Join('\n', processingCodeList.Keys) + "\n\n" + + String.Join('\n', processingCodeList.Keys) + "\n\n" + "You should save the game data (if it's necessary) and re-open the app.\n"); } } diff --git a/UndertaleModLib/Util/DebugUtil.cs b/UndertaleModLib/Util/DebugUtil.cs index 615b07913..2567a9014 100644 --- a/UndertaleModLib/Util/DebugUtil.cs +++ b/UndertaleModLib/Util/DebugUtil.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -8,6 +9,14 @@ namespace UndertaleModLib.Util { public class DebugUtil { + + /// + /// Asserts that a specified condition is true. + /// + /// The condition to assert for. + /// The message to use if the assertion fails. + /// Gets thrown if the assertion fails. + [Conditional("DEBUG")] public static void Assert(bool expr, string msg = "Unknown error.") { if (expr) diff --git a/UndertaleModLib/Util/DictionaryExtensions.cs b/UndertaleModLib/Util/DictionaryExtensions.cs deleted file mode 100644 index 5eb520ff4..000000000 --- a/UndertaleModLib/Util/DictionaryExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace UndertaleModLib.Util -{ - public static class DictionaryExtensions - { - public static TValue GetValueOrDefault(this Dictionary dictionary, TKey key, TValue defaultValue = default(TValue)) - { - if (dictionary == null) { throw new ArgumentNullException(nameof(dictionary)); } - if (key == null) { throw new ArgumentNullException(nameof(key)); } - - TValue value; - return dictionary.TryGetValue(key, out value) ? value : defaultValue; - } - } -}