Centrifuge
Centrifuge copied to clipboard
Silent catch-all in RuntimePatcher.AutoPatch
Describe the Issue
Use of the function RuntimePatcher.AutoPatch()
is a debugging nightmare for anyone developing mods without realizing what's inside. The silent catch-all (shown below) without logging makes it impossible to track where patch errors are originating from.
https://github.com/Centrifuge-Modding-Framework/Centrifuge/blob/2485670337515b69216e2dd2828ee0fc5b3bd85b/Reactor.API/Runtime/Patching/RuntimePatcher.cs#L43-L53
Possible Solutions
Add Logging
The catch block should at least be changed to below to match the RuntimePatcher.RunTranspilers()
function. This way failures can be logged and viewed.
catch (Exception e)
{
Log.Exception(e);
}
Add Throwing
But ideally, it should be possible to call the RuntimePatcher
functions and allow exceptions to be thrown and handled by the caller.
This could be achieved by overloading the functions with the argument bool throwErrors
, where the default behavior of false
would ensure backwards compatibility with mods that have faulty patches, but ultimately still function as expected.
There are two ways to solve this:
- One way would be to duplicate both function, the new one with extra handling.
- The other would be to create a private sub-function where we pass the assembly, since we still need to be able to use
Assembly.GetCallingAssembly()
. - The solution can't be to overload the only function as
AutoPatch(bool throwErrors = false)
, because that would break binary compatibility with mods using a newer dll version.
Duplicate both functions
Code example
public static void AutoPatch()
{
try
{
HarmonyInstance.PatchAll(Assembly.GetCallingAssembly());
}
catch (Exception e)
{
Log.Exception(e);
}
}
public static void AutoPatch(bool throwErrors)
{
try
{
HarmonyInstance.PatchAll(Assembly.GetCallingAssembly());
}
catch (Exception e)
{
if (throwErrors)
{
throw;
}
else
{
Log.Exception(e);
}
}
}
Pass calling assembly to private function
Code example
private static void AutoPatch(Assembly asm, bool throwErrors)
{
try
{
HarmonyInstance.PatchAll(asm);
}
catch (Exception e)
{
if (throwErrors)
{
throw;
}
else
{
Log.Exception(e);
}
}
}
public static void AutoPatch()
{
AutoPatch(Assembly.GetCallingAssembly(), false);
}
public static void AutoPatch(bool throwErrors)
{
AutoPatch(Assembly.GetCallingAssembly(), throwErrors);
}