Skip to content
This repository has been archived by the owner on Dec 30, 2024. It is now read-only.

Commit

Permalink
🚑️ Fix ArgumentOutOfRangeException when removing hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
Chasmical committed Jun 26, 2022
1 parent 34abcd4 commit b7235cf
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 33 deletions.
52 changes: 34 additions & 18 deletions RogueLibsCore/Hooks/HookController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public void AddHook(IHook<T> 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();
}
/// <summary>
Expand All @@ -40,8 +39,7 @@ public THook AddHook<THook>()
{
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;
}
Expand All @@ -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);
}
}

/// <inheritdoc/>
public bool RemoveHook(IHook<T> 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;
Expand All @@ -74,17 +92,15 @@ public bool RemoveHook<THook>()
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)
{
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;
}

Expand All @@ -109,18 +125,18 @@ public THook[] GetHooks<THook>()

public void Dispose()
{
for (int i = 0, count = hooks.Count; i < count; i++)
try
{
IHook<T> hook = hooks[i];
try
for (int i = 0, count = hooks.Count; i < count; i++)
{
// ReSharper disable once SuspiciousTypeConversion.Global
IHook<T> hook = hooks[i];
HandleHookRemoval(hook);
(hook as IDisposable)?.Dispose();
}
catch (Exception e)
{
RogueFramework.LogError(e, nameof(IDisposable.Dispose), hook, Instance);
}
}
finally
{
hooks.Clear();
}
}

Expand Down
53 changes: 38 additions & 15 deletions RogueLibsCore/Patches/Patches_Misc.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using UnityEngine;
using UnityEngine.UI;

Expand Down Expand Up @@ -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<IHook> updateList = new List<IHook>();
internal static readonly List<IHook> removeFromUpdateList = new List<IHook>();
internal static bool fixedUpdatingHooks;
internal static readonly List<IHook> fixedUpdateList = new List<IHook>();
internal static readonly List<IHook> removeFromFixedUpdateList = new List<IHook>();

private static bool IsUpdateHookValid(IHook hook)
private static bool IsUpdateHookInvalid(IHook hook)
{
static bool IsInvalid(InvItem item)
{
Expand All @@ -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();
}
}

Expand Down

0 comments on commit b7235cf

Please sign in to comment.