using System.Collections.Generic; 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(); /// Generates proxy classes to access mod APIs through an arbitrary interface. private readonly InterfaceProxyFactory ProxyFactory; /********* ** Public methods *********/ /// Construct an instance. /// The mod using this instance. /// The underlying mod registry. /// Generates proxy classes to access mod APIs through an arbitrary interface. /// Encapsulates monitoring and logging for the mod. public ModRegistryHelper(IModMetadata mod, ModRegistry registry, InterfaceProxyFactory proxyFactory, IMonitor monitor) : base(mod) { this.Registry = registry; this.ProxyFactory = proxyFactory; 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}."); 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 return api is TInterface castApi ? castApi : this.ProxyFactory.CreateProxy(api, sourceModID: this.ModID, targetModID: uniqueID); } } }