From e8da8fff5163eacd6ae7870eaa8c7dbc8285e3e7 Mon Sep 17 00:00:00 2001 From: Khloe Leclair Date: Mon, 26 Sep 2022 15:18:36 -0400 Subject: Initial work on a way for mods to return specific API instances to specific mods. --- .../Framework/ModHelpers/ModRegistryHelper.cs | 53 +++++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index 348ba225..9ad3e3ae 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -1,5 +1,7 @@ +using System; using System.Collections.Generic; using StardewModdingAPI.Framework.Reflection; +using StardewModdingAPI.Internal; namespace StardewModdingAPI.Framework.ModHelpers { @@ -15,8 +17,8 @@ namespace StardewModdingAPI.Framework.ModHelpers /// 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(); + /// The APIs accessed by this instance. + private readonly Dictionary AccessedModApis = new(); /// Generates proxy classes to access mod APIs through an arbitrary interface. private readonly IInterfaceProxyFactory ProxyFactory; @@ -66,11 +68,50 @@ namespace StardewModdingAPI.Framework.ModHelpers return null; } - // get raw API + // get our cached API if one is available 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; + if (mod == null) + return null; + + if (this.AccessedModApis.ContainsKey(mod.Manifest.UniqueID)) + { + return this.AccessedModApis[mod.Manifest.UniqueID]; + } + + object? api; + + // safely request a specific API instance + try + { + api = mod.Mod?.GetApi(this.Mod.Manifest); + if (api != null && !api.GetType().IsPublic) + { + api = null; + this.Monitor.Log($"{mod.DisplayName} provided a specific API instance with a non-public type. This isn't currently supported, so the specific API won't be available to the requesting mod.", LogLevel.Warn); + } + + if (api != null) + this.Monitor.Log($"Accessed specific mod-provided API ({api.GetType().FullName}) for {mod.DisplayName}."); + } + catch (Exception ex) + { + this.Monitor.Log($"Failed loading specific mod-provided API for {mod.DisplayName}. Integrations with other mods may not work. Error: {ex.GetLogSummary()}", LogLevel.Error); + api = null; + } + + // fall back to the generic API instance + if (api == null) + { + api = mod.Api; + if (api != null) + { + this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}."); + } + } + + // cache the API instance and return it + this.AccessedModApis[mod.Manifest.UniqueID] = api; + return api; } /// -- cgit From a565ac9405a95d24f7cf945228935107e91bb89f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 8 Oct 2022 19:59:21 -0400 Subject: make GetApi methods mutually exclusive & improve docs --- .../Framework/ModHelpers/ModRegistryHelper.cs | 56 ++++++++++------------ 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index 9ad3e3ae..8cc73481 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -68,49 +68,43 @@ namespace StardewModdingAPI.Framework.ModHelpers return null; } - // get our cached API if one is available + // get the target mod IModMetadata? mod = this.Registry.Get(uniqueID); if (mod == null) return null; - if (this.AccessedModApis.ContainsKey(mod.Manifest.UniqueID)) + // fetch API + if (!this.AccessedModApis.TryGetValue(mod.Manifest.UniqueID, out object? api)) { - return this.AccessedModApis[mod.Manifest.UniqueID]; - } - - object? api; + // if the target has a global API, this is mutually exclusive with per-mod APIs + if (mod.Api != null) + api = mod.Api; - // safely request a specific API instance - try - { - api = mod.Mod?.GetApi(this.Mod.Manifest); - if (api != null && !api.GetType().IsPublic) + // else try to get a per-mod API + else { - api = null; - this.Monitor.Log($"{mod.DisplayName} provided a specific API instance with a non-public type. This isn't currently supported, so the specific API won't be available to the requesting mod.", LogLevel.Warn); + try + { + api = mod.Mod?.GetApi(this.Mod.Manifest); + if (api != null && !api.GetType().IsPublic) + { + api = null; + this.Monitor.Log($"{mod.DisplayName} provides a per-mod API instance with a non-public type. This isn't currently supported, so the API won't be available to other mods.", LogLevel.Warn); + } + } + catch (Exception ex) + { + this.Monitor.Log($"Failed loading the per-mod API instance from {mod.DisplayName}. Integrations with other mods may not work. Error: {ex.GetLogSummary()}", LogLevel.Error); + api = null; + } } + // cache & log API access + this.AccessedModApis[mod.Manifest.UniqueID] = api; if (api != null) - this.Monitor.Log($"Accessed specific mod-provided API ({api.GetType().FullName}) for {mod.DisplayName}."); - } - catch (Exception ex) - { - this.Monitor.Log($"Failed loading specific mod-provided API for {mod.DisplayName}. Integrations with other mods may not work. Error: {ex.GetLogSummary()}", LogLevel.Error); - api = null; - } - - // fall back to the generic API instance - if (api == null) - { - api = mod.Api; - if (api != null) - { - this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}."); - } + this.Monitor.Log($"Accessed mod-provided API ({api.GetType().FullName}) for {mod.DisplayName}."); } - // cache the API instance and return it - this.AccessedModApis[mod.Manifest.UniqueID] = api; return api; } -- cgit From 8d6670cfc8abf7e71197d2f621314fb04a0543b8 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 8 Oct 2022 20:33:01 -0400 Subject: pass mod info to GetApi instead --- src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index 8cc73481..93edd597 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -85,7 +85,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { try { - api = mod.Mod?.GetApi(this.Mod.Manifest); + api = mod.Mod?.GetApi(this.Mod); if (api != null && !api.GetType().IsPublic) { api = null; -- cgit