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 IInterfaceProxyFactory 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, IInterfaceProxyFactory 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);
}
}
}