using System; using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; namespace ShrinkModFramework { /// 默认模组组件根;目录变更只提交完整的新组合,失败时由 Host 恢复旧组合。 public static class ShrinkModCordisRuntime { private static ShrinkModContextHost _host; public static bool IsInitialized => _host != null; public static ShrinkModContextHost Host => _host ?? throw new InvalidOperationException( "ShrinkModCordisRuntime has not been initialized."); public static IReadOnlyDictionary Mods => _host?.Mods ?? EmptyMods; private static readonly IReadOnlyDictionary EmptyMods = new Dictionary(); public static async UniTask> ApplyDiscoveredAsync( ShrinkModFrameworkSettings settings = null, IEnumerable authorizedDllPaths = null) { settings ??= ShrinkModFrameworkSettings.Instance; var verboseLogging = settings == null || settings.verboseLogging; if (_host == null) { _host = new ShrinkModContextHost( settings == null || settings.enableHarmonyPatching, verboseLogging); } var revisionState = ShrinkExternalModAssemblyLoader.CaptureState(); ShrinkModNetworkManager.Configure(settings == null || settings.enableNetworkSync, verboseLogging); try { var authorizedPaths = authorizedDllPaths?.ToArray() ?? Array.Empty(); var sources = ShrinkModComponentDiscovery.Discover( settings, verboseLogging, authorizedPaths); await _host.ApplyAsync(sources); } catch { // DLL revision discovery is part of the same composition transaction: // a failing replacement must not make the failed assembly current. ShrinkExternalModAssemblyLoader.RestoreState(revisionState); throw; } if (verboseLogging) UnityEngine.Debug.Log($"[ShrinkModFramework] Cordis 模组组合已提交,共 {_host.Mods.Count} 个。"); return _host.Mods; } public static IReadOnlyShrinkModRegistry GetOrCreateRegistry(string name) => Host.GetOrCreateRegistry(name); internal static void ResetForDomainReload() { _host = null; } internal static void ResetForTesting() { if (_host != null) _host.ShutdownAsync().GetAwaiter().GetResult(); _host = null; } } }