Pathoschild / SMAPI

The modding API for Stardew Valley.
https://smapi.io/
GNU Lesser General Public License v3.0
1.71k stars 258 forks source link

Private assemblies via custom AssemblyLoadContext #915

Closed Shockah closed 2 days ago

Shockah commented 9 months ago

Hey @Pathoschild. This PR implements marking specific assemblies used by mods as "private", which forbids other mods from using them directly, but allows multiple assemblies named the same to co-exist. This is mostly useful for mods consuming the same Nuget packages but at different versions. Before this PR, such mods could potentially fail to load if the older library loaded first or if the newer library had breaking changes. The developers of said mods can now specify the assemblies coming from these Nuget packages under a new PrivateAssemblies field in the manifest.json.

The PR also adds validations for this new manifest key. If a mod does not reference an assembly listed under PrivateAssemblies, a warning will be logged. Also, if a content pack lists any assembly under that field, a warning will be logged too (as this PR only makes sense for SMAPI mods, not content packs). The unreferenced private assembly warning can be disabled for a given assembly by suffixing the name with a ! - this is only really useful if the assembly is not used directly in the mod - so in the rare case of loading the assembly via reflection.

By default, this change is purely additive and opt-in, so there should be no breaking changes. The loading code changed from using Assembly methods to AssemblyLoadContext ones, but it's pretty much the same change my other PR #891 did, which means stuff like mod rewriting and Edit-and-Continue are still working. Types from private assemblies should still be usable via Pintail-powered APIs. Direct references to such types from other mods will throw an exception at runtime, but that's to be expected.

This PR makes my other PR #891 obsolete, so I will be closing it.

Pathoschild commented 9 months ago

Thanks for the pull request!

I tentatively set this to SMAPI 4.1.0 since this'll be backwards-compatible, so I'll take a closer look when I'm working on that release. But my first impressions based on a quick review:

spacechase0 commented 8 months ago

This would also be useful for SpaceCore using Miniscript's nuget package without scripting function registration co-existing with the ones Farmtronics does 👀

Pathoschild commented 1 month ago

I made a few changes.

There's two things left I'd want to look into:

Pathoschild commented 2 days ago

Merged into develop for the upcoming SMAPI 4.1.0. Thanks for the help!