HashStrings passed str.Length (a char count) as the byte count to
MD5.TransformBlock, so for any non-ASCII string only a truncated prefix
of the UTF-8 bytes was hashed. Capture the byte array and use its Length.
ConfigFile documents its public methods as thread-safe, but GetEnumerator
returned the live Dictionary enumerator with no lock, so a concurrent
Bind/Reload could invalidate it mid-foreach. Snapshot under _ioLock instead.
typeof(byte) was registered twice in the TypeConverters initializer; the
second entry silently overwrote the first. Keep the one grouped with the
other integral types.
* Don't abort startup when the config file can't be written
ConfigFile.Save opens the file for writing with no exception handling and is invoked automatically via SaveOnConfigSet while settings are bound during startup, before logging is initialized. A read-only or otherwise unwritable config file (a read-only install directory, a file locked by another process or antivirus) therefore throws UnauthorizedAccessException out of the early startup path and shows the Failed to start BepInEx dialog.
BaseChainloader.Execute invoked the Finished event inside the same
try/catch that reports plugin-loading failures, so an exception thrown
by a Finished event listener was logged as "Error occurred loading
plugins:" even though it was unrelated to plugin loading.
Move Finished?.Invoke() into its own try/catch with an accurate
message. Control flow is otherwise unchanged: Finished still runs only
after LoadPlugins succeeds, a throwing listener is still caught, and
"Chainloader startup complete" is still logged afterwards.
Fixes#842
The chainloader collected both not-installed dependencies and
installed-but-incompatible-version dependencies into one list and
reported them all as "missing dependencies", which is confusing when
the plugin is present but on a version outside the requested range.
Separate the two cases and log distinct, actionable messages: one for
dependencies that are not installed, and one for dependencies present
with an incompatible version (showing the found version and the
required range).
Also expand the BepInDependency(string, string) xmldoc: the version is
a SemVer range, link the range syntax, and warn about the BepInEx 5 ->
6 behaviour change (a bare version was a minimum, now it is exact).
Fixes#779
The new resolver resides in BepInEx.Unity.Core
The resolver is based on multiple heuristics and integrates all workarounds we currently use so this shouldn't be a breaking change
This fixes several issues with loading assemblies. In turn, this commit also removes old Location/CodeBase fixes since now assemblies are resolved automatically correctly.
Additionally, integrate the mono loader into preloading which fixes assembly location resolving
To simplify versioning and configuration:
* Removed BepInEx.Shared
* Removed BuildInfoAttribute
* Moved shared configuration to Directory.Build.props
* Refactored to use VersionSuffix and SourceRevisionId for embedding BE and commit hash info
* Enabled debug info embedding