using System.Collections.Generic; using Nanoray.Pintail; using StardewModdingAPI.Framework.Reflection; namespace StardewModdingAPI.Framework.ModHelpers { /// Provides metadata about installed mods. internal class ModRegistryHelper : BaseHelper, IModRegistry { /********* ** Fields *********/ /// The underlying mod registry. private readonly ModRegistry Registry; /// Encapsulates monitoring and logging for the mod. private readonly IMonitor Monitor; /// The mod IDs for APIs accessed by this instanced. private readonly HashSet AccessedModApis = new HashSet(); /// Generates proxy classes to access mod APIs through an arbitrary interface. private readonly IProxyManager ProxyManager; /********* ** Public methods *********/ /// Construct an instance. /// The unique ID of the relevant mod. /// The underlying mod registry. /// Generates proxy classes to access mod APIs through an arbitrary interface. /// Encapsulates monitoring and logging for the mod. public ModRegistryHelper(string modID, ModRegistry registry, IProxyManager proxyManager, IMonitor monitor) : base(modID) { this.Registry = registry; this.ProxyManager = proxyManager; this.Monitor = monitor; } /// public IEnumerable GetAll() { return this.Registry.GetAll(); } /// public IModInfo Get(string uniqueID) { return this.Registry.Get(uniqueID); } /// public bool IsLoaded(string uniqueID) { return this.Registry.Get(uniqueID) != null; } /// public object GetApi(string uniqueID) { // validate ready if (!this.Registry.AreAllModsInitialized) { this.Monitor.Log("Tried to access a mod-provided API before all mods were initialized.", LogLevel.Error); return null; } // get raw API IModMetadata mod = this.Registry.Get(uniqueID); if (mod?.Api != null && this.AccessedModApis.Add(mod.Manifest.UniqueID)) this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}.", LogLevel.Trace); return mod?.Api; } /// public TInterface GetApi(string uniqueID) where TInterface : class { // get raw API object api = this.GetApi(uniqueID); if (api == null) return null; // validate mapping if (!typeof(TInterface).IsInterface) { this.Monitor.Log($"Tried to map a mod-provided API to class '{typeof(TInterface).FullName}'; must be a public interface.", LogLevel.Error); return null; } if (!typeof(TInterface).IsPublic) { this.Monitor.Log($"Tried to map a mod-provided API to non-public interface '{typeof(TInterface).FullName}'; must be a public interface.", LogLevel.Error); return null; } // get API of type if (api is TInterface castApi) return castApi; return this.ProxyManager.ObtainProxy(api, this.ModID, uniqueID); } } }