diff --git a/RogueLibsCore/Hooks/HookController.cs b/RogueLibsCore/Hooks/HookController.cs index b6d9c096f..6e94ab54d 100644 --- a/RogueLibsCore/Hooks/HookController.cs +++ b/RogueLibsCore/Hooks/HookController.cs @@ -26,8 +26,7 @@ public void AddHook(IHook hook) if (hook is null) throw new ArgumentNullException(nameof(hook)); hook.Instance = Instance; hooks.Add(hook); - if (hook is IDoUpdate) RogueLibsPlugin.updateList.Add(hook); - if (hook is IDoFixedUpdate) RogueLibsPlugin.fixedUpdateList.Add(hook); + HandleHookAddition(hook); hook.Initialize(); } /// @@ -40,8 +39,7 @@ public THook AddHook() { THook hook = new THook { Instance = Instance }; hooks.Add(hook); - if (hook is IDoUpdate) RogueLibsPlugin.updateList.Add(hook); - if (hook is IDoFixedUpdate) RogueLibsPlugin.fixedUpdateList.Add(hook); + HandleHookAddition(hook); hook.Initialize(); return hook; } @@ -52,13 +50,33 @@ void IHookController.AddHook(IHook hook) else throw new ArgumentException("Invalid type!", nameof(hook)); } + private static void HandleHookAddition(IHook hook) + { + if (hook is IDoUpdate) RogueLibsPlugin.updateList.Add(hook); + if (hook is IDoFixedUpdate) RogueLibsPlugin.fixedUpdateList.Add(hook); + } + private static void HandleHookRemoval(IHook hook) + { + if (hook is IDoUpdate) + { + if (RogueLibsPlugin.updatingHooks) + RogueLibsPlugin.removeFromUpdateList.Add(hook); + else RogueLibsPlugin.updateList.Remove(hook); + } + if (hook is IDoFixedUpdate) + { + if (RogueLibsPlugin.fixedUpdatingHooks) + RogueLibsPlugin.removeFromFixedUpdateList.Add(hook); + else RogueLibsPlugin.fixedUpdateList.Remove(hook); + } + } + /// public bool RemoveHook(IHook hook) { if (hooks.Remove(hook)) { - if (hook is IDoUpdate) RogueLibsPlugin.updateList.Remove(hook); - if (hook is IDoFixedUpdate) RogueLibsPlugin.fixedUpdateList.Remove(hook); + HandleHookRemoval(hook); return true; } return false; @@ -74,8 +92,7 @@ public bool RemoveHook() if (index is -1) return false; IHook hook = hooks[index]; hooks.RemoveAt(index); - if (hook is IDoUpdate) RogueLibsPlugin.updateList.Remove(hook); - if (hook is IDoFixedUpdate) RogueLibsPlugin.fixedUpdateList.Remove(hook); + HandleHookRemoval(hook); return true; } bool IHookController.RemoveHook(IHook hook) @@ -83,8 +100,7 @@ bool IHookController.RemoveHook(IHook hook) int index = hooks.FindIndex(h => h == hook); if (index is -1) return false; hooks.RemoveAt(index); - if (hook is IDoUpdate) RogueLibsPlugin.updateList.Remove(hook); - if (hook is IDoFixedUpdate) RogueLibsPlugin.fixedUpdateList.Remove(hook); + HandleHookRemoval(hook); return true; } @@ -109,18 +125,18 @@ public THook[] GetHooks() public void Dispose() { - for (int i = 0, count = hooks.Count; i < count; i++) + try { - IHook hook = hooks[i]; - try + for (int i = 0, count = hooks.Count; i < count; i++) { - // ReSharper disable once SuspiciousTypeConversion.Global + IHook hook = hooks[i]; + HandleHookRemoval(hook); (hook as IDisposable)?.Dispose(); } - catch (Exception e) - { - RogueFramework.LogError(e, nameof(IDisposable.Dispose), hook, Instance); - } + } + finally + { + hooks.Clear(); } } diff --git a/RogueLibsCore/Patches/Patches_Misc.cs b/RogueLibsCore/Patches/Patches_Misc.cs index 745dde4f5..0c4891d46 100644 --- a/RogueLibsCore/Patches/Patches_Misc.cs +++ b/RogueLibsCore/Patches/Patches_Misc.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization.Formatters; using UnityEngine; using UnityEngine.UI; @@ -69,10 +70,14 @@ public static bool NameDB_GetName(string? myName, string type, out string? __res return __result is null; } + internal static bool updatingHooks; internal static readonly List updateList = new List(); + internal static readonly List removeFromUpdateList = new List(); + internal static bool fixedUpdatingHooks; internal static readonly List fixedUpdateList = new List(); + internal static readonly List removeFromFixedUpdateList = new List(); - private static bool IsUpdateHookValid(IHook hook) + private static bool IsUpdateHookInvalid(IHook hook) { static bool IsInvalid(InvItem item) { @@ -97,30 +102,48 @@ static bool IsInvalid(InvItem item) } public static void Updater_Update() { - for (int i = 0, count = updateList.Count; i < count; i++) + try { - IHook hook = updateList[i]; - if (IsUpdateHookValid(hook)) + updatingHooks = true; + for (int i = 0, count = updateList.Count; i < count; i++) { - updateList.Remove(hook); - i--; - continue; + IHook hook = updateList[i]; + if (IsUpdateHookInvalid(hook)) + removeFromUpdateList.Add(hook); + else ((IDoUpdate)hook).Update(); + } + } + finally + { + updatingHooks = false; + if (removeFromUpdateList.Count > 0) + { + updateList.RemoveAll(removeFromUpdateList.Contains); + removeFromUpdateList.Clear(); } - ((IDoUpdate)hook).Update(); } } public static void Updater_FixedUpdate() { - for (int i = 0, count = fixedUpdateList.Count; i < count; i++) + try + { + fixedUpdatingHooks = true; + for (int i = 0, count = fixedUpdateList.Count; i < count; i++) + { + IHook hook = fixedUpdateList[i]; + if (IsUpdateHookInvalid(hook)) + removeFromFixedUpdateList.Add(hook); + else ((IDoFixedUpdate)hook).FixedUpdate(); + } + } + finally { - IHook hook = fixedUpdateList[i]; - if (IsUpdateHookValid(hook)) + fixedUpdatingHooks = false; + if (removeFromFixedUpdateList.Count > 0) { - fixedUpdateList.Remove(hook); - i--; - continue; + fixedUpdateList.RemoveAll(removeFromFixedUpdateList.Contains); + removeFromFixedUpdateList.Clear(); } - ((IDoFixedUpdate)hook).FixedUpdate(); } }