BepInEx / BepInEx.ConfigurationManager

Plugin configuration manager for BepInEx
https://www.patreon.com/ManlyMarco
GNU Lesser General Public License v3.0
231 stars 53 forks source link

BepInEx4 reference breaks Assembly.GetTypes() (System.Reflection) #30

Closed Vheos closed 3 years ago

Vheos commented 3 years ago

Phew, it took me over an hour to get to the bottom of this confusing exception... I hope I got it right!

Because the types LegacySettingSearcher and SavedKeyboardShortcut (both in the Obsolete folder) still exist in the code, GetTypes() throws ReflectionTypeLoadException unless the user is consciously using BepIn4Patcher - which isn't shipped with ConfigurationManager (nor with BepInEx 5) and there's no information of such (very conditional, but actual) dependency.

And yes, there are game libraries which actually use GetTypes() in production code - I've stumbled upon this issue in whichever version of AwesomeTechnology's VegetationStudio the game Outward is using.

Obviously, the root of the issue is not the ConfigurationManager, but other libraries using GetTypes() AND using it outside of the try-catch block. Currently, Outward players have to harmony-patch GetTypes() so it ignores missing assemblies (which requires a separate plugin) and even though the patch is conveniently included in the most popular Outward modding tool (SideLoader), it's still somewhat of a dirty, too-far-down-the-road workaround.

Removing ConfigurationManager's obsolete code and the BepIn4Patcher reference won't fix the issue at its source, but it will be at least one step up.

And if that's too risky for BepInEx4 backwards compatibility, there should at least be information that ConfigurationManager requires the BepIn4Patcher in some games (as the users won't know whether their game uses GetTypes() or not).

PS. I'm a huge fan of ConfigurationManager, thank you for your work <3

Vheos commented 3 years ago

Ohhh I've actually missed using BepInEx4 in my search... So it's not just the LegacySettingSearcher, but also SavedKeyboardShortcut (also in the Obsolete directory)

Vheos commented 3 years ago

Ok, I've finally got to forking and building and I can confirm the issue/solution - without any references to BepInEx4, GetTypes() doesn't throw exceptions. There is one line of code in the CollectSettings method referencing the obsolete classes.

ManlyMarco commented 3 years ago

The obsolete API is due to be removed sometime soon but this issue will likely happen with other plugins as well, like runtime editor. It sounds like the game is doing GetTypes on all assemblies, which will throw if any type is not able to be loaded. Ideally you would patch the game code that does this and make it gather types properly (e.g. https://github.com/ManlyMarco/RuntimeUnityEditor/blob/029227feb35f2543944630dd51d662e9b40f6051/RuntimeUnityEditor/Utils/Extensions.cs#L113-L118) so it's not an issue in the future.

ManlyMarco commented 3 years ago

There's a new utility plugin that solves this issue https://github.com/BepInEx/BepInEx.Utility#suppressgettypeserrorspatcher